中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android插件化之RePlugin項目怎么用

發布時間:2021-08-09 10:53:07 來源:億速云 閱讀:154 作者:小新 欄目:移動開發

這篇文章主要為大家展示了“Android插件化之RePlugin項目怎么用”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“Android插件化之RePlugin項目怎么用”這篇文章吧。

1.什么是RePlugin?

在Android開發領域,有關插件化的討論一直熱度不減。目前市面上的插件化方案雖然很多,但多數只能實現某些功能的插件化,距離開發者的預期尚有相當差距。對此,在近期GMTC全球移動技術大會上,360手機衛士主程序架構負責人張炅軒宣布,360的插件化框架RePlugin已經可以實現“全面插件化”,同時具有出色的穩定性和靈活性,可適用于各種類型的應用上。
“RePlugin預計7月份開源,這將是我們獻給安卓世界最好的禮物。”360如是說。

2.RePlugin有什么用?

RePlugin是一套完整的、穩定的、適合全面使用的,占坑類插件化方案,由360手機衛士的RePlugin Team研發,也是業內首個提出”全面插件化“(全面特性、全面兼容、全面使用)的方案。

3.RePlugin官方介紹

其主要優勢有:

  1. 極其靈活:主程序無需升級(無需在Manifest中預埋組件),即可支持新增的四大組件,甚至全新的插件

  2. 非常穩定:Hook點僅有一處(ClassLoader),無任何Binder Hook!如此可做到其崩潰率僅為“萬分之一”,并完美兼容市面上近乎所有的Android ROM

  3. 特性豐富:支持近乎所有在“單品”開發時的特性。包括靜態Receiver、Task-Affinity坑位、自定義Theme、進程坑位、AppCompat、DataBinding等

  4. 易于集成:無論插件還是主程序,只需“數行”就能完成接入

  5. 管理成熟:擁有成熟穩定的“插件管理方案”,支持插件安裝、升級、卸載、版本管理,甚至包括進程通訊、協議版本、安全校驗等

  6. 數億支撐:有360手機衛士龐大的數億用戶做支撐,三年多的殘酷驗證,確保App用到的方案是最穩定、最適合使用的

一、集成主工程

1、在項目根目錄的 build.gradle 下添加 RePlugin Host Gradle 依賴:

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:2.3.3'
    // 1、添加RePlugin Host Gradle依賴
    classpath 'com.qihoo360.replugin:replugin-host-gradle:2.2.1'
  }
}

2、在 app/build.gradle 下添加 RePlugin Host Library 依賴(為了更清晰的表示出代碼添加的位置,將原有代碼也一并貼出):
apply plugin: 'com.android.application'

android {
  compileSdkVersion 26
  buildToolsVersion "26.0.1"
  defaultConfig {
    applicationId "cn.codingblock.repluginstudy"
    minSdkVersion 21
    targetSdkVersion 26
    versionCode 1
    versionName "1.0"
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
  }
  buildTypes {
    release {
      minifyEnabled false
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
    }
  }
}

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

// 集成 RePlugin 添加的配置
repluginHostConfig {
  useAppCompat = true // 如果項目需要支持 AppComat,則需要將此配置置為 true
  // 如果應用需要個性化配置坑位數量,則需要添加以下代碼進行配置
//  countNotTranslucentStandard = 6
//  countNotTranslucentSingleTop = 2
//  countNotTranslucentSingleTask = 3
//  countNotTranslucentSingleInstance = 2
}

dependencies {
  compile fileTree(dir: 'libs', include: ['*.jar'])
  androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
  })
  compile 'com.android.support:appcompat-v7:26.+'
  compile 'com.android.support.constraint:constraint-layout:1.0.2'
  compile 'com.qihoo360.replugin:replugin-host-lib:2.2.1' // 集成 RePlugin 添加的配置
  testCompile 'junit:junit:4.12'
}

