【Android】插件化开发的学习一:RePlugin简单使用

一、了解

1、博客:有关Android 插件化的思考

学习链接:https://www.cnblogs.com/cr330326/p/7222489.html

  主流框架(详细介绍见上方链接):

(1)DL 动态加载框架 ( 2014 年底)

(2)DroidPlugin ( 2015 年 8 月)

(3)Small ( 2015 年底)

(4)VirtualAPK (2017年 6 月)

(5)RePlugin (2017 年 7 月)

2、博客:Android插件化-RePlugin项目集成与使用

学习链接:https://www.cnblogs.com/codingblock/p/7766365.html

3、博客:【Android插件化】RePlugin集成配置

学习链接:https://www.jianshu.com/p/42d35abff2d4

二、尝试

1、使用:RePlugin

(1)Android 工程根目录中的build.gradle文件中:添加RePlugin Host Gradle依赖

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        google()
        jcenter()
        
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.2'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files

        // 1、添加RePlugin Host Gradle依赖
        classpath 'com.qihoo360.replugin:replugin-host-gradle:2.3.1'

    }
}

allprojects {
    repositories {
        google()
        jcenter()
        
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

(2)Android 工程中app项目(主APP)中,build.gradle文件中:添加RePlugin Host Library依赖 

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "yc.bluetooth.testrepluginpro"
        minSdkVersion 18
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

// 集成 RePlugin 添加的配置
pply plugin: 'replugin-host-gradle'

// 集成 RePlugin 添加的配置
repluginHostConfig {
    useAppCompat = true // 如果项目需要支持 AppComat,则需要将此配置置为 true
    // 如果应用需要个性化配置坑位数量,则需要添加以下代码进行配置
    //    countNotTranslucentStandard = 6
    //    countNotTranslucentSingleTop = 2
    //    countNotTranslucentSingleTask = 3
    //    countNotTranslucentSingleInstance = 2
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    // 集成 RePlugin 添加的配置
    implementation 'com.qihoo360.replugin:replugin-host-lib:2.3.2'
}

(3)Android 工程中app项目(主APP)中,新建 MyApplication 直接继承自 RePluginApplication:

package yc.bluetooth.testrepluginpro;

import com.qihoo360.replugin.RePlugin;
import com.qihoo360.replugin.RePluginApplication;
import com.qihoo360.replugin.RePluginConfig;

/**
 * 注意:MyApplication要在AndroidManifest.xml中添加名字
 */
public class MyApplication extends RePluginApplication {

    @Override
    public void onCreate() {

        super.onCreate();
        //不会自动将“主程序签名”加入进来。如有需要,建议您自行加入。
//        RePlugin.addCertSignature("379C790B7B726B51AC58E8FCBCFE4567");

    }
    @Override
    protected RePluginConfig createConfig() {
        RePluginConfig c = new RePluginConfig();
        //若为Debug环境下则无需校验签名,只有Release才会校验
        //打开签名校验
        c.setVerifySign(!BuildConfig.DEBUG);
        return c;
    }
}

(4)Android 工程中app项目(主APP)中,在AndroidManifest.xml文件中 给Application标签添加name属性 : 

(5)Android 工程中app项目(主APP)中,在AndroidManifest.xml文件中 声明访问存储空间的权限: 

注意Android 6.0以上需要动态申请权限

 (6)Android 工程根目录中的build.gradle文件中:添加RePlugin Plugin Gradle依赖(插件工程用)

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        google()
        jcenter()
        
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.3.2'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files

        // 1、添加RePlugin Host Gradle依赖
        classpath 'com.qihoo360.replugin:replugin-host-gradle:2.3.1'

        // 2、添加RePlugin Plugin Gradle依赖(插件工程用)
        classpath 'com.qihoo360.replugin:replugin-plugin-gradle:2.3.2'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
        
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

 

 (7)Android 工程中插件项目(插件 APP)中,build.gradle文件中:添加RePlugin Plugin Library依赖  

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28



    defaultConfig {
        applicationId "yc.bluetooth.pluginapp1"
        minSdkVersion 18
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

}

// 集成 RePlugin 添加的配置
apply plugin: 'replugin-plugin-gradle'

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])

    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    // 集成 RePlugin 添加的配置
    implementation 'com.qihoo360.replugin:replugin-plugin-lib:2.3.2'
}

(8)编译Sync now报错

