Android插件實例——360 DroidPlugin詳解

jopen 8年前發布 | 27K 次閱讀 Android開發 移動開發

在中國找到錢不難,但你的一個點子不意味著是一個創業。你談一個再好的想法,比如我今天談一個創意說,新浪為什么不收購GOOGLE呢?這個創意很好。新浪一收購GOOGLE,是不是新浪就變成老大了?你從哪兒弄來錢?怎么去整合GOOGLE呢;

之前寫過有關于Android 插件方向的文章,解析了一下Android的插件原理與運行方式。很多小伙伴都問我,為什么不把我制作的插件放到Github上,讓大家共享一下。

我只能說,大哥啊,這個插件是我在公司研發的時候制作的,商業機密,不能開源啊。

剛好,最近逛github的時候,看到了奇虎360手機助手團隊的一個Android插件開源項目。今天,我們就具體的分析一下它的原理與實現邏輯。讓大家更清楚的了解,一個Android插件的構造。


360 Android 插件項目 DroidPlugin

這個框架是奇虎360手機助手團隊,最近在github上開源出來的Android插件框架。這種精神是很值得鼓勵的。

github地址為: https://github.com/Qihoo360/DroidPlugin

好,一下純屬引入了官方的說明:

說明

DroidPlugin是360手機助手在Android系統上實現了一種新的插件機制: 
它可以在無需安裝、修改的情況下運行APK文件,此機制對改進大型APP的架構,實現多團隊協作開發具有一定的好處。

特點

  1. 支持Androd 2.3以上系統

  2. 插件APK完全不需做任何修改,可以獨立安裝運行、也可以做插件運行。要以插件模式運行某個APK,你無需重新編譯、無需知道其源碼。

  3. 插件的四大組件完全不需要在Host程序中注冊,支持Service、Activity、BroadcastReceiver、ContentProvider四大組件

  4. 插件之間、Host程序與插件之間會互相認為對方已經”安裝”在系統上了。

  5. API低侵入性:極少的API。HOST程序只是需要一行代碼即可集成Droid Plugin

  6. 超強隔離:插件之間、插件與Host之間完全的代碼級別的隔離:不能互相調用對方的代碼。通訊只能使用Android系統級別的通訊方法。

  7. 支持所有系統API 資源完全隔離:插件之間、與Host之間實現了資源完全隔離,不會出現資源竄用的情況。

  8. 實現了進程管理,插件的空進程會被及時回收,占用內存低。

  9. 插件的靜態廣播會被當作動態處理,如果插件沒有運行(即沒有插件進程運行),其靜態廣播也永遠不回被觸發。

那么這個插件框架,和我們之前所說的插件框架,有什么特點?它的實現方式是什么樣的?這里我們從源碼來分析一下。


插件原理——DexClassLoader

之前,我們也討論過,一個Android的apk插件是個什么形式。主要是三點,我總結如下: 
- DexLoader動態的加載dex文件進入vm 
- AndroidManifest.xml中預注冊一些將要使用的四大組件(方法很low,其實有更好的) 
- 針對四大組件,分別進行抽象代理,proxy 
- Apk安裝還需要單獨處理native的,so文件。 
- 宿主需要處理好Resource,保證R文件的正確使用。

