插件化Android知识Android开发经验谈

全面插件化时代RePlugin来临

2017-07-10  本文已影响1343人  阿犇专用

一、RePlugin简介


RePlugin是一套完整的、稳定的、适合全面使用的,占坑类插件化方案。我们“逐>词”拆开来解释这个定义:

完整的:让插件运行起来“像单品那样”,支持大部分特性
稳定的:如此灵活完整的情况下,其框架崩溃率仅为业内很低的“万分之一”
适合全面使用的:其目的是让应用内的“所有功能皆为插件”
占坑类:以稳定为前提的Manifest占坑思路
插件化方案:基于Android原生API和语言来开发,充分利用原生特性

RePlugin:<a href="https://github.com/Qihoo360/RePlugin">Github地址</a>

RePlugin使用简易示例:<a href="https://github.com/aBenVip/RePluginHostDemo.git">Github地址</a>仅作为学习交流使用,欢迎star

二、RePlugin配置说明


RePlugin分宿主工程和插件工程,需要在工程下配置以下内容

1、宿主工程配置


A)在Project级别gradle的dependencies中添加

classpath 'com.qihoo360.replugin:replugin-host-gradle:2.1.3'

B)在Moudle级别gradle中添加

apply plugin: 'replugin-host-gradle'
compile 'com.qihoo360.replugin:replugin-host-lib:2.1.3'

2、插件工程配置


A)在Project级别gradle的dependencies中添加

classpath 'com.qihoo360.replugin:replugin-plugin-gradle:2.1.4'

B)在Moudle级别gradle中添加

apply plugin: 'replugin-plugin-gradle'
compile 'com.qihoo360.replugin:replugin-plugin-lib:2.1.3'

三、RePlugin内置插件


1、内置插件安装


内置插件以jar文件的形式放置在assets->plugins目录下(注:内置插件只有放在此目录下才能被RePlugin识别并自动安装,如plugins文件夹未自动创建,需要手动创建)

2、内置插件识别机制


插件的相关配置信息采用json的格式进行存储,存储在assets->plugins-builtin.json文件下,程序启动时,由RePlugin识别并自动进行插件安装

  [{"high":null,
    "frm":null,
    "ver":100,
    "low":null,
    "pkg":"com.qihoo360.replugin.sample.demo1",
    "path":"plugins/demo1.jar","name":"demo1"
  }]

3、内置插件升级


A)主程序随包升级

安装包更新时,若插件版本更新时自动升级

B)通过install方法升级

同外置插件升级,RePlugin.install()方法进行插件升级

4、内置插件删除


直接移除jar文件即可,RePlugin会完成剩余操作

四、RePlugin外置插件

1、外置插件安装


i. 外置插件安装方式

采用加载apk的方式,使用RePlugin.install()方法进行安装

ii. 外置插件安装注意事项

如果处于debug模式,需要在application中关闭签名校验,通过对RePluginConfig的处理,关闭签名校验,(预计下个版本会默认关闭签名校验,不过官方建议在release中打开该校验)

  @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        //--------------开发的时候不验证签名
        RePluginConfig config = new RePluginConfig();
        config.setVerifySign(!BuildConfig.DEBUG);
        config.setPrintDetailLog(BuildConfig.DEBUG);
        config.setUseHostClassIfNotFound(true);
        RePlugin.App.attachBaseContext(this, config);    }

iii. 插件的安装

通过RePlugin.install()方法进行安装,可以通过RePlugin.preload()方法对插件进行预加载,提升用户体验

  PluginInfo pluginInfo = RePlugin.install(absolutePath + "/aa.apk");
  if (pluginInfo != null) {
        Toast.makeText(MainActivity.this, "插件安装成功",Toast.LENGTH_SHORT).show();
        boolean preload = RePlugin.preload(pluginInfo);   
 if (preload){
        Toast.makeText(MainActivity.this, "预加载完成", Toast.LENGTH_SHORT).show();
    } else {    
        Toast.makeText(MainActivity.this, "插件安装失败",Toast.LENGTH_SHORT).show();
    }

iiii. 插件的版本

需要Plugin的AndroidManifest中对插件的别名和版本进行设置,不设置的话以包名和version为默认值(注:暂不支持同版本覆盖,升级插件必须修改版本号,卸载重新安装也需要进行版本修改)

    <meta-data
        android:name="com.qihoo360.plugin.name"
        android:value="plugin01" />
    <meta-data
        android:name="com.qihoo360.plugin.version.ver"
        android:value="114" />

2、插件的升级


通过RePlugin.install(pi)方法进行升级

3、插件的卸载


通过RePlugin.uninstall("demo01")卸载

五、RePlugin宿主与插件交互

1、宿主打开插件中的四大组件


A)Activity

  RePlugin.startActivity(MainActivity.this, RePlugin.createIntent("plugin01", "com.dg.replugindemo01.MainActivity"));