No signature of method: com.android.build.gradle.internal.scope.VariantScopeImpl.getMergeAssetsTask() is applicable for argument types: () values: []
解决:降低gradle plugin版本至3.1.4(由3.3.2降至3.1.4)

学习博客

1、360插件化踩坑记录(一),RePlugin无法Sync成功,No signature of method: com.android.build.gradle.internal.scope

https://blog.csdn.net/MengJun1/article/details/88529208

2、RePlugin 初体验

https://www.jianshu.com/p/bc79ba98662f

(10)插件 APP界面和逻辑:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="这是pluginApp 的界面!!"
        android:textSize="20sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

 MainActivity.java

package yc.bluetooth.pluginapp1;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

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

(11)打包插件 APP生成apk文件: pluginapp1-release.apk

(12)主APP界面和逻辑:

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/bt_start_plugin1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="打开插件1!"
        android:textSize="20sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

MainActivity.java

package yc.bluetooth.testrepluginpro;

import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.qihoo360.replugin.RePlugin;
import com.qihoo360.replugin.model.PluginInfo;
import com.qihoo360.replugin.utils.FileUtils;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;

public class MainActivity extends AppCompatActivity {

    private Button btStartPlugin1;

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

        btStartPlugin1 = findViewById(R.id.bt_start_plugin1);
        btStartPlugin1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                simulateInstallExternalPlugin();

            }
        });
    }

    /**
     * 模拟安装或升级(覆盖安装)外置插件
     * 注意:本demo将外置插件放置到/storage/emulated/0/2019yayplugin/xxx.apk目录下
     *
     * todo 测试:重新安装项目后apk路径需要重新设定,重新将apk放到目新目录中
     */
    private void simulateInstallExternalPlugin() {
        //sd卡路径
        //获取外部存储的路径返回绝对路径的,就是你的设备SD卡的文件路径
        String pluginName = "pluginapp1-release.apk";
        String externalPluginPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/2019yayplugin/" + pluginName;
        String internalPluginPath = getFilesDir() + "/" + pluginName;
        File externalPluginFile = new File(externalPluginPath);
        File internalPluginFile = new File(internalPluginPath);

        if (externalPluginFile.exists()) {
            if (internalPluginFile.exists()) {
                FileUtils.deleteQuietly(internalPluginFile);
            }
            //复制文件 更新操作
            copyFile(externalPluginPath, internalPluginPath);
            PluginInfo info = RePlugin.install(externalPluginPath);
            if (info != null) {
                RePlugin.startActivity(this, RePlugin.createIntent(info.getName(), "yc.bluetooth.pluginapp1.MainActivity"));
            } else {
                Toast.makeText(this, "加载插件失败", Toast.LENGTH_SHORT).show();
            }
        } else {
            if (internalPluginFile.exists()) {
                PluginInfo info = null;
                if (internalPluginFile.exists()) {
                    info = RePlugin.install(internalPluginPath);
                }
                if (info != null) {
                    RePlugin.startActivity(this, RePlugin.createIntent(info.getName(), "yc.bluetooth.pluginapp1.MainActivity"));
                } else {
                    Toast.makeText(this, "加载插件失败", Toast.LENGTH_SHORT).show();
                }
            } else {
                Toast.makeText(this, "没有插件", Toast.LENGTH_SHORT).show();
                Log.d("Plugin1", "没有插件2");

            }
        }
    }
    /**
     * 复制单个文件
     *
     * @param oldPath String 原文件路径
     * @param newPath String 复制后路径
     * @return boolean
     */
    public void copyFile(String oldPath, String newPath) {
        try {
            int bytesum = 0;
            int byteread = 0;
            File oldfile = new File(oldPath);
            if (oldfile.exists()) { //文件存在时
                InputStream inStream = new FileInputStream(oldPath); //读入原文件
                FileOutputStream fs = new FileOutputStream(newPath);
                byte[] buffer = new byte[1444];
                while ((byteread = inStream.read(buffer)) != -1) {
                    bytesum += byteread; //字节数 文件大小
                    System.out.println(bytesum);
                    fs.write(buffer, 0, byteread);
                }
                inStream.close();
            }
        } catch (Exception e) {
            System.out.println("复制单个文件操作出错");
            e.printStackTrace();

        }

    }
}

(13)运行主APP,点击“打开插件1”,跳转插件APP的MainActivity界面。

       

至此,RePlugin的简单使用已初步实现,后续将进行更深入的学习。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值