美文网首页
DexClassLoader加载apk

DexClassLoader加载apk

作者: vonnie | 来源:发表于2017-07-16 00:02 被阅读383次

    DexClassLoader

    在java环境中,有个概念叫类加载器(ClassLoader),其作用是动态加载class文件,标准的java sdk中,有ClassLoader这个类,可以用来加载想要加载的class文件,每个ClassLoader在初始化的时候必须指定class的路径。

    每个ClassLoader都有一个父ClassLoader,当加载类的时候,子ClassLoader会先请求父ClassLoader去加载class文件,如果父ClassLoader找不到改class文件的时候,子ClassLoader才会继续去加载改class文件,只是一种安全机制。

    在android中加载的是dex文件,dex事经过优化的class文件。Android中事通过DexClassLoader来加载calss的,下面通过一个demo来介绍DexClassLoader的用法。

    首先创建一个PluginTest的project。在里面定义一个类,叫PluginClass,代码如下:

    //如果对PluginTest做了混淆,就加上@keep,没有就忽略
    @Keep
    public class PluginClass {
        public PluginClass() {
            Log.e("vonnie", "plugin:PluginClass was initialized");
        }
      
        public int add(int a, int b) {
            return a + b;
        }
    }
    

    在manifest文件中加入一个action:

    <activity android:name=".MainActivity">
        <intent-filter>
            <action android:name="android.intent.action.MAIN"/>
    
            <category android:name="android.intent.category.LAUNCHER"/>
        </intent-filter>
        <intent-filter>
            <action android:name="com.vonnie.plugintest.client"/>
        </intent-filter>
    </activity>
    

    然后编译运行,把生产的apk装入手机,接着新建一个叫Host的project,在Activity调用如下代码:

     public void onClick(View view) {
            Intent intent = new Intent("com.vonnie.plugintest.client", null);//action 为在pluginTest中添加的action
            PackageManager pm = getPackageManager();
            List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
            if (resolveInfos != null && !resolveInfos.isEmpty()) {
                ResolveInfo info = resolveInfos.get(0);
                ActivityInfo activityInfo = info.activityInfo;
                String packageName = activityInfo.packageName;
                String dexPath = activityInfo.applicationInfo.sourceDir;
                String dexOutputDir = getApplicationInfo().dataDir;
                String libPath = activityInfo.applicationInfo.nativeLibraryDir;
    
                DexClassLoader dcl = new DexClassLoader(dexPath, dexOutputDir
                        , libPath, this.getClassLoader());
                try {
                    Class<?> clazz = dcl.loadClass(packageName + ".PluginClass");
                    Object object = clazz.newInstance();
                    Method method = clazz.getMethod("add", Integer.TYPE, Integer.TYPE);
                    int result = (int) method.invoke(object, 1, 1);
                    Log.e("vonnie", "host: result:" + result);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    

    运行之后,log如下:

    A5EE630E-EDE2-4CCA-BEAC-1DEA52D95FCD.png
    DexClassLoader(String dexPath, String optimizedDirectory, String librarySearchPath, ClassLoader parent)
    

    dexPath:被解压的apk路径,不能为空。
    optimizedDirectory:解压后的.dex文件的存储路径,不能为空。这个路径强烈建议使用应用程序的私有路径,不要放到sdcard上,否则代码容易被注入攻击。
    libraryPath:os库的存放路径,可以为空,若有os库,必须填写。
    parent:父亲加载器,一般为context.getClassLoader(),使用当前上下文的类加载器。

    相关文章

      网友评论

          本文标题:DexClassLoader加载apk

          本文链接:https://www.haomeiwen.com/subject/mkzzhxtx.html