美文网首页
RePlugin 插件化框架介绍与使用说明

RePlugin 插件化框架介绍与使用说明

作者: Little丶Jerry | 来源:发表于2018-12-04 13:25 被阅读0次

    RePlugin GitHub 主页

    RePlugin Wiki 主页

    RePlugin 原理剖析

    全面插件化:RePlugin 的使命

    * RePlugin 介绍
    
      * 主要优势
    
      * RePlugin 架构
    
    * 快速上手
    
      * 针对主程序开发者
    
        * 将 RePlugin 接入到你的主程序
    
        * 安装一个插件
    
        * 打开一个插件的 Activity
    
      * 针对插件开发者
    
        * 将现有工程 → RePlugin 插件
    
        * 声明一个插件的 Activity
    
        * 打开一个插件的 Activity
    
    * 调试与运行
    
      * 调试宿主
    
        * 环境配置
    
          * 仓库配置
    
          * 插件使用配置
    
        * 插件的 Gradle 任务
    
      * 调试插件
    
        * 环境配置
    
          * 仓库配置
    
          * 插件使用配置
    
        * 插件的 Gradle 任务
    

    一、RePlugin 介绍

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

    • 完整的:让插件运行起来“像单品那样”,支持大部分特性

    • 稳定的:如此灵活完整的情况下,其框架崩溃率仅为业内很低的“万分之一”

    • 适合全面使用的:其目的是让应用内的“所有功能皆为插件”

    • 占坑类:以稳定为前提的 Manifest 占坑思路

    • 插件化方案:基于 Android 原生 API 和语言来开发,充分利用原生特性

    1.1 主要优势

    • 极其灵活:主程序无需升级(无需在 Manifest 中预埋组件),即可支持新增的四大组件,甚至全新的插件

    • 非常稳定Hook 点仅有一处(ClassLoader),无任何 Binder Hook!如此可做到其崩溃率仅为“万分之一”,并完美兼容市面上近乎所有的 Android ROM

    • 特性丰富:支持近乎所有在“单品”开发时的特性。包括静态 ReceiverTask-Affinity 坑位、自定义 Theme、进程坑位、AppCompatDataBinding

    • 易于集成:无论插件还是主程序,只需“数行”就能完成接入

    • 管理成熟:拥有成熟稳定的“插件管理方案”,支持插件安装、升级、卸载、版本管理,甚至包括进程通讯、协议版本、安全校验等

    1.2 RePlugin 架构

    RePlugin 架构图

    以 360 手机卫士为例:

    • 系统层 —— Android:为 Android Framework 层。只有 ClassLoaderHook 的,而 AMSResources 等都没有做 Hook,确保了其稳定性。

    • 框架层 —— RePlugin 框架RePlugin 框架层,只有 RePlugin 是对“上层完全公开”的,其余均为 Internal,或“动态编译方案”生效后的调用,对开发者而言是“无需关心”的。

    • 插件层 —— 各插件“标蓝部分”是各插件,包括大部分的业务插件(如体检、清理、桌面插件等)。而其中“标黄部分”是支撑一个应用的各种基础插件,如 WebViewDownloadShare,甚至 Protobuf 都能成为基础插件。

    二、快速上手

    RePlugin 的使用方法非常简单易懂,大部分情况下和“单品”开发无异。以下分别针对:主程序(接入 RePlugin)和插件(研发 RePlugin 插件)来进行导引,以便适用于不同的团队成员。

    2.1 针对主程序开发者

    2.1.1 将 RePlugin 接入到你的主程序

    只需三步,就能让你的 “主程序” 接入 RePlugin

    注意:目前有开发同学反馈,开启 Instant Run 时可能会出现运行时异常情况,请临时关掉此功能后再试。

    有关“混淆”:

    RePlugin 的 AAR 自带 Proguard 文件,你无需关心,直接引入 AAR 即可生效。此外,其内部仅 Keep 了关键的接口类,大部分都是允许被混淆的,故对应用来说也没有影响。

    第 1 步:添加 RePlugin Host Gradle 依赖

    在项目根目录的 build.gradle(注意:不是 app/build.gradle) 中添加 replugin-host-gradle 依赖:

    buildscript {
        dependencies {
            classpath 'com.qihoo360.replugin:replugin-host-gradle:2.3.1'
            ...
        }
    }
    

    第 2 步:添加 RePlugin Host Library 依赖

    app/build.gradle 中应用 replugin-host-gradle 插件,并添加 replugin-host-lib 依赖:

    android {
        // ATTENTION!!! Must CONFIG this to accord with Gradle's standard, and avoid some error
        defaultConfig {
            // 如果已经有一个 applicationId 则无需再添加
            applicationId "com.qihoo360.replugin.sample.host"
            ...
        }
        ...
    }
    
    // ATTENTION!!! Must be PLACED AFTER "android{}" to read the applicationId
    // 注意!必须放在 “android{ }” 块后面,因为要先读取 applicationId
    apply plugin: 'replugin-host-gradle'
    
    /**
     * 配置项均为可选配置,默认无需添加
     * 更多可选配置项参见replugin-host-gradle的RepluginConfig类
     * 可更改配置项参见 自动生成RePluginHostConfig.java
     */
    repluginHostConfig {
        /**
         * 是否使用 AppCompat 库
         * 不需要个性化配置时,无需添加
         */
        useAppCompat = true
        /**
         * 背景不透明的坑的数量
         * 不需要个性化配置时,无需添加
         */
        countNotTranslucentStandard = 6
        countNotTranslucentSingleTop = 2
        countNotTranslucentSingleTask = 3
        countNotTranslucentSingleInstance = 2
    }
    
    dependencies {
        implementation 'com.qihoo360.replugin:replugin-host-lib:2.3.1'
        ...
    }
    
    以下内容请务必注意:
    • 请一定要确保符合 Gradle 开发规范,即“必须将包名写在applicatonId”,而非 AndroidManifest.xml 中(通常从 Eclipse 迁移过来的项目可能出现此问题)。如果不这么写,则有可能导致运行时出现 “Failed to find provider info for com.ss.android.auto.loader.p.main” 的问题。具体可参见 #87 Issue 的问答

    • 请将 apply plugin: 'replugin-host-gradle' 放在 android{ } 块之后,防止出现无法读取 applicationId,导致生成的坑位出现异常

    • 如果你的应用需要支持 AppComat,则除了在主程序中引入 AppComat-v7 包以外,还需要在宿主的 build.gradle 中添加下面的代码,若不支持 AppComat 则请不要设置此项:

    repluginHostConfig {
        useAppCompat = true
    }
    

    开启 useAppCompat 后,RePlugin 会在编译期生成 AppCompat 专用坑位,这样插件若使用 AppCompatTheme 时就能生效了。若不设置,则可能会出现 “IllegalStateException: You need to use a Theme.AppCompat theme (or descendant) with this activity.” 的异常。

    • 如果你的应用需要个性化配置坑位数量,则需要在宿主的 build.gradle 中添加下面的代码:
    repluginHostConfig {
         /**
         * 背景不透明的坑的数量
         */
        countNotTranslucentStandard = 6
        countNotTranslucentSingleTop = 2
        countNotTranslucentSingleTask = 3
        countNotTranslucentSingleInstance = 2
    }
    
    • 笔者在导入了上述依赖库之后,进行同步项目时,遇到了如下问题:Gradle sync failed: No signature of method: com.android.build.gradle.internal.scope.VariantScopeImpl.getMergeAssetsTask() is applicable for argument types: () values: []。这是因为 Google 对 3.2.0 版本之后的 Gradle 构建工具做了一些修改(笔者用的是 3.2.1),RePlugin 官方还没有对此用兼容性处理。 解决方法也很简单,把项目根目录的 build.gradle(注意:不是 app/build.gradle)中的
        dependencies {
            classpath 'com.android.tools.build:gradle:3.2.1'
        }
    

    改为

        dependencies {
            classpath 'com.android.tools.build:gradle:3.1.4'
        }
    

    即可,具体参见 #Issue 640

    更多可选配置项请参见 replugin-host-gradleRepluginConfig 类。

    第 3 步:配置 Application 类

    让工程的 Application 直接继承自 RePluginApplication。笔者发现,如果应用导入了 RePlugin,但是不配置 Application 类的话,那么应用程序将无法运行。详情请看这里 #Issue 46 sample 运行报错

    如果你的工程已有 Application 类,则可以将基类切换到 RePluginApplication 即可。或者你也可以用“非继承式”接入。

    public class MainApplication extends RePluginApplication {
    }
    

    既然声明了 Application,自然还需要在 AndroidManifest 中配置这个 Application

        <application
            android:name=".MainApplication"
            ... />
    
    备选:“非继承式”配置 Application

    若你的应用对 Application 类继承关系的修改有限制,或想自定义 RePlugin 加载过程(慎用!),则可以直接调用相关方法来使用 RePlugin

    public class MainApplication extends Application {
    
        @Override
        protected void attachBaseContext(Context base) {
            super.attachBaseContext(base);
    
            RePlugin.App.attachBaseContext(this);
            ....
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            
            RePlugin.App.onCreate();
            ....
        }
    
        @Override
        public void onLowMemory() {
            super.onLowMemory();
    
            /* Not need to be called if your application's minSdkVersion > = 14 */
            RePlugin.App.onLowMemory();
            ....
        }
    
        @Override
        public void onTrimMemory(int level) {
            super.onTrimMemory(level);
    
            /* Not need to be called if your application's minSdkVersion > = 14 */
            RePlugin.App.onTrimMemory(level);
            ....
        }
    
        @Override
        public void onConfigurationChanged(Configuration config) {
            super.onConfigurationChanged(config);
    
            /* Not need to be called if your application's minSdkVersion > = 14 */
            RePlugin.App.onConfigurationChanged(config);
            ....
        }
    }
    
    针对“非继承式”的注意点:
    • 所有方法必须在 UI 线程来“同步”调用。切勿放到工作线程,或者通过 post 方法来执行

    • 所有方法必须一一对应,例如 RePlugin.App.attachBaseContext() 方法只在 Application.attachBaseContext() 中调用

    • 请将 RePlugin.App 的调用方法,放在“仅次于 super.xxx()方法的后面

    2.1.2 安装一个插件

    这部分内容请看 RePlugin 关于插件管理

    2.1.3 打开一个插件的 Activity

    这部分内容请看 RePlugin 关于插件的组件

    2.2 针对插件开发者

    2.2.1 将现有工程 → RePlugin 插件

    只需两步,就能让你的 App 变成 “RePlugin 插件”:

    有关“混淆”:

    RePlugin 的 AAR 自带 Proguard 文件,你无需关心,直接引入 AAR 即可生效。此外,其内部仅 Keep 了关键的接口类,大部分都是允许被混淆的,故对应用来说也没有影响。

    第 1 步:添加 RePlugin Plugin Gradle 依赖

    在项目根目录的 build.gradle(注意:不是 app/build.gradle) 中添加 replugin-plugin-gradle 依赖:

    buildscript {
        dependencies {
            classpath 'com.qihoo360.replugin:replugin-plugin-gradle:2.3.1'
            ...
        }
    }
    

    第 2 步:添加 RePlugin Plugin Library 依赖

    app/build.gradle 中应用 replugin-plugin-gradle 插件,并添加 replugin-plugin-lib 依赖:

    apply plugin: 'replugin-plugin-gradle'
    
    dependencies {
        implementation 'com.qihoo360.replugin:replugin-plugin-lib:2.3.1'
        ...
    }
    

    接下来你就可以像单品那样,开你的插件。生成出来的是 APK,既可以“安装到设备”,又可以“作为插件”使用。

    2.2.2 声明一个插件的 Activity

    这部分内容请看 RePlugin 关于插件的组件

    2.2.3 打开一个插件的 Activity

    这部分内容请看 RePlugin 关于插件的组件

    三、调试与运行

    3.1 调试宿主

    3.1.1 环境配置

    3.1.1.1 仓库配置
    buildscript {
        repositories {
            maven { url 'https://dl.google.com/dl/android/maven2/' }
            google()
            jcenter()
        }
        dependencies {
            ...
            classpath 'com.qihoo360.replugin:replugin-host-gradle:2.3.1'
        }
    }
    
    3.1.1.2 插件使用配置
    // ATTENTION!!! Must be PLACED AFTER "android{}" to read the applicationId
    apply plugin: 'replugin-host-gradle'
    
    repluginHostConfig {
        /**
         * 是否使用 AppCompat 库
         * 不需要个性化配置时,无需添加
         */
        useAppCompat = true
    }
    

    apply plugin 尽量放在 android 配置之后,因为可以自动读取 android中 的配置项,方便以后升级。简单的说,就是放在你 build.gradle 文件末尾即可。

    3.1.2 插件的 Gradle 任务

    • rpGenerateDebugBuiltinJsonrpGenerateReleaseBuiltinJson

    生成内置插件的配置文件(一般很少使用,编译时会自动处理)

    • rpGenerateDebugHostConfigrpGenerateReleaseHostConfig

    生成插件们的坑位配置文件(一般很少使用,编译时会自动处理)

    • rpShowPluginsDebugrpShowPluginsRelease

    查看所有内置插件的信息

    3.2 调试插件

    3.2.1 环境配置

    3.2.1.1 仓库配置
    buildscript {
        repositories {
            maven { url 'https://dl.google.com/dl/android/maven2/' }
            google()
            jcenter()
        }
        dependencies {
            ...
            classpath 'com.qihoo360.replugin:replugin-plugin-gradle:2.3.1'
        }
    }
    
    3.2.1.2 插件使用配置
    apply plugin: 'replugin-plugin-gradle'
    
    repluginPluginConfig {
        //插件名
        pluginName = "demo1"
        //宿主app的包名
        hostApplicationId = "com.qihoo360.replugin.sample.host"
        //宿主app的启动activity
        hostAppLauncherActivity = "com.qihoo360.replugin.sample.host.MainActivity"
    }
    

    apply plugin 需要放在 android 配置之后,因为需要读取 android 中的配置项。简单的说,就是放在你 build.gradle 文件末尾即可。

    3.2.2 插件的 Gradle 任务

    一些 Gradle 任务依赖宿主,需要在宿主中添加 RePlugin.enableDebugger(base, BuildConfig.DEBUG); 这行代码

    • rpForceStopHostApp

    强制停止宿主程序

    • rpInstallAndRunPluginDebugrpInstallAndRunPluginRelease

    安装插件到宿主并运行(常用任务)

    • rpInstallPluginDebugrpInstallPluginRelease

    仅仅安装插件到宿主

    • rpRestartHostApp

    重启宿主程序

    • rpRunPluginDebugrpRunPluginRelease

    仅仅运行插件,如果插件前面没安装,则执行不成功

    • rpStartHostApp

    启动宿主程序

    • rpUninstallPluginDebugrpUninstallPluginRelease

    仅仅卸载插件,如果完全卸载,还需要执行 rpRestartHostAp 任务

    相关文章

      网友评论

          本文标题:RePlugin 插件化框架介绍与使用说明

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