基于RePlugin实现Android项目插件化(一)

前一篇文章介绍了Android项目基于ARouter的组件化过程,其实大部分中小型项目只需要组件化就足够了,但是大型项目比如淘宝、微信、美团、钉钉、360手机助手等等,这些项目太大太复杂了,项目开发到后期编译一次要花费很多时间。在这样的背景下,插件化实现方式就诞生了。

本文的重点是记录RePlugin的使用,没有什么底层原理性的知识点,接下来就开始我们项目的插件化之旅吧。本篇文章的目标是将ft_login插件化,然后接入到宿主app中,能够从宿主工程的LoadingActivity跳转到插件工程中的LoginActivity。

下图是演示demo的目录结构

一、按RePlugin上介绍的来,先接入主程序。

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

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

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

defaultConfig {
    //这里配置一定要跟包名一致 
    applicationId "com.example.test" 
    //插件化不需要分包
    multiDexEnabled false 
}

// ATTENTION!!! Must be PLACED AFTER "android{}" to read the applicationId
apply plugin: 'replugin-host-gradle'

/**
 * 配置项均为可选配置,默认无需添加
 * 更多可选配置项参见replugin-host-gradle的RepluginConfig类
 * 可更改配置项参见 自动生成RePluginHostConfig.java
 */
repluginHostConfig {
    /**
     * 是否使用 AppCompat 库
     * 不需要个性化配置时,无需添加
     */
    useAppCompat = true
}

dependencies {
    compile 'com.qihoo360.replugin:replugin-host-lib:2.3.4'
    ...
}

最后一步是MyApplicaiton要继承RePluginApplication,并在manifest中添加。

public class MyApplication extends RePluginApplication {
    @Override
    public void onCreate() {
        super.onCreate();
    }
}

二、插件工程接入RePlugin

子程序接入步骤

  • 接入插件化框架
  • 接入到主程序

参考官方文档,先接入插件化框架

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

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

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

apply plugin: 'replugin-plugin-gradle'

repluginPluginConfig {
    //当前插件的名字
    pluginName = 'ft_login'
    //当前插件要继承到哪个宿主工程中
    hostApplicationId = 'com.example.test'
    //宿主工程的启动activity
    hostAppLauncherActivity = 'com.example.test.LoadingActivity'
}

dependencies {
    implementation 'com.qihoo360.replugin:replugin-plugin-lib:2.3.4'
}

以上操作完成后再sync工程,可能会报错,是gradle版本的问题,报错之前的版本gradle tools版本是4.0.0,gradle版本是gradle-6.1.1,分别改成3.4.2和5.1.1就好了。

3、插件工程的Activity需要继承PluginActivity

public class LoginActivity extends PluginActivity {
    ......
}

4、打包插件工程,输入命令./gradlew :ft_login:assembleDebug

5、找到打包好的apk,然后复制到宿主工程特定的目录下

需要注意的是将apk复制到目录/main/assets/plugins下,文件名需要跟插件工程中定义的pluginName字段名保持一致。

宿主工程中的LoadingActivity很简单

package com.example.test;

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import com.qihoo360.replugin.RePlugin;

public class LoadingActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_loading_layout);

        handler.sendEmptyMessageDelayed(1, 2000);
    }

    Handler handler = new Handler(Looper.myLooper()) {
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
            Intent intent = RePlugin.createIntent("ft_login", "com.example.ft_login.LoginActivity");
            //相当于在宿主app主启动另外一个app中的activity,需要加这个参数
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            RePlugin.startActivity(LoadingActivity.this, intent);
            finish();
        }
    };

    private boolean hasLogin() {
        return false;
    }

    @Override
    public void onBackPressed() {

    }
}

接着我满怀激动的心情来启动了app工程,很遗憾,报错了

java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/localbroadcastmanager/content/LocalBroadcastManager;
        at com.qihoo360.loader2.PmBase.callAppCreate(PmBase.java:656)
        at com.qihoo360.loader2.PMF.callAppCreate(PMF.java:84)
        at com.qihoo360.replugin.RePlugin$App.onCreate(RePlugin.java:1009)
        at com.qihoo360.replugin.RePluginApplication.onCreate(RePluginApplication.java:74)
        at com.example.test.MyApplication.onCreate(MyApplication.java:9)

只需要在宿主工程中引入:

implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'

以上就是插件化集成的过程,下一节我将带着大家一起来看下宿主和插件之间是如何通信的。