ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

android 基于dex的插件化开发

2021-12-20 16:32:09  阅读:196  来源: 互联网

标签:dex 插件 getInstance TAG static so android null


安卓里边可以用DexClassLoader实现动态加载dex文件,通过访问dex文件访问dex中封装的方法,如果dex文件本身还调用了native方法,也就间接实现了runtime调用native方法,这一流程主要包括:构建dex和so文件、在主工程添加动态调用代码、移除dex的module,将dex和so push到手机的指定路径

 

构建dex和so文件

首先在主工程里边新建一个名为testdepence的module,新建一个add类,在add类里边我们创建一个单例方法和一个native方法

public class Add {
    private final static String TAG = "Add";
    private static Add add = null;
    static {
        System.loadLibrary("anclivejni");
    }

    public static Add getInstance(){
        Log.d(TAG, "getInstance: ");
        if (add == null){
            add = new Add();
        }
        return add;
    }
    
    public native void init(byte[] data);


}

然后新建jni.cpp,实现init方法,这里我们就只是打印一个log


#define TAG "SXF"
#define LOG(...) __android_log_print(ANDROID_LOG_DEBUG,TAG,__VA_ARGS__)

extern "C" JNIEXPORT void JNICALL Java_com_example_testdepence_Add_init(JNIEnv * env, jobject thiz ,jbyteArray array) { LOG("call init from native"); // TODO: implement init() }

然后在gradle task里边选择 assembleRelease,运行,在testdepence module outputs/aar下会生成一个aar文件,把它的后缀改成zip,解压,得到classes.jar和so文件,然后用/your sdk dir/build-tools/plarform id下的dx工具将jar转换为dex文件,就ok了

## 在主工程添加动态调用代码

新建一个DynamicLoader类,添加使用DexClassLoader反射调用dex文件的代码

public class DynamicLoader {
    private final static String TAG = "DanymicLoader";
    private static Object handle;
    /**
     * 加载dex文件中的class,并调用其中的方法
     * 这里由于是加载 jar文件,所以采用DexClassLoader
     * 下面开始加载dex class
     */
    private static Method getMethod(Context context,String methodName,Class<?>... methodArgs) {
        File cacheFile = context.getCacheDir();
        Log.d(TAG, "loadDexClass file path: " + cacheFile.getAbsolutePath());
        String internalPath = cacheFile.getAbsolutePath() + File.separator + "classes.dex";
        File desFile = new File(internalPath);
        Method method = null;
        if (desFile.exists()) {
            DexClassLoader dexClassLoader = new DexClassLoader(internalPath//dex文件路径, cacheFile.getAbsolutePath()//dex文件解压路径, cacheFile.getAbsolutePath()//so的搜索路径, context.getClass().getClassLoader());
            try {
                Class<?> libClazz = dexClassLoader.loadClass("com.example.testdepence.Add");
                Method getInstance = libClazz.getMethod("getInstance");
                getInstance.setAccessible(true);
                handle = getInstance.invoke(null);
                if (handle ==null){
                    Log.d(TAG, "getInstance error handle is null !!! ");
                }else {
                    Log.d(TAG, "getInstance success!!! ");
                }

                method = libClazz.getMethod(methodName,methodArgs);
                method.setAccessible(true);

            } catch (Exception e) {
                e.printStackTrace();
                Log.d(TAG, "getMethod error: " + e.getMessage());
                return method;
            }
        }else{
            Log.d(TAG, "aar not exist!!!");
        }
        return method;
    }

    public static int dynamicInit(Context context,byte[] data){
        Method initHandle = getMethod(context,"init",byte[].class);
        if (initHandle !=null && handle != null && data != null){
            try {
                initHandle.invoke(handle,data);
            } catch (IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
                return -1;
            }
        }
        return 0;
    }
}

然后在activity里边调用之

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DynamicLoader.dynamicInit(this,new byte[1024]);
    }

之后在setting.gradle里边将testdepence里这个module移除,编译app,准备运行

将dex和so push到手机的指定路径

按照“internalPath//dex文件路径, cacheFile.getAbsolutePath()//dex文件解压路径, cacheFile.getAbsolutePath()//so的搜索路径”,将dex和so push到手机对应的目录,然后就可以打开app运行啦。

 

源码见github:https://github.com/gangmiangongjue/Android-Dynamic-Plugin-demo

好用的话请点个星星~不好用欢迎提case,谢谢

 

标签:dex,插件,getInstance,TAG,static,so,android,null
来源: https://www.cnblogs.com/changweijinghu/p/15703519.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有