360這個Android插件系統是否和我們之前討論的類似呢?這里我們從IPluginManagerImpl.java文件中,我們能夠看到其真正的安裝apk插件的方法——installPackage。具體方法詳解如下所示:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    <span class="hljs-javadoc" style="color: rgb(136, 0, 0); box-sizing: border-box;">/**
      *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> filepath 插件Apk的路徑
      *<span class="hljs-javadoctag" style="color: rgb(102, 0, 102); box-sizing: border-box;"> @param</span> flags Flag
      * 
      */</span>
    <span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> <span class="hljs-title" style="box-sizing: border-box;">installPackage</span>(String filepath, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> flags) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> RemoteException {
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//install plugin</span>
        String apkfile = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
            <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 驗證合法性</span>
            PackageManager pm = mContext.getPackageManager();
            PackageInfo info = pm.getPackageArchiveInfo(filepath, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (info == <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> PackageManagerCompat.INSTALL_FAILED_INVALID_APK;
            }

            apkfile = PluginDirHelper.getPluginApkFile(mContext, info.packageName);

            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> ((flags & PackageManagerCompat.INSTALL_REPLACE_EXISTING) != <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 新安裝的插件</span>

                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 停止,刪除插件的緩存</span>
                forceStopPackage(info.packageName);
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mPluginCache.containsKey(info.packageName)) {
                    deleteApplicationCacheFiles(info.packageName, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>);
                }
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(apkfile).delete();
                Utils.copyFile(filepath, apkfile);
                PluginPackageParser parser = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> PluginPackageParser(mContext, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(apkfile));
                parser.collectCertificates(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
                PackageInfo pkgInfo = parser.getPackageInfo(PackageManager.GET_PERMISSIONS | PackageManager.GET_SIGNATURES);

                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 驗證申請的permission,宿主中是否存在,不存在不讓安裝。</span>
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (pkgInfo != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && pkgInfo.requestedPermissions != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && pkgInfo.requestedPermissions.length > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (String requestedPermission : pkgInfo.requestedPermissions) {
                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> b = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
                            b = pm.getPermissionInfo(requestedPermission, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
                        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (NameNotFoundException e) {
                        }
                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!mHostRequestedPermission.contains(requestedPermission) && b) {
                            Log.e(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"No Permission %s"</span>, requestedPermission);
                            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(apkfile).delete();
                            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> PluginManager.INSTALL_FAILED_NO_REQUESTEDPERMISSION;
                        }
                    }
                }

                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 保存簽名</span>
                saveSignatures(pkgInfo);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//                if (pkgInfo.reqFeatures != null && pkgInfo.reqFeatures.length > 0) {</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//                    for (FeatureInfo reqFeature : pkgInfo.reqFeatures) {</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//                        Log.e(TAG, "reqFeature name=%s,flags=%s,glesVersion=%s", reqFeature.name, reqFeature.flags, reqFeature.getGlEsVersion());</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//                    }</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//                }</span>

                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 拷貝插件中的native庫文件。</span>
                copyNativeLibs(mContext, apkfile, parser.getApplicationInfo(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>));
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// opt Dex文件,并使用DexClassLoader動態的載入類代碼。</span>
                dexOpt(mContext, apkfile, parser);
                mPluginCache.put(parser.getPackageName(), parser);

                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 回調函數,通知插件安裝</span>
                mActivityManagerService.onPkgInstalled(mPluginCache, parser, parser.getPackageName());
                sendInstalledBroadcast(info.packageName);
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> PackageManagerCompat.INSTALL_SUCCEEDED;
            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
                <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// 以下是插件,覆蓋安裝的過程。即更新的過程。與新安裝類似。不做解釋了。</span>

                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (mPluginCache.containsKey(info.packageName)) {
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> PackageManagerCompat.INSTALL_FAILED_ALREADY_EXISTS;
                } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">else</span> {
                    forceStopPackage(info.packageName);
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(apkfile).delete();
                    Utils.copyFile(filepath, apkfile);
                    PluginPackageParser parser = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> PluginPackageParser(mContext, <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(apkfile));
                    parser.collectCertificates(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>);
                    PackageInfo pkgInfo = parser.getPackageInfo(PackageManager.GET_PERMISSIONS | PackageManager.GET_SIGNATURES);
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (pkgInfo != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && pkgInfo.requestedPermissions != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span> && pkgInfo.requestedPermissions.length > <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) {
                        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">for</span> (String requestedPermission : pkgInfo.requestedPermissions) {
                            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">boolean</span> b = <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">false</span>;
                            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">try</span> {
                                b = pm.getPermissionInfo(requestedPermission, <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>) != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>;
                            } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (NameNotFoundException e) {
                            }
                            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (!mHostRequestedPermission.contains(requestedPermission) && b) {
                                Log.e(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"No Permission %s"</span>, requestedPermission);
                                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(apkfile).delete();
                                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> PluginManager.INSTALL_FAILED_NO_REQUESTEDPERMISSION;
                            }
                        }
                    }
                    saveSignatures(pkgInfo);
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//                    if (pkgInfo.reqFeatures != null && pkgInfo.reqFeatures.length > 0) {</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//                        for (FeatureInfo reqFeature : pkgInfo.reqFeatures) {</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//                            Log.e(TAG, "reqFeature name=%s,flags=%s,glesVersion=%s", reqFeature.name, reqFeature.flags, reqFeature.getGlEsVersion());</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//                        }</span>
<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//                    }</span>

                    copyNativeLibs(mContext, apkfile, parser.getApplicationInfo(<span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>));
                    dexOpt(mContext, apkfile, parser);
                    mPluginCache.put(parser.getPackageName(), parser);
                    mActivityManagerService.onPkgInstalled(mPluginCache, parser, parser.getPackageName());
                    sendInstalledBroadcast(info.packageName);
                    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> PackageManagerCompat.INSTALL_SUCCEEDED;
                }
            }
        } <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">catch</span> (Exception e) {
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (apkfile != <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">null</span>) {
                <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> File(apkfile).delete();
            }
            handleException(e);
            <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">return</span> PackageManagerCompat.INSTALL_FAILED_INTERNAL_ERROR;
        }
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li><li style="box-sizing: border-box; padding: 0px 5px;">79</li><li style="box-sizing: border-box; padding: 0px 5px;">80</li><li style="box-sizing: border-box; padding: 0px 5px;">81</li><li style="box-sizing: border-box; padding: 0px 5px;">82</li><li style="box-sizing: border-box; padding: 0px 5px;">83</li><li style="box-sizing: border-box; padding: 0px 5px;">84</li><li style="box-sizing: border-box; padding: 0px 5px;">85</li><li style="box-sizing: border-box; padding: 0px 5px;">86</li><li style="box-sizing: border-box; padding: 0px 5px;">87</li><li style="box-sizing: border-box; padding: 0px 5px;">88</li><li style="box-sizing: border-box; padding: 0px 5px;">89</li><li style="box-sizing: border-box; padding: 0px 5px;">90</li><li style="box-sizing: border-box; padding: 0px 5px;">91</li><li style="box-sizing: border-box; padding: 0px 5px;">92</li><li style="box-sizing: border-box; padding: 0px 5px;">93</li><li style="box-sizing: border-box; padding: 0px 5px;">94</li><li style="box-sizing: border-box; padding: 0px 5px;">95</li><li style="box-sizing: border-box; padding: 0px 5px;">96</li><li style="box-sizing: border-box; padding: 0px 5px;">97</li><li style="box-sizing: border-box; padding: 0px 5px;">98</li><li style="box-sizing: border-box; padding: 0px 5px;">99</li><li style="box-sizing: border-box; padding: 0px 5px;">100</li><li style="box-sizing: border-box; padding: 0px 5px;">101</li><li style="box-sizing: border-box; padding: 0px 5px;">102</li><li style="box-sizing: border-box; padding: 0px 5px;">103</li><li style="box-sizing: border-box; padding: 0px 5px;">104</li><li style="box-sizing: border-box; padding: 0px 5px;">105</li><li style="box-sizing: border-box; padding: 0px 5px;">106</li><li style="box-sizing: border-box; padding: 0px 5px;">107</li><li style="box-sizing: border-box; padding: 0px 5px;">108</li><li style="box-sizing: border-box; padding: 0px 5px;">109</li><li style="box-sizing: border-box; padding: 0px 5px;">110</li><li style="box-sizing: border-box; padding: 0px 5px;">111</li><li style="box-sizing: border-box; padding: 0px 5px;">112</li><li style="box-sizing: border-box; padding: 0px 5px;">113</li><li style="box-sizing: border-box; padding: 0px 5px;">114</li><li style="box-sizing: border-box; padding: 0px 5px;">115</li><li style="box-sizing: border-box; padding: 0px 5px;">116</li></ul>

