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

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 插件化框架介绍与使用说明_第1张图片
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

若你的应用对 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 插件化框架介绍与使用说明)