天天看點

Android全面插件化方案-RePlugin踩坑1.什麼是RePlugin?2.RePlugin有什麼用?3.RePlugin官方介紹4.SO?怎麼用?總結

1.什麼是RePlugin?

在Android開發領域,有關插件化的讨論一直熱度不減。目前市面上的插件化方案雖然很多,但多數隻能實作某些功能的插件化,距離開發者的預期尚有相當差距。對此,在近期GMTC全球移動技術大會上,360手機衛士主程式架構負責人張炅軒宣布,360的插件化架構RePlugin已經可以實作“全面插件化”,同時具有出色的穩定性和靈活性,可适用于各種類型的應用上。

“RePlugin預計7月份開源,這将是我們獻給安卓世界最好的禮物。”360如是說。

2.RePlugin有什麼用?

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

3.RePlugin官方介紹

其主要優勢有:

  • 極其靈活:主程式無需更新(無需在Manifest中預埋元件),即可支援新增的四大元件,甚至全新的插件
  • 非常穩定:Hook點僅有一處(ClassLoader),無任何Binder Hook!如此可做到其崩潰率僅為“萬分之一”,并完美相容市面上近乎所有的Android ROM
  • 特性豐富:支援近乎所有在“單品”開發時的特性。包括靜态Receiver、Task-Affinity坑位、自定義Theme、程序坑位、AppCompat、DataBinding等
  • 易于內建:無論插件還是主程式,隻需“數行”就能完成接入
  • 管理成熟:擁有成熟穩定的“插件管理方案”,支援插件安裝、更新、解除安裝、版本管理,甚至包括程序通訊、協定版本、安全校驗等
  • 數億支撐:有360手機衛士龐大的數億使用者做支撐,三年多的殘酷驗證,確定App用到的方案是最穩定、最适合使用的

截止2017年6月底,RePlugin的:

特性 描述
插件數 103(核心57個)
插件占應用比 高達83%
年發版次數 高達596次(工作日均2次)
崩潰率 萬分之一(0.01%),極低
時間 2014年應用,3年驗證

目前360公司幾乎所有的億級使用者量的APP,以及多款主流第三方APP,都采用了RePlugin方案。

有關RePlugin的詳細介紹,請

點選這裡閱讀《RePlugin 官方 WiKi》

還支援以下特性

元件 四大元件(含靜态Receiver)
更新無需改主程式Manifest 完美支援
Android特性 支援近乎所有(包括SO庫等)
TaskAffinity & 多程序 支援(坑位方案)
插件類型 支援自帶插件(自識别)、外置插件
插件間耦合 支援Binder、Class Loader、資源等
程序間通訊 支援同步、異步、Binder、廣播等
自定義Theme & AppComat 支援
DataBinding
安全校驗
資源方案 獨立資源 + Context傳遞(相對穩定)
Android 版本 API Level 9+ (2.3及以上)

願景

讓插件化能飛入尋常應用家,做到穩定、靈活、自由,大小項目兼用。

RePlugin 架構圖

4.SO?怎麼用?

ok,看完了官方介紹給我們畫的大餅,現在看看怎麼實作它,是的,坑來了。。

主程式的配置,這裡就不多說了。。

将RePlugin接入到您的主程式

,官方文檔描述的很清楚,也沒有什麼奇奇怪怪的錯誤。

主要來說說如何

開發新的 RePlugin 插件

,從RePlugin的Wiki我們可以看到,好簡單呀,就三步嘛,來吧。

然後我們碰到了.........

問題一:Gradle配置出錯
Android全面插件化方案-RePlugin踩坑1.什麼是RePlugin?2.RePlugin有什麼用?3.RePlugin官方介紹4.SO?怎麼用?總結

EXCUSE ME?那裡有問題?再看看文檔,沒啥特别的描述呀。