以下是dexOpt方法的具體內容,簡單的貼一下,不做說明了。

<code class="hljs avrasm has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;">    private void dexOpt(Context hostContext, String apkfile, PluginPackageParser parser) throws Exception {
        String packageName = parser<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getPackageName</span>()<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        String optimizedDirectory = PluginDirHelper<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getPluginDalvikCacheDir</span>(hostContext, packageName)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        String libraryPath = PluginDirHelper<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getPluginNativeLibraryDir</span>(hostContext, packageName)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
        ClassLoader classloader = new PluginClassLoader(apkfile, optimizedDirectory, libraryPath, ClassLoader<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getSystemClassLoader</span>())<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
//        DexFile dexFile = DexFile<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.loadDex</span>(apkfile, PluginDirHelper<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getPluginDalvikCacheFile</span>(mContext, parser<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getPackageName</span>()), <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">0</span>)<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
//        Log<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.e</span>(TAG, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"dexFile=%s,1=%s,2=%s"</span>, dexFile, DexFile<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.isDexOptNeeded</span>(apkfile), DexFile<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.isDexOptNeeded</span>(PluginDirHelper<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getPluginDalvikCacheFile</span>(mContext, parser<span class="hljs-preprocessor" style="color: rgb(68, 68, 68); box-sizing: border-box;">.getPackageName</span>())))<span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">;</span>
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

占坑——預注冊四大組件

360 Android插件DroidPlugin中,主要的四大組件代理方式還是占坑。這里所說的占坑就是指,在AndroidManifest.xml中預注冊以下可能會用到的信息。

ps.這個方式不是特別好。如果大家對為什么要預注冊這個問題不是很了解,或者不了解為什么不好。可以看一下我的博客,我會持續更新。http://blog.csdn.net/yzzst/article/details/45582315

OK,下面是我們從DroidPlugin的Test項目中,截取出來的AndroidManifest.xml代碼,我們看看什么叫占坑,怎么占坑。代碼如下所示:

<code class="language-xml hljs  has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"> <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">application
</span>        <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:icon</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@drawable/ic_launcher"</span>
        <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:label</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@string/app_name"</span>
        <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:theme</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@style/AppTheme"</span> ></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">activity
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".MyActivity"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:label</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@string/app_name"</span> ></span>
            <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">intent-filter</span>></span>
                <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">action</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"android.intent.action.MAIN"</span> /></span>

                <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">category</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"android.intent.category.LAUNCHER"</span> /></span>
            <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">intent-filter</span>></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">activity</span>></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">activity
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".ServiceTest1"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:label</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"服務測試"</span> /></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">activity
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".ContentProviderTest"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:label</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"ContentProvider測試"</span> /></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">activity
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".BroadcastReceiverTest"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:label</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"廣播測試"</span> /></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">activity
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".NotificationTest"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:label</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"通知測試"</span> /></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">activity
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".ServiceTest2"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:label</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"多進程服務測試"</span> /></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">activity
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".ContentProviderTest2"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:label</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"多進程ContentProvider測試"</span> /></span>

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- 預聲明不同process的Service --></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">service</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".Service1"</span> /></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">service</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".Service2"</span> /></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">service
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".Service3"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:process</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">":Process2"</span> /></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">service
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".Service4"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:process</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">":Process2"</span> /></span>

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- 預聲明兩種process的Provider --></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">provider
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".MyContentProvider1"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:authorities</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"com.example.ApiTest.MyContentProvider1"</span> /></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">provider
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".MyContentProvider2"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:authorities</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"com.example.ApiTest.MyContentProvider2"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:process</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">":Process2"</span> /></span>

        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">receiver</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".StaticBroadcastReceiver"</span> ></span>
            <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">intent-filter</span>></span>
                <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">action</span> <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"com.example.ApiTest.StaticBroadcastReceiver"</span> /></span>
            <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">intent-filter</span>></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">receiver</span>></span>

        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;"><!-- 預聲明各種launchMode的Activity --></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">activity
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".StandardActivity"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:label</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@string/title_activity_standard"</span> /></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">activity
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".SingleTopActivity"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:label</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@string/title_activity_single_top"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:launchMode</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"singleTop"</span> /></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">activity
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".SingleTaskActivity"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:label</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@string/title_activity_single_task"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:launchMode</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"singleTask"</span> /></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">activity
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".SingleInstanceActivity"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:label</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@string/title_activity_single_instance"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:launchMode</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"singleInstance"</span> /></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"><<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">activity
</span>            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:name</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">".ActivityTestActivity"</span>
            <span class="hljs-attribute" style="box-sizing: border-box; color: rgb(102, 0, 102);">android:label</span>=<span class="hljs-value" style="box-sizing: border-box; color: rgb(0, 136, 0);">"@string/title_activity_activity_test"</span> ></span>
        <span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">activity</span>></span>
<span class="hljs-tag" style="color: rgb(0, 102, 102); box-sizing: border-box;"></<span class="hljs-title" style="box-sizing: border-box; color: rgb(0, 0, 136);">application</span>></span></code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li><li style="box-sizing: border-box; padding: 0px 5px;">34</li><li style="box-sizing: border-box; padding: 0px 5px;">35</li><li style="box-sizing: border-box; padding: 0px 5px;">36</li><li style="box-sizing: border-box; padding: 0px 5px;">37</li><li style="box-sizing: border-box; padding: 0px 5px;">38</li><li style="box-sizing: border-box; padding: 0px 5px;">39</li><li style="box-sizing: border-box; padding: 0px 5px;">40</li><li style="box-sizing: border-box; padding: 0px 5px;">41</li><li style="box-sizing: border-box; padding: 0px 5px;">42</li><li style="box-sizing: border-box; padding: 0px 5px;">43</li><li style="box-sizing: border-box; padding: 0px 5px;">44</li><li style="box-sizing: border-box; padding: 0px 5px;">45</li><li style="box-sizing: border-box; padding: 0px 5px;">46</li><li style="box-sizing: border-box; padding: 0px 5px;">47</li><li style="box-sizing: border-box; padding: 0px 5px;">48</li><li style="box-sizing: border-box; padding: 0px 5px;">49</li><li style="box-sizing: border-box; padding: 0px 5px;">50</li><li style="box-sizing: border-box; padding: 0px 5px;">51</li><li style="box-sizing: border-box; padding: 0px 5px;">52</li><li style="box-sizing: border-box; padding: 0px 5px;">53</li><li style="box-sizing: border-box; padding: 0px 5px;">54</li><li style="box-sizing: border-box; padding: 0px 5px;">55</li><li style="box-sizing: border-box; padding: 0px 5px;">56</li><li style="box-sizing: border-box; padding: 0px 5px;">57</li><li style="box-sizing: border-box; padding: 0px 5px;">58</li><li style="box-sizing: border-box; padding: 0px 5px;">59</li><li style="box-sizing: border-box; padding: 0px 5px;">60</li><li style="box-sizing: border-box; padding: 0px 5px;">61</li><li style="box-sizing: border-box; padding: 0px 5px;">62</li><li style="box-sizing: border-box; padding: 0px 5px;">63</li><li style="box-sizing: border-box; padding: 0px 5px;">64</li><li style="box-sizing: border-box; padding: 0px 5px;">65</li><li style="box-sizing: border-box; padding: 0px 5px;">66</li><li style="box-sizing: border-box; padding: 0px 5px;">67</li><li style="box-sizing: border-box; padding: 0px 5px;">68</li><li style="box-sizing: border-box; padding: 0px 5px;">69</li><li style="box-sizing: border-box; padding: 0px 5px;">70</li><li style="box-sizing: border-box; padding: 0px 5px;">71</li><li style="box-sizing: border-box; padding: 0px 5px;">72</li><li style="box-sizing: border-box; padding: 0px 5px;">73</li><li style="box-sizing: border-box; padding: 0px 5px;">74</li><li style="box-sizing: border-box; padding: 0px 5px;">75</li><li style="box-sizing: border-box; padding: 0px 5px;">76</li><li style="box-sizing: border-box; padding: 0px 5px;">77</li><li style="box-sizing: border-box; padding: 0px 5px;">78</li></ul>

大家都看的出來,雖然簡單的插件已經完全夠用了。但是這種方式確實不是很好。


Hook 系統API方法

DroidPlugin中最重要的就是,為了讓插件中的方法能夠正確的調用。DroidPlugin把所有的,方法都在內部Hook并替換掉了。

等等,為什么不能夠正確的調用? 
因為,這個是一個插件系統,Activity是虛擬Proxy出來的。四大組件,并不是真正的,即Context拿到不一定是真的。系統也不會有此類的回調。所以,很多單例都需要Context才能使用。 
比如:InputMethodManager.getInstance(Context context);

這時,插件中的代碼將不能夠直接運行。當然,還有其他原因。

具體的替換和操作方法,我們能夠在 HookFactory.java文件中installHook方法中,看到整個DroidPlugin的具體操作如下所示:

<code class="hljs java has-numbering" style="display: block; padding: 0px; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-radius: 0px; word-wrap: normal; background: transparent;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">final</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">installHook</span>(Context context, ClassLoader classLoader) <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">throws</span> Throwable {
        installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IClipboardBinderHook(context), classLoader);
        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">//for INotificationManager</span>
        installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> INotificationManagerBinderHook(context), classLoader);
        installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IMountServiceBinder(context), classLoader);
        installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IAudioServiceBinderHook(context), classLoader);
        installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IContentServiceBinderHook(context), classLoader);
        installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IWindowManagerBinderHook(context), classLoader);
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP_MR1) {
            installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IGraphicsStatsBinderHook(context), classLoader);
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
            installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IMediaRouterServiceBinderHook(context), classLoader);
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
            installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> ISessionManagerBinderHook(context), classLoader);
        }
        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2) {
            installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IWifiManagerBinderHook(context), classLoader);
        }

        <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">if</span> (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2) {
            installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IInputMethodManagerBinderHook(context), classLoader);
        }

        installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IPackageManagerHook(context), classLoader);
        installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> IActivityManagerHook(context), classLoader);
        installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> PluginCallbackHook(context), classLoader);
        installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> InstrumentationHook(context), classLoader);
        installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> LibCoreHook(context), classLoader);

        installHook(<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">new</span> SQLiteDatabaseHook(context), classLoader);
    }</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right; background-color: rgb(238, 238, 238);"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li><li style="box-sizing: border-box; padding: 0px 5px;">13</li><li style="box-sizing: border-box; padding: 0px 5px;">14</li><li style="box-sizing: border-box; padding: 0px 5px;">15</li><li style="box-sizing: border-box; padding: 0px 5px;">16</li><li style="box-sizing: border-box; padding: 0px 5px;">17</li><li style="box-sizing: border-box; padding: 0px 5px;">18</li><li style="box-sizing: border-box; padding: 0px 5px;">19</li><li style="box-sizing: border-box; padding: 0px 5px;">20</li><li style="box-sizing: border-box; padding: 0px 5px;">21</li><li style="box-sizing: border-box; padding: 0px 5px;">22</li><li style="box-sizing: border-box; padding: 0px 5px;">23</li><li style="box-sizing: border-box; padding: 0px 5px;">24</li><li style="box-sizing: border-box; padding: 0px 5px;">25</li><li style="box-sizing: border-box; padding: 0px 5px;">26</li><li style="box-sizing: border-box; padding: 0px 5px;">27</li><li style="box-sizing: border-box; padding: 0px 5px;">28</li><li style="box-sizing: border-box; padding: 0px 5px;">29</li><li style="box-sizing: border-box; padding: 0px 5px;">30</li><li style="box-sizing: border-box; padding: 0px 5px;">31</li><li style="box-sizing: border-box; padding: 0px 5px;">32</li><li style="box-sizing: border-box; padding: 0px 5px;">33</li></ul>

