宿主与插件进行数据交互研究

本文主要介绍通过跨进程通信(aidl)完成宿主与插件数据通信。

首先看下项目结构
这里写图片描述

1.分别在宿主与插件中新增IService.aidl文件,文件名与包名要一致。IService.aidl中增加2个方法

interface IService {

    void init(String str, int i);//宿主将数据传入插件中

    String getString();//从插件中获取数据
}

2.接着在宿主中新建ProxyService,然后在onBind方法中实现方法转发

public IBinder onBind(Intent intent) {
   fillService();
   return pluginService.onBind(intent);
}

pluginService即为插件中的Service,pluginService是有fillService方法获取而来,具体实现实现如下

3.首先加载插件apk,构建出插件的DexClassLoader

String dexOutputPath = this.getDir("plugin", 0).getAbsolutePath();
String libOutputPath = this.getDir("plugin_lib", 0).getAbsolutePath();

String pluginApkPath = getDestPath();
File file=new File((pluginApkPath));
if(!file.exists()){
    return;
}
//获取插件dexClassLoader,pluginApkPath为插件apk的目录
DexClassLoader pluginDexClassLoader = new DexClassLoader(pluginApkPath, dexOutputPath, libOutputPath, this.getClassLoader());

然后通过DexClassLoader新建插件中的Service

 pluginService = (Service) pluginDexClassLoader.loadClass("com.afun.plugin.MyService").newInstance();

最后反射调用插件Service的attach方法,构建出插件Service的上下文与基础参数。

先看下attach方法需要的参数

public final void attach(
            Context context,
            ActivityThread thread, String className, IBinder token,
            Application application, Object activityManager)

然后通过反射获取各个参数,执行插件Service的attach方法

Object[] objArr = new Object[6];
objArr[0] = this.getBaseContext();

Class service = this.getClass().getSuperclass();
Field field = service.getDeclaredField("mThread");
field.setAccessible(true);
objArr[1] = field.get(this);

objArr[2] = getClass().getName();

Field field1 = service.getDeclaredField("mToken");
field1.setAccessible(true);
objArr[3] = field1.get(this);

objArr[4] = getApplication();

Field field2 = service.getDeclaredField("mActivityManager");
field2.setAccessible(true);
objArr[5] = field2.get(this);

Method attach = pluginService.getClass().getMethod("attach", Context.class, (objArr[1]).getClass(), String.class, IBinder.class, Application.class, Object.class);
attach.setAccessible(true);
attach.invoke(pluginService, objArr);

4.接下来在MainActivity中完成bindService,关键代码如下

private void bindService() {
      ServiceConnection serviceConnection = new ServiceConnection() {

          public void onServiceDisconnected(ComponentName name) {

          }

          public void onServiceConnected(ComponentName name, IBinder service) {
              //iService为Binder的Proxy
              iService = IService.Stub.asInterface(service);

              try {
                  iService.init("test", 123);

                  Toast.makeText(MainActivity.this, iService.getString(), Toast.LENGTH_SHORT).show();
              } catch (RemoteException e) {
                  e.printStackTrace();
              }
          }
      };

      Intent intent = new Intent();
      intent.setPackage(this.getPackageName());
      bindService(new Intent(this, ProxyService.class), serviceConnection, Context.BIND_AUTO_CREATE);
    }

有了iService可以调用iService.getString()方法从插件中获取数据。

至此,宿主apk调用IService中的init方法将数据传递到了插件中,也调用了getString方法从插件中获取数据。

5.下面看下插件中的com.afun.plugin.MyService的关键代码

  class IServiceImpl extends com.sdk.service.IService.Stub {

        @Override
        public void init(String str, int i) throws RemoteException {
            Log.e("in plugin", "init success");
            Log.e("in plugin", "str:" + str + "," + "i:" + i);

            Toast.makeText(getBaseContext(), "str:" + str + "," + "i:" + i, Toast.LENGTH_SHORT).show();
        }

        @Override
        public String getString() throws RemoteException {
            return "you get data from plugin service";
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new IServiceImpl();
    }

最后将插件plugin.apk push到手机中运行宿主apk查看结果

01-24 20:16:59.534 12977-12977/? E/in plugin: init success
01-24 20:16:59.535 12977-12977/? E/in plugin: str:test,i:123
01-24 20:16:59.542 12977-12977/? E/in app: str:you get data from plugin service

可以看出,在宿主获取到了插件中的数据,在插件中获取到了宿主传入的数据。

感兴趣的可以看下源码
本文Demo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值