以上代碼有三點需要注意:

  1. 需要將 apply plugin: 'replugin-host-gradle' 放在 android {...} 之后。

  2. 如果項目需要支持 AppComat,則需要將 repluginHostConfig 的 userAppCompat 置為 true。

  3. 如果應用需要個性化配置坑位數量,則需要在 repluginHostConfig 中添加以下代碼進行配置:

countNotTranslucentStandard = 6

countNotTranslucentSingleTop = 2

countNotTranslucentSingleTask = 3

countNotTranslucentSingleInstance = 2

3、讓工程的 Application 直接繼承自 RePluginApplication:

public class MyApplication extends RePluginApplication { }

當然,同時不要忘了在 AndroidManifest 對 MyApplication 的相關配置。

說明:有時候由于項目原有結構的需要,我們可能不能直接使用繼承 RePluginApplication 的方式,這個問題看來 RePlugin 開發者也想到了,所以還特地多了一種選擇,下面是項目的 Application 不繼承 RePluginApplication 的方式:

public class MyApplication 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();
    RePlugin.App.onLowMemory();
  }

  @Override
  public void onTrimMemory(int level) {
    super.onTrimMemory(level);
    RePlugin.App.onTrimMemory(level);
  }

  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    RePlugin.App.onConfigurationChanged(newConfig);
  }
}

二、集成插件

新建一個工程做為插件APP,這里為了方便起見,直接在主工程中新建了一個 Module。

1、同集成主工程類似,在根目錄的 build.gradle 添加 RePlugin Plugin Gradle 依賴(若是單獨創建插件工程,則不需要添加注釋1下面的代碼):

buildscript {
  repositories {
    jcenter()
  }
  dependencies {
    classpath 'com.android.tools.build:gradle:2.3.3'
    // 1、添加RePlugin Host Gradle依賴(主工程用)
    classpath 'com.qihoo360.replugin:replugin-host-gradle:2.2.1'
    // 2、添加RePlugin Plugin Gradle依賴(插件工程用)
    classpath 'com.qihoo360.replugin:replugin-plugin-gradle:2.2.1'
  }
}

2、在 app/build.gradle 中添加 replugin-plugin-gradle 插件和 replugin-plugin-lib 依賴:

apply plugin: 'com.android.application'

android {
  ...
}

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

dependencies {
  compile fileTree(dir: 'libs', include: ['*.jar'])
  androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
    exclude group: 'com.android.support', module: 'support-annotations'
  })
  compile 'com.android.support:appcompat-v7:26.+'
  compile 'com.android.support.constraint:constraint-layout:1.0.2'
  compile 'com.qihoo360.replugin:replugin-plugin-lib:2.2.1' // 集成 RePlugin 添加的配置
  testCompile 'junit:junit:4.12'
}

三、管理插件

RePlugin 對插件定義兩種方式一種是外置插件、一種是內置插件。

  1. 外置插件:即從網絡下載或者從SD卡中獲得的,以 .apk 結尾。

  2. 內置插件:內置于 APP 之中,并隨 APP 一并發版,需要將插件 apk 改成 .jar 結尾放入主程序的assets/plugins目錄。

(一)外置插件的安裝(升級)、啟動、卸載

安裝插件:

PluginInfo pluginInfo = RePlugin.install(Environment.getExternalStorageDirectory().getPath().toString() + "/plugin1.apk");

System.out.println(pluginInfo);

同時別忘了添加文件讀寫的權限。 輸出日下:

復制代碼 代碼如下:


10-30 16:10:23.769 20280-20280/cn.codingblock.repluginstudy I/System.out: PInfo { <cn.codingblock.plugin1:1(4)> [APK] [DEX_EXTRACTED] processes=[] js={"pkgname":"cn.codingblock.plugin1","name":"cn.codingblock.plugin1","low":10,"high":10,"ver":1,"verv":2814792716779521,"path":"\/data\/user\/0\/cn.codingblock.repluginstudy\/app_p_a\/-347346251.jar","type":11,"frm_ver":4} dex=/data/data/cn.codingblock.repluginstudy/app_p_od/-347346251.dex nlib=/data/data/cn.codingblock.repluginstudy/app_p_n/-347346251 }

安裝成功了! (升級插件也是用 install() 方法,不可降級,同本版可覆蓋安裝)

啟動插件

先來看一下 RePlugin.java 中啟動插件相關的源碼

/**
 * 創建一個用來定向到插件組件的Intent <p>
 * <p>
 * 推薦用法: <p>
 * <code>
 * Intent in = RePlugin.createIntent("clean", "com.qihoo360.mobilesafe.clean.CleanActivity");
 * </code> <p>
 * 當然,也可以用標準的Android創建方法: <p>
 * <code>
 * Intent in = new Intent(); <p>
 * in.setComponent(new ComponentName("clean", "com.qihoo360.mobilesafe.clean.CleanActivity"));
 * </code>
 *
 * @param pluginName 插件名
 * @param cls    目標全名
 * @return 可以被RePlugin識別的Intent
 * @since 1.0.0
 */
public static Intent createIntent(String pluginName, String cls) {
  Intent in = new Intent();
  in.setComponent(createComponentName(pluginName, cls));
  return in;
}

/**
 * 開啟一個插件的Activity <p>
 * 其中Intent的ComponentName的Key應為插件名(而不是包名),可使用createIntent方法來創建Intent對象
 *
 * @param context Context對象
 * @param intent 要打開Activity的Intent,其中ComponentName的Key必須為插件名
 * @return 插件Activity是否被成功打開?
 * FIXME 是否需要Exception來做?
 * @see #createIntent(String, String)
 * @since 1.0.0
 */
public static boolean startActivity(Context context, Intent intent) {
  // TODO 先用舊的開啟Activity方案,以后再優化
  ComponentName cn = intent.getComponent();
  if (cn == null) {
    // TODO 需要支持Action方案
    return false;
  }
  String plugin = cn.getPackageName();
  String cls = cn.getClassName();
  return Factory.startActivityWithNoInjectCN(context, intent, plugin, cls, IPluginManager.PROCESS_AUTO);
}

根據 RePlugin 的 startActivity() 和 createIntent() 方法注釋中的示例可知,啟動插件需要先用插件的名字和目標Activity的全路徑創建一個 Intent,然后調用 RePlugin.startActviity() 啟動即可:

Intent intent = RePlugin.createIntent("Plugin1", "cn.codingblock.plugin1.MainActivity");

if (!RePlugin.startActivity(MainActivity.this, intent)) {

  Toast.makeText(mContext, "啟動失敗", Toast.LENGTH_LONG).show();

}

點擊按鈕,輸出如下:

10-30 16:21:02.464 20280-20280/cn.codingblock.repluginstudy D/RePlugin.ws001: start activity: intent=Intent { cmp=Plugin1/cn.codingblock.plugin1.MainActivity } plugin=Plugin1 activity=cn.codingblock.plugin1.MainActivity process=-2147483648

10-30 16:21:02.464 20280-20280/cn.codingblock.repluginstudy D/RePlugin.ws001: start activity: intent=Intent { cmp=Plugin1/cn.codingblock.plugin1.MainActivity } plugin=Plugin1 activity=cn.codingblock.plugin1.MainActivity process=-2147483648 download=true

10-30 16:21:02.464 20280-20280/cn.codingblock.repluginstudy D/RePlugin.ws001: plugin=Plugin1 not found, start download ...

10-30 16:21:02.469 20280-20280/cn.codingblock.repluginstudy D/RePlugin.ws001: isNeedToDownload(): V5 file not exists. Plugin = Plugin1

啟動失敗了!(插件名稱確實是:Plugin1,而不是 plugin1 )

把 ==createIntent() 方法的第一參數換成插件的包名 cn.codingblock.plugin1 ==試一試,居然可以了。

但是,注釋總不會這樣赤裸裸的坑我們吧!

卸載插件

RePlugin.uninstall("Plugin1");

點擊卸載,輸入如下:

10-30 16:31:21.988 5006-5006/cn.codingblock.repluginstudy D/RePlugin.ws001: MP.pluginUninstall ... pluginName=Plugin1

