[Android 插件化(一)] DynamicLoadApk的用法
1 簡介
Android大型項目中為了減小apk的體積,可以采用插件化的方法,即一些不常用的功能獨立成插件,當用戶需要的使用的時候再從服務器上下載回來,動態(tài)加載。這樣就避免了為了滿足所有用戶需求而把功能全部打包到apk,導致apk體積的膨脹。所謂的插件,其實也是一個apk,但是一般都依賴正式對外發(fā)布的app,也叫宿主。本篇不討論插件化的原理和實現難點,只介紹怎么使用以及優(yōu)缺點。?
Android插件化常用實現方案有兩種:
(1) DynamicLoadApk?
(2) DroidPlugin
這兩個是目前比較主流的Android插件化實現方案,在Github的星星數很高,兩者的Github地址如下:
DynamicLoadApk的Github地址:https://github.com/singwhatiwanna/dynamic-load-apk?
DroidPlugin的Github地址:https://github.com/Qihoo360/DroidPlugin
2 特點
(1) DynamicLoadApk是由團隊維護的,但是目前已經很長時間沒有更新了,途牛用的就是這個插件化框架?
優(yōu)點:
- 插件不依賴宿主,對宿主開發(fā)者透明,提供三種依賴方式
- 宿主和插件可以頻繁交互,啟動時間短
缺點:
- 插件apk必須實現DLBasePluginActivity,屬于侵入式的,以及不支持service
- 宿主調用插件和插件內部的相互調用都要使用DL提供的方法,而不能使用Android原生的api,例如:啟動Activity
- 插件開發(fā)有一套規(guī)定,因此造成插件開發(fā)門檻高,學習成本高
(2) DroidPlugin是360公司開源的一個框架,已經在360手機助手上使用?
優(yōu)點:
- 宿主和插件完全隔離,插件不依賴宿主,可以獨立安裝運行
- 低入侵設計,插件不需要繼承任何類
- 插件apk和普通apk一樣的,所以插件開發(fā)沒有門檻
- 有大公司維護,有360手機助手這樣的商用app在使用
缺點:
- 插件啟動速度太慢,而且宿主只能調用插件的LaunchMode的Activity,不能調用其他Activity
3 使用方法
(1) 導入Dynamic-load-apk中的lib。?
下載Dynamic-load-apk后解壓,在Android Studio中新建工程DLTest(自己命名) –> new –> import module –>選擇lib所在的目錄:dynamic-load-apk-master\DynamicLoadApk\lib
(2) 新建插件模塊plugin,宿主模塊host,這兩個模塊都是application, 最后都要生成apk的。項目目錄如下:
編譯lib模塊,命令是build菜單–>make module lib,目的是為了獲得生成的jar文件,jar文件所在位置是lib\build\intermediates\bundles\debug\class.jar,復制jar文件重命名為lib.jar
(3) 導入lib.jar到plugin項目的libs目錄下,開發(fā)plugin項目,注意Activity要繼承DLBasePluginActivity ,R.layout.activity_test上就一個TextView,顯示”這個界面來自Plugin”?
插件項目Plugin的MainActivity:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
注意:plugin模塊的buidle.gradle需要修改為如下:
dependencies {provided fileTree(dir: 'libs', include: ['*.jar'])......... }- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
provided 意思是編譯時候使用,但不打包到APK中,這樣做是因為我們的宿主項目host中已經包含了lib.jar,如果插件中也包含的話就會報找不到plugin中的Activity的錯,原因是兩個包重復,必須要用host中的DL框架來加載plugin,而不是plugin自帶的DL框架
(4) 導入lib.jar到host項目的libs目錄下,開發(fā)host項目?
host項目的MainActivity:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
host的activity_main.xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"><TextView android:id="@+id/tv_tip"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="沒有檢測到插件"/><Button android:id="@+id/btn_test"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@id/tv_tip"android:layout_marginTop="10dp"android:text="測試調用插件"/></RelativeLayout>- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
注意:Host的AndroidManifest.xml中需要額外的聲明幾個DL框架中的類,否則運行時候找不到Activity.
Host的AndroidManifest.xml:
<manifest package="com.host"xmlns:android="http://schemas.android.com/apk/res/android"><uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><application android:allowBackup="true"android:icon="@mipmap/ic_launcher"android:label="@string/app_name"android:supportsRtl="true"android:theme="@style/AppTheme"><activity android:name=".MainActivity"android:label="@string/app_name"android:theme="@style/AppTheme.NoActionBar"><intent-filter><action android:name="android.intent.action.MAIN"/><category android:name="android.intent.category.LAUNCHER"/></intent-filter></activity><activity android:name="com.ryg.dynamicload.DLProxyActivity"android:label="@string/app_name"><intent-filter><action android:name="com.ryg.dynamicload.proxy.activity.VIEW"/><category android:name="android.intent.category.DEFAULT"/></intent-filter></activity><activity android:name="com.ryg.dynamicload.DLProxyFragmentActivity"android:label="@string/app_name"><intent-filter><action android:name="com.ryg.dynamicload.proxy.fragmentactivity.VIEW"/><category android:name="android.intent.category.DEFAULT"/></intent-filter></activity><service android:name="com.ryg.dynamicload.DLProxyService"/></application></manifest>- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
(5) 編譯plugin項目,將生成的plugin-debug.apk文件放入/mnt/sdcard/DynaminLoadHost目錄下,然后運行Host,運行結果如下:?
4 總結
- 1 宿主和插件沒有任何聯系,但是插件需要繼承DLBasePluginActivity,這個不太友好
- 2 侵入式的,對插件apk的開發(fā)限制太多,例如:必須繼承DLBasePluginActivity,啟動時候必須調用startPluginActivity(new?
DLIntent(getPackageName(),TestActivity.class)) - 3 這個框架學習成本高,限制多,聯調不方便,不建議使用
- 4 目前比較好的插件有360公司的DroidPlugin, 以及類似友盟的第三方解決方案ApkPlug
5 擴展
1 Android Studio中可以不用jar文件嗎?
Host可以,但plugin不可以。宿主項目可以依賴于lib項目,但是plugin必須使用jar文件,原因參見下面第3條
2 Host項目如何直接依賴lib項目,而不用jar文件?
修改host文件的build.gradle文件
dependencies {compile project(':lib')..... }- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
修改lib的build.gradle文件,不修改的話就會和host項目中的support-v4包沖突
dependencies {provided fileTree(dir: 'libs', include: ['*.jar']) }- 1
- 2
- 3
- 1
- 2
- 3
3 為什么plugin必須使用jar文件?
Plugin不能將lib模塊打包到apk中,所以不能使用compile,只能使用provided,所以如果不用jar則plugin模塊的build.gradle只能如下:
dependencies {provided project(':lib')..... }- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
呵呵,可惜這樣是不行的,project只能使用compile ,不能使用provided ,百度了半天沒有解決這個問題,如果你有辦法歡迎留言
6 參考博客:
(1)?http://blog.csdn.net/singwhatiwanna/article/details/40283117
7 轉載請注明來自“梧桐那時雨”的博客:http://blog.csdn.net/fuchaosz/article/details/51056947
總結
以上是生活随笔為你收集整理的[Android 插件化(一)] DynamicLoadApk的用法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用DroidPlugin实践应用的插件
- 下一篇: [Android 插件化(二)] Dro