• 解析android framework下利用app_process来调用java写的命令及示例


    解析android framework下利用app_process来调用java写的命令及示例

     

           在android SDK的framework/base/cmds目录下了,有不少目录,这些目的最终都是build出一个bin文件,再存放到/system/bin目录下,对于C/CPP写的命令,我们还是比较好理解的,都有一个main函数作为入口,但是在cmds目录下还有一些原生代码是java的,比如input、settings,那么这种类型的命令是怎么实现的呢?

          笔者研习了原生的命令实现,写了一个demo,抛砖引玉吧!暂时叫strong吧!我们都知道java写的文件最后都是编译成了class文件,java类里面也有很多接口,在android平台上cmds目录下的各模块的java文件都实现了一个共同的方法,还是叫main(),真是情有独钟啊!当然从技术角度看叫其他名字也是可以的。那我们就简单实现以下这个class吧!如下:

    /*
     * Copyright (C) 2012 The Android Open Source Project
     *
     * Licensed under the Apache License, Version 2.0 (the "License");
     * you may not use this file except in compliance with the License.
     * You may obtain a copy of the License at
     *
     *      http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing, software
     * distributed under the License is distributed on an "AS IS" BASIS,
     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     * See the License for the specific language governing permissions and
     * limitations under the License.
     */
    
    package com.android.commands.strong;
    
    import android.app.ActivityManagerNative;
    import android.app.IActivityManager;
    import android.app.IActivityManager.ContentProviderHolder;
    import android.content.IContentProvider;
    import android.os.Binder;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.os.UserHandle;
    
    public final class strongcmd {
        static final String TAG = "strong";
    
        static String[] mArgs;
        int mNextArg;
        static int value = 0;
    
        public static void main(String[] args) {
        int c;
        
        printUsage();
        System.err.println("Wellcom strong test function!!");               
    
            try {
               new strongcmd().run();
            } catch (Exception e) {
                System.err.println("Unable to run settings command");
            }
        }
    
        public void run() {
    
            try {
               System.err.println("Now strong run() again");
            } catch (Exception e) {
               System.err.println("Now strong run() Exception");        	
            }
    
        }
    
        private String nextArg() {
            if (mNextArg >= mArgs.length) {
                return null;
            }
            String arg = mArgs[mNextArg];
            mNextArg++;
            return arg;
        }
        
        private static void printUsage() {
            System.err.println("usage:  strong -a -b -h");
            System.err.println("'a' is for add");
            System.err.println("-h for help");
        }
    }

    /*****************************************************************************************************/
    声明:本博内容均由http://blog.csdn.net/edsam49原创,转载请注明出处,谢谢!
    /*****************************************************************************************************/

      写好Android.mk,编译好这个文件,会生成strong.jar包,包含这个class。那么,又怎么跟命令挂钩呢?先看看Android.mk,如下:

    # Copyright 2011 The Android Open Source Project
    #
    LOCAL_PATH:= $(call my-dir)
    include $(CLEAR_VARS)
    
    LOCAL_SRC_FILES := $(call all-subdir-java-files)
    LOCAL_MODULE := strong
    LOCAL_MODULE_TAGS := optional
    include $(BUILD_JAVA_LIBRARY)
    
    include $(CLEAR_VARS)
    LOCAL_MODULE := strong
    LOCAL_SRC_FILES := pre_strong
    LOCAL_MODULE_CLASS := EXECUTABLES
    LOCAL_MODULE_TAGS := optional
    include $(BUILD_PREBUILT)

      上一部分是BUILD_JAVA_LIBRARY,关键在下面,利用的是BUILD_PREBUILT,添加一个预编译好的应用程序,我们叫pre_strong,它有可执行的权限,看看它的具体实现吧!

    # Script to start "strong" on the device
    #
    base=/system
    export CLASSPATH=$base/framework/strong.jar
    exec app_process $base/bin com.android.commands.strong.strongcmd "$@"

       首先还是设置好这个java lib的路径,如何再调用app_process来执行,主要是把这个类名要给对,app_process其实也是个命令。在app_process里面,还是一样利用JNI技术,在java ENV里面查找传给app_process的class,找到这个class后再去找main函数接口的field,然后再call这个main接口,这样就call到java里面去了。

         下面简要看看app_process的关键代码吧!

        virtual void onVmCreated(JNIEnv* env)
        {
            if (mClassName == NULL) {
                return; // Zygote. Nothing to do here.
            }
    
            /*
             * This is a little awkward because the JNI FindClass call uses the
             * class loader associated with the native method we're executing in.
             * If called in onStarted (from RuntimeInit.finishInit because we're
             * launching "am", for example), FindClass would see that we're calling
             * from a boot class' native method, and so wouldn't look for the class
             * we're trying to look up in CLASSPATH. Unfortunately it needs to,
             * because the "am" classes are not boot classes.
             *
             * The easiest fix is to call FindClass here, early on before we start
             * executing boot class Java code and thereby deny ourselves access to
             * non-boot classes.
             */
            char* slashClassName = toSlashClassName(mClassName);
            mClass = env->FindClass(slashClassName);
            if (mClass == NULL) {
                ALOGE("ERROR: could not find class '%s'
    ", mClassName);
            }
            free(slashClassName);
    
            mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass));
        }
    
        virtual void onStarted()
        {
            sp<ProcessState> proc = ProcessState::self();
            ALOGV("App process: starting thread pool.
    ");
            proc->startThreadPool();
    
            AndroidRuntime* ar = AndroidRuntime::getRuntime();
            ar->callMain(mClassName, mClass, mArgC, mArgV);
    
            IPCThreadState::self()->stopProcess();
        }
    
    if (className) {
            // Remainder of args get passed to startup class main()
            runtime.mClassName = className;
            runtime.mArgC = argc - i;
            runtime.mArgV = argv + i;
            runtime.start("com.android.internal.os.RuntimeInit",
                    application ? "application" : "tool");
        }

         Android平台提供的app_process,还是相当不错的,比较实用,利用好app_process还是可以写成很多供我们自己开发、测试、定制一些特殊的程序,给开发带来了很大的便利。

     

  • 相关阅读:
    centOS 开机自启动自己的脚本
    python SMTP 发送邮件 阿里企业邮箱、163邮箱 及535错误
    memcach 命令行
    python requests上传文件 tornado 接收文件
    Python memecache
    python Redis
    Slave_SQL_Running: No mysql同步故障解决方法
    mysql 数据库的主从同步
    Centos7 安装mysql5.7.16
    centos python2.6 升级到 python2.7
  • 原文地址:https://www.cnblogs.com/riskyer/p/3310606.html
Copyright © 2020-2023  润新知