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找到文件;
- 如有覺得講解的不明白的剛好用到插件化框架的可以聯繫我