Android DexClassLoader调用其他apk中的函数

场景:
手机内安装两个应用A和B,B通过DexClassLoader调用A中的方法
原理:
1.通过Intent查询系统注册的A应用的Activity信息
2.从得到的Activity信息中得到A应用的包名,apk或jar存放路径等信息
3.通过得到A应用的信息构造DexClassLoader对象
4.得到的DexClassLoader对象是和应用A关联起来的,然后去通过DexClassLoader对象加载你需要使用的类。
5.通过反射调用A应用的里面的方法。

A应用实现:
创A工程,包名为com.cn.plugin,在com.cn.plugin目录下创建一个类

package com.cn.plugin;

import android.util.Log;

public class PluginClass {
    public PluginClass() {
        Log.i("Plugin", "PluginClass client initialized");
    }

    public int function1(int a, int b) {
        return a + b;
    }
}

然后给A的一个Activity配置一个Action,这里直接个MainActivty设置一个Action

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.cn.plugin"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <action android:name="com.cn.plugin.client" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

给应用A的MainActivity指定了一个Action为”com.cn.plugin.client”至此,应用A的工作做完了,安装应用A。

新建工程B,在B中调用下面函数

    public void useDexClassLoader() {
        Intent intent = new Intent("com.cn.plugin.client", null);
        PackageManager pm = getPackageManager();
        //通过Intent查询ResolveInfo
        final List<ResolveInfo> plugins = pm.queryIntentActivities(intent, 0);
        //取出第一个ResolveInfo,因为这只是一个Demo,所以直接取第一个就是我们所要的A中MainActivity信息
        ResolveInfo rInfo = plugins.get(0);
        //得到A应用的Activity信息
        ActivityInfo aInfo = rInfo.activityInfo;
        //通过ActivityInfo得到构造DexClassLoader对象的参数信息
        String packageName = aInfo.packageName;
        String dexPath = aInfo.applicationInfo.sourceDir;
        String dexOutputDir = getApplicationInfo().dataDir;
        String libPath = aInfo.applicationInfo.nativeLibraryDir;

        Log.d("TAG", "packageName is : " + packageName + "\n" + "dexPath is : "
                + dexPath + "\ndexOutputDir is : " + dexOutputDir
                + "\nlibPath is : " + libPath);
        //构造ClassLoader对象
        DexClassLoader classLoader = new DexClassLoader(dexPath, dexOutputDir,
                libPath, getClass().getClassLoader());
        try {
            //通过全路径名加载PluginClass类
            Class<?> clazz = classLoader
                    .loadClass(packageName + ".PluginClass");
            //构造PluginClass对象
            Object obj = clazz.newInstance();
            Class<?>[] params = new Class[2];
            params[0] = Integer.TYPE;
            params[1] = Integer.TYPE;
            //反射调用function1方法
            Method action = clazz.getMethod("function1", params);
            Integer ret = (Integer) action.invoke(obj, 12, 34);
            Log.i("Host", "return value is " + ret);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

安装B应用,在调用的地方查看打印如下:

12-30 23:53:08.077: D/TAG(19891): packageName is : com.cn.plugin
12-30 23:53:08.077: D/TAG(19891): dexPath is : /data/app/com.cn.plugin-1/base.apk
12-30 23:53:08.077: D/TAG(19891): dexOutputDir is : /data/user/0/com.cn.host
12-30 23:53:08.077: D/TAG(19891): libPath is : /data/app/com.cn.plugin-1/lib/arm64
12-30 23:53:08.083: W/System(19891): ClassLoader referenced unknown path: /data/app/com.cn.plugin-1/lib/arm64
12-30 23:53:08.084: I/Plugin(19891): PluginClass client initialized
12-30 23:53:08.084: I/Host(19891): return value is 46

成功的通过B应用调用A应用的方法完成了两个数的相加。

Demo下载

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值