B)Service

  PluginServiceClient.bindService(RePlugin.createIntent( "exam", "AbcService"), mServiceConn);

B)Service

  PluginServiceClient.bindService(RePlugin.createIntent( "exam", "AbcService"), mServiceConn);

B)ContentProvider

  PluginProviderClient.query(xxx);

。。。。

2、宿主调用插件方法


A)fetchComponentList(String pluginName);//获取插件的组件列表

B)fetchPackageInfo(String pluginName);//获取插件的包信息

C)fetchResources(String pluginName);//获取插件的资源信息

D)fetchClassLoader(String pluginName);//获取插件的ClassLoader对象

E)fetchContext(String pluginName);//获取插件的Context对象

F)fetchBinder(String pluginName, String module, String process);
//通过插件里的Plugin类,获取插件定义的IBinder

示例:

    //加载插件中的工具类
    ClassLoader classLoader = RePlugin.fetchClassLoader("plugin01");
    try {    
    Class<?> aClass = classLoader.loadClass("com.dgcredit.replugindemo01.DateHelper");   
    Method formatDate = aClass.getMethod("formatDate", Date.class); 
    String invoke = (String) formatDate.invoke(null, new Date()); 
    tvShow.setText(invoke);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }

///加载插件,并获取插件的资源信息

    Resources resources = RePlugin.fetchResources("plugin01");
    int identifier = resources.getIdentifier("icon_app", "drawable", "com.dgcredit.replugindemo01");
    ivShow.setImageResource(identifier);

3、插件调用宿主方法


//加载宿主中的工具类

  ClassLoader classLoader = RePlugin.getHostClassLoader();
    try {
        Class<?> aClass = classLoader.loadClass("com.dgcredit.repluginhostdemo.DateHelper");
        Method formatDate = aClass.getMethod("formatDate", Date.class);
        String invoke = (String) formatDate.invoke(null, new Date());
        viewById.setText(invoke);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (InvocationTargetException e) {
        e.printStackTrace();
    }

//加载宿主中图片资源

  ClassLoader classLoader = RePlugin.getHostClassLoader();
    try{
        Class clazz = classLoader.loadClass("com.dgcredit.repluginhostdemo.R$drawable");
        Field field = clazz.getField("icon_app");
        int identifier = (int)field.get(null);
        ivShow.setImageResource(identifier);
    }catch(Exception e){
        Log.i("Loader", "error:"+Log.getStackTraceString(e));
    }

4、插件调用宿主组件


  Intent intent = new Intent();
  intent.setComponentName(new ComponentName("com.qihoo360.replugin.sample.host", "com.qihoo360.replugin.sample.host.MainActivity"));
  context.startActivity(intent);

六、RePlugin接入错误集锦

1、Theme错误


  Caused by: java.lang.IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.

解决方式

A)去除插件中对application的theme的引入,单独对插件中的activity设置相关theme
   android:theme="@style/AppTheme"
B)在宿主的build.gradle中加入
  repluginHostConfig {
    useAppCompat = true
}

2、ActivityNotFoundException错误


Unable to find explicit activity class{com.qihoo360.replugin.sample.host/con.qihoo360.replugin.sample.host.loader.a.ActivityN1NRNTS3};have you declared this activity in your AndroidManifest.xml?
解决方式:
  关闭Setting中instand run功能。目前此Bug在官方2.1.4版本已修复,尚未验证

3、Fail to apply plugin [id 'replugin-plugin-gradle']错误


解决方式:
 这个plugin需要放在android配置之后,因为需要读取android中的配置项

4、外置插件RePlugin.install()方法无反应


解决方式:
@override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        //-------------- 开发的时候不验证签名 -----------//
        RePluginConfig config = new RePluginConfig();
        config.setVerifySign(!BuildConfig.DEBUG);
        RePlugin.App.attachBaseContext(this, config);
        // =======================//
        }

文档正在整理完善中,欢迎讨论指正。。。。

上一篇下一篇

猜你喜欢

热点阅读