然後,我在Issues裡找到了官方項目組說的這一句:“這個要自動讀取前面build.gradle的配置内容,如果放在前面,會讀為空。我們内部讨論過這個問題,如果要想自由放置就得傳參配置。當時考慮到盡量減少傳參配置就約定俗成讓放在檔案末尾。你可以看

demo1

。”

好吧,既然如此能不能提一句隻能放在檔案末尾啊!

你是360,你老大,我改!

Android全面插件化方案-RePlugin踩坑1.什麼是RePlugin?2.RePlugin有什麼用?3.RePlugin官方介紹4.SO?怎麼用?總結

??按你說的還不行??

然後,我在Issues裡看到了吃瓜群衆說的這一句:“你試試把

apply plugin: 'replugin-plugin-gradle'

放在<

apply plugin: 'com.android.application'

之前就好了,我的就是這樣好使的,你試試?”

抱着試一試的心态,然後我發現...成功了??說好的讀取配置内容呢?說好的會讀為空呢?

OK,按照官方文檔,各項都配置完成,我們繼續進行。。

插件界面很簡單:

Android全面插件化方案-RePlugin踩坑1.什麼是RePlugin?2.RePlugin有什麼用?3.RePlugin官方介紹4.SO?怎麼用?總結

插件單獨運作一下,ok,沒問題。

好的,接下來走一下内置插件的流程,将插件項目build一個apk出來,字尾改成jar,導入主程式assets的plugins内,

主程式界面也很簡單,就一個HelloRePlugin的TextView,給TextView設定一個點選事件

tv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                RePlugin.startActivity(MainActivity.this, RePlugin.createIntent("aap2", "com.zzcn77.replugindemo2.MainActivity"));
            }
        });           

問題二:主題出錯

點選HelloRePlugin,程式崩潰。

Android全面插件化方案-RePlugin踩坑1.什麼是RePlugin?2.RePlugin有什麼用?3.RePlugin官方介紹4.SO?怎麼用?總結

主題錯了?繼承的是Activity啊,有主題啊,單獨運作沒有錯啊。。

自此,我開始多番嘗試之路,改了n個主題發現沒有用,氣的我,直接把

apply plugin: 'replugin-plugin-gradle'

我把這句去掉了,運作。。程式調起成功了。。。我的天哪

詭異的一幕出現了,吊起的插件Acitivity顯示界面:

Android全面插件化方案-RePlugin踩坑1.什麼是RePlugin?2.RePlugin有什麼用?3.RePlugin官方介紹4.SO?怎麼用?總結

???這個界面哪來的?,這不是我的插件界面啊。。

奇怪的是,插件的activity的onCreate也走了。那我的界面去哪了?

是不是因為我删去了

apply plugin: 'replugin-plugin-gradle'

,是以出現問題了?,還是加上吧,再看看主題出錯有沒有其他解決方法。------加上,buildApk,導入主程式,運作主程式,點選HelloRePlugin,調起,成功了?!,唉?你不是主題有問題的嗎?你不是主題有問題的嗎?你不是主題有問題的嗎?好吧,,雖然調起成功,可是還沒完,打開的activity界面依然如上。

Android全面插件化方案-RePlugin踩坑1.什麼是RePlugin?2.RePlugin有什麼用?3.RePlugin官方介紹4.SO?怎麼用?總結

然後我們發現了.........

問題三: Didn't find class "com.qihoo360.plugin.app2.Entry"

Didn't find class "com.qihoo360.plugin.app2.Entry" on path: DexPathList[[zip file "/data/user/0/com.replugindemo/app_plugins_v3/app2-10-10-101.jar"],nativeLibraryDirectories=[/data/user/0/com.replugindemo/app_plugins_v3_libs/app2-10-10-101, /vendor/lib, /system/lib]]
 java.lang.ClassNotFoundException: Didn't find class "com.qihoo360.plugin.app2.Entry" on path: DexPathList[[zip file "/data/user/0/com.replugindemo/app_plugins_v3/app2-10-10-101.jar"],nativeLibraryDirectories=[/data/user/0/com.replugindemo/app_plugins_v3_libs/app2-10-10-101, /vendor/lib, /system/lib]]
                 at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:56)
                 at java.lang.ClassLoader.loadClass(ClassLoader.java:511)
                 at com.qihoo360.replugin.PluginDexClassLoader.loadClass(PluginDexClassLoader.java:76)
                 at java.lang.ClassLoader.loadClass(ClassLoader.java:469)
                 at com.qihoo360.loader2.Loader.loadEntryMethod2(Loader.java:419)
                 at com.qihoo360.loader2.Plugin.loadEntryLocked(Plugin.java:857)
                 at com.qihoo360.loader2.Plugin.doLoad(Plugin.java:822)
                 at com.qihoo360.loader2.Plugin.loadLocked(Plugin.java:621)
                 at com.qihoo360.loader2.Plugin.load(Plugin.java:432)
                 at com.qihoo360.loader2.PmBase.loadPlugin(PmBase.java:1033)
                 at com.qihoo360.loader2.PmBase.loadAppPlugin(PmBase.java:1018)
                 at com.qihoo360.loader2.PmLocalImpl.getActivityInfo(PmLocalImpl.java:443)
                 at com.qihoo360.loader2.PmLocalImpl.loadPluginActivity(PmLocalImpl.java:319)
                 at com.qihoo360.loader2.PmInternalImpl.startActivity(PmInternalImpl.java:230)
                 at com.qihoo360.loader2.PmLocalImpl.startActivity(PmLocalImpl.java:307)
                 at com.qihoo360.i.Factory.startActivityWithNoInjectCN(Factory.java:324)
                 at com.qihoo360.replugin.RePlugin.startActivity(RePlugin.java:236)
                 at com.zzcn77.replugindemo.MainActivity$1.onClick(MainActivity.java:24)
                 at android.view.View.performClick(View.java:5198)
                 at android.view.View$PerformClick.run(View.java:21147)
                 at android.os.Handler.handleCallback(Handler.java:739)
                 at android.os.Handler.dispatchMessage(Handler.java:95)
                 at android.os.Looper.loop(Looper.java:148)
                 at android.app.ActivityThread.main(ActivityThread.java:5417)
                 at java.lang.reflect.Method.invoke(Native Method)
                 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
                 Suppressed: java.lang.ClassNotFoundException: com.qihoo360.plugin.app2.Entry
                 at java.lang.Class.classForName(Native Method)
                 at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
                 at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
                 at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
                     ... 25 more
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available           

為什麼?

再看看官方文檔,遺漏什麼了?沒有啊。

再看看官方文檔,還有沒看到的?沒有啊。

再回想一下整個流程,gradle出錯,主題樣式錯誤,

Didn't find class "com.qihoo360.plugin.app2.Entry

對,主題樣式,這一環并沒有真正的解決。

找不到主題?application裡面配置的有主題呀。

把application的統一主題去掉,分别給每個activity配置主題。

再來一次,buildApk,導入主程式,運作主程式,調起,成功了!!!完美運作!!!

掌聲,掌聲,掌聲

總結

首次的整個內建過程,也算是踩坑無數,樂趣多多啊。希望Replugin項目組在後續的版本中能夠提供更多的功能,以及更高的穩定性,當然也希望官方的Wiki再友好一點,能對一些內建規範的描述更詳細點呗。不過好用是真的。

作為行業大哥360開源出來的全面化插件機制,以及在360衆多項目中的實踐,Replugin的功能性,肯定是毋庸置疑的,應用場景也必将十分廣泛。相信在未來很多項目中,會見到它的身影。

Android全面插件化方案-RePlugin踩坑1.什麼是RePlugin?2.RePlugin有什麼用?3.RePlugin官方介紹4.SO?怎麼用?總結

繼續閱讀