9

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

 3 years ago
source link: https://www.longdw.com/950.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

基于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'
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'
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
RePluginApplication

,并在manifest中添加。

public class MyApplication extends RePluginApplication {
@Override
public void onCreate() {
super.onCreate();
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'
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'
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 {
......
public class LoginActivity extends PluginActivity {
    ......
}

4、打包插件工程,输入命令

./gradlew :ft_login:assembleDebug
./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() {
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)
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'

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK