Android 插件化框架 RePlugin 使用心得

0.先附上一篇原理講解 
http://www.jianshu.com/p/18530be5dcdd
這應該算是給作者打的廣告吧。如有涉及侵權,請通知我立刻刪除。

1.應用場景
Android開發人員不多,又要求使用插件化開發的模式。(簡單點講就是自己需要寫宿主APP,還有N多個插件需要開發)
如下圖:


360官方給的Demo是宿主一個工程,插件一個工程,並且工程的build.gradle文件中添加宿主和插件對應所需要的依賴,多人開發時,每個人或多個人維護一個宿主工程或者插件工程,都沒有什麼問題,但是一個人需要同時維護宿主和多個插件時,來回切換工程調試以及打包就異常頭疼了。。。

2.一個工程配置宿主和插件的所有依賴
    2.1工程的build.gradle文件中添加
  • buildscript {
  •    ...
  •     dependencies {
  •         classpath 'com.android.tools.build:gradle:2.3.3'       
  •         //插件化框架 宿主工程所需依賴
  •         classpath 'com.qihoo360.replugin:replugin-host-gradle:2.2.0'
  •          //插件化框架 插件工程所需依賴
  •         classpath 'com.qihoo360.replugin:replugin-plugin-gradle:2.2.0'
  •         ...
  •     }
  •    ...
  • }
    2.2宿主app的build.gradle文件中添加
    //replugin插件化框架,這一行建議就放在dependencies 的上面,千萬不要放在android{...}的上面
    apply plugin: 'replugin-host-gradle'    
  • dependencies {
  •     compile fileTree(include: ['*.jar'], dir: 'libs')
  •     ...
  •     releaseCompile project(path: ':library的moudle名字', configuration: 'release')
         debugCompile project(path: ':library的moudle名字', configuration: 'debug')
  •     compile 'com.qihoo360.replugin:replugin-host-lib:2.2.0'
  •     ...
  • }
  • 2.3插件moudle對應的build.gradle文件中添加
  • //replugin插件化框架,這一行建議就放在dependencies 的上面,千萬不要放在android{...}的上面
  • apply plugin: 'replugin-plugin-gradle'
  • repluginPluginConfig {
  •     pluginName = "你自己的插件名字"
  •     hostApplicationId = "宿主包名"
  •     hostAppLauncherActivity = "宿主包名.MainActivity"
  • }

  • dependencies {
  •     ...
  •     releaseCompile project(path: ':library的moudle名字', configuration: 'release')
  •     debugCompile project(path: ':library的moudle名字', configuration: 'debug')
  •     compile 'com.qihoo360.replugin:replugin-plugin-lib:2.2.0'
  •     ...
  • }

3.宿主及所有插件使用到的library,這裏建議自己做成一個moudle,配置方法上面的代碼理由了 (library的moudle名字
如有依賴的衝突,在對應moudle中添加
android{
    ...
    configurations.all {
  •     resolutionStrategy.eachDependency { DependencyResolveDetails details ->
  •         def requested = details.requested
  •         if (requested.group == 'com.android.support') {
  •             if (!requested.name.startsWith("multidex")) {
  •                 details.useVersion '25.3.1'//這裏可根據個人需要改成自己想要的版本
  •             }
  •         }
  •     }
  • }
  • ...
}

4.關於調試以及成品包。
調試時有幾個moudle,就安裝幾個應用,調用的地方
  • if (!BuildConfig.DEBUG) {//非Debug,成品包
  •     if (RePlugin.isPluginInstalled("插件包名")) {
  •         //已安裝
  •         Intent intentHasInstall = RePlugin.createIntent("插件包名" ,
  •                 "插件包名.MainActivity");
  •         intentHasInstall.putExtras(bundle);
  •         RePlugin.startActivity(mContext, intentHasInstall);
  •      }else{//沒有安裝,自己寫下載的代碼}
  • }else {//debug模式
  • Intent intent1 = new Intent();
  • intent1.setComponent(new ComponentName("插件包名", "插件包名.MainActivity"));
  • intent1.putExtras(bundle);
  • startActivity(intent1);
  • }

5.關於FileProvider
    5.1這個首先公用library的那個moudle要有一個公用的Utils,並且每個moudle(插件或宿主)都初始化此工具類
  • public final class Utils {    
  •     private static Context context;
  •     /**
  •      * 初始化工具類
  •      *
  •      * @param context 上下文
  •      */
  •     public static void init(@NonNull final Context context) {
  •         Utils.context = context.getApplicationContext();
  •     }

  •     /**
  •      * 獲取ApplicationContext
  •      *
  •      * @return ApplicationContext
  •      */
  •     public static Context getContext() {
  •         if (context != null) return context;
  •         throw new NullPointerException("請保證你已經初始化過!");
  •     }
  • }
  • 5.2每個moudle(插件或宿主)的manifest文件中都添加
  • <provider
  •     android:name="android.support.v4.content.FileProvider"
  •     android:authorities="對應moudle的包名.fileProvider"
  •     android:grantUriPermissions="true"
  •     android:exported="false">
  •     <meta-data
  •         android:name="android.support.FILE_PROVIDER_PATHS"
  •         android:resource="@xml/file_paths" />
  • </provider>

  • 需使用FileProvider時:以獲取文件URI爲例
  • File mTmpFile = new File("你自己的文件路徑");
  • Uri uri= FileProvider.getUriForFile(Utils.getContext(), Utils.getContext().getPackageName() + ".fileProvider", mTmpFile);

  • Utils.getContext().getPackageName(),重點是這個方法;
  • a.debug時,獲取的對應插件的包名,通過每個moudle的manifest配置中對應的fileProvider找到文件;
  • b.release時,Utils.getContext().getPackageName()獲取的只會是宿主的fileProvider,這時自然可以通過宿主manifest配置對應的fileProvider找到文件;

  • 如有覺得講解的不明白的剛好用到插件化框架的可以聯繫我

發佈了42 篇原創文章 · 獲贊 26 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章