限制和缺陷

Ok,說到最后,還是得稱贊一下360。國內大公司開源的使用框架原來越少了。他們的這一舉動確實是造福了目前的Android開發者。

但是,對于DroidPlugin來說,目前還存在一下幾種不足和缺點:

  1. 無法在插件中發送具有自定義資源的Notification,例如: a. 帶自定義RemoteLayout的Notification b. 
    圖標通過R.drawable.XXX指定的通知(插件系統會自動將其轉化為Bitmap)

  2. 無法在插件中注冊一些具有特殊Intent 
    Filter的Service、Activity、BroadcastReceiver、ContentProvider等組件以供Android系統、已經安裝的其他APP調用。

  3. 對Activity的LaunchMode支持不夠好,Activity 
    Stack管理存在一定缺陷。Activity的onNewIntent函數可能不會被觸發。 (此為BUG,未來會修復)

  4. 缺乏對Native層的Hook,對某些帶native代碼的apk支持不好,可能無法運行。比如一部分游戲(cocos2d、unity3d開發的游戲估計都用不了)無法當作插件運行。


當然,看我說的再多,也只是我的個人理解,有興趣的同學,直接去github clone一份代碼閱讀閱讀吧。

github地址為: https://github.com/Qihoo360/DroidPlugin

來自: http://blog.csdn.net/zhyooo123/article/details/50546207

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!