10-30 16:31:21.988 5006-5006/cn.codingblock.repluginstudy D/RePlugin.ws001: Not installed. pluginName=Plugin1

沒卸載成功?哈哈,這個簡單,原套路把參數換成包名,果然可以了:

10-30 16:41:46.179 10193-10193/cn.codingblock.repluginstudy D/RePlugin.ws001: MP.pluginUninstall ... pluginName=cn.codingblock.plugin1

10-30 16:41:46.202 10193-10193/cn.codingblock.repluginstudy D/RePlugin.ws001: sendIntent pr=cn.codingblock.repluginstudy intent=Intent { act=ACTION_UNINSTALL_PLUGIN (has extras) }

10-30 16:41:46.203 10193-10193/cn.codingblock.repluginstudy D/RePlugin.ws001: Clear plugin cache. pn=cn.codingblock.plugin1

10-30 16:41:46.204 10193-10193/cn.codingblock.repluginstudy D/RePlugin.ws001: removeInfo plugin table: info=PInfo { <cn.codingblock.plugin1:1(4)> [APK] processes=[] js={"pkgname":"cn.codingblock.plugin1","name":"cn.codingblock.plugin1","low":10,"high":10,"ver":1,"verv":2814792716779521,"path":"\/data\/user\/0\/cn.codingblock.repluginstudy\/app_p_a\/-347346251.jar","type":11,"frm_ver":4,"used":true} dex=/data/user/0/cn.codingblock.repluginstudy/app_p_od/-347346251.dex nlib=/data/user/0/cn.codingblock.repluginstudy/app_p_n/-347346251 } rc=true

10-30 16:41:46.204 10193-10193/cn.codingblock.repluginstudy D/RePlugin.ws001: cached filename: cn.codingblock.plugin1 -> null

10-30 16:41:46.275 10193-10263/cn.codingblock.repluginstudy V/RenderScript: 0xb34e8000 Launching thread(s), CPUs 4

啟動插件那里畢竟在官方教程里面找不到,但是 Plugin.uninstall() 方法傳入插件名即可這可是官方文檔說的,這次不會是官方文檔和源碼注釋合起伙來坑我們把? 經過多次試驗后,有個有趣的發現:對于啟動插件創建 Intent 的createIntent() 方法和 卸載插件的 RePlugin.uninstall() 方法,如果項目是使用繼承 RePluginApplication 方式的話,參數傳包名才生效;如果不是繼承的方式傳插件名才生效!(本人是在一款小米3手機上試驗的,由于并沒有廣泛測試,所以不保證其他手機也是這個套路)這真是奇了葩了!

卸載插件時有一點需要注意:如果插件正在運行,則不會立即卸載插件,而是將卸載訴求記錄下來。直到所有“正在使用插件”的進程結束并重啟后才會生效。(引自官方說明)

(二)內置插件

添加內置插件非常簡單,首先在主工程的 assets 目錄下創建一個 plugins 文件夾,然后將要作為插件的 apk 后綴名改成 .jar 并放入到新建的 plugins 文件夾下,剩下的事情就不用管了,交給 RePlugin 即可,也就說,框架會自動加載插件。

  1. 內置插件無需開發者安裝,啟動方式和外置插件一致,但不可刪除。

  2. 內置插件可通過 RePlugin.install() 升級(需要先將升級包下載好),升級后等同于外置插件。

以上是“Android插件化之RePlugin項目怎么用”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

罗平县| 泰安市| 阿图什市| 兴海县| 石嘴山市| 老河口市| 砚山县| 冀州市| 朝阳市| 广饶县| 彭山县| 潮州市| 板桥市| 普兰县| 罗山县| 大洼县| 台东县| 南漳县| 泽州县| 扎鲁特旗| 江阴市| 双江| 长沙县| 绥化市| 景谷| 天等县| 吉林市| 雷波县| 南皮县| 阿坝县| 桐梓县| 文安县| 连城县| 鹤庆县| 雅安市| 论坛| 鲜城| 鹿泉市| 乌拉特前旗| 锦屏县| 普宁市|