日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android apk动态加载机制的研究(二):资源加载和activity生命周期管理

發布時間:2025/3/15 Android 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android apk动态加载机制的研究(二):资源加载和activity生命周期管理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載請注明出處:http://blog.csdn.net/singwhatiwanna/article/details/23387079 (來自singwhatiwanna的csdn博客)

前言

為了更好地閱讀本文,你需要先閱讀Android apk動態加載機制的研究這篇文章,在此文中,博主分析了Android中apk的動態加載機制,并在文章的最后指出需要解決的兩個復雜問題:資源的訪問和activity生命周期的管理,而本文將會分析這兩個復雜問題的解決方法。需要說明的一點是,我們不可能調起任何一個未安裝的apk,這在技術上是無法實現的,我們調起的apk必須受某種規范的約束,只有在這種約束下開發的apk,我們才能將其調起。另外,本文給出的解決方案也不是完美的,但是邏輯已經可以正常地跑通了,剩下的極個別細節問題是可以優化的。

資源管理

我們知道,宿主程序調起未安裝的apk,一個很大的問題就是資源如何訪問,具體來說就是,凡是以R開頭的資源都不能訪問了,因為宿主程序中并沒有apk中的資源,所以通過R來加載資源是行不通的,程序會報錯:無法找到某某id所對應的資源。針對這個問題,有人提出了將apk中的資源在宿主程序中也copy一份,這雖然能解決問題,可以一聽起來就很奇怪,首先這樣會持有兩份資源,會增加宿主程序包的大小,其次,沒發布一個插件都需要將資源copy到宿主程序中,這樣就意味著每發布一個插件都要更新一下宿主程序,這和插件化的思想是相悖的,插件化的目的就是要減小宿主程序apk包的大小同時降低宿主程序的更新頻率并做到自由裝載模塊。所以這種方法并不可行。還有人提供了一種方式:將apk中的資源解壓出來,然后通過文件流去讀取資源,這樣做理論上是可行的,但是實際操作起來還是有很大難度的,首先不同資源有不同的文件流格式,比如圖片、xml等,還有就是針對不同設備加載的資源可能是不一樣的,如果選擇合適的資源也是一個需要解決的問題,基于這兩點,這種方法不建議使用,因為它實現起來有難度。下面說說本文所采用的方法。


我們知道,activity的工作主要是由ContextImpl來完成的, 它在activity中是一個叫做mBase的成員變量。注意到Context中有如下兩個抽象方法,看起來是和資源有關的,實際上context就是通過它們來獲取資源的,這兩個抽象方法的真正實現在ContextImpl中。也即是說,只要我們自己實現這兩個方法,就可以解決資源問題了。

? ? /** Return an AssetManager instance for your application's package. */
? ? public abstract AssetManager getAssets();

? ? /** Return a Resources instance for your application's package. */
? ? public abstract Resources getResources();

下面看一下如何實現這兩個方法

首先要加載apk中的資源:

[java] view plain copy
  • protected?void?loadResources()?{??
  • ????try?{??
  • ????????AssetManager?assetManager?=?AssetManager.class.newInstance();??
  • ????????Method?addAssetPath?=?assetManager.getClass().getMethod("addAssetPath",?String.class);??
  • ????????addAssetPath.invoke(assetManager,?mDexPath);??
  • ????????mAssetManager?=?assetManager;??
  • ????}?catch?(Exception?e)?{??
  • ????????e.printStackTrace();??
  • ????}??
  • ????Resources?superRes?=?super.getResources();??
  • ????mResources?=?new?Resources(mAssetManager,?superRes.getDisplayMetrics(),??
  • ????????????superRes.getConfiguration());??
  • ????mTheme?=?mResources.newTheme();??
  • ????mTheme.setTo(super.getTheme());??
  • }??
  • 說明:加載的方法是通過反射,通過調用AssetManager中的addAssetPath方法,我們可以將一個apk中的資源加載到Resources中,由于addAssetPath是隱藏api我們無法直接調用,所以只能通過反射,下面是它的聲明,通過注釋我們可以看出,傳遞的路徑可以是zip文件也可以是一個資源目錄,而apk就是一個zip,所以直接將apk的路徑傳給它,資源就加載到AssetManager中了,然后再通過AssetManager來創建一個新的Resources對象,這個對象就是我們可以使用的apk中的資源了,這樣我們的問題就解決了。

    [java] view plain copy
  • /**?
  • ?*?Add?an?additional?set?of?assets?to?the?asset?manager.??This?can?be?
  • ?*?either?a?directory?or?ZIP?file.??Not?for?use?by?applications.??Returns?
  • ?*?the?cookie?of?the?added?asset,?or?0?on?failure.?
  • ?*?{@hide}?
  • ?*/??
  • public?final?int?addAssetPath(String?path)?{??
  • ????int?res?=?addAssetPathNative(path);??
  • ????return?res;??
  • }??
  • 其次是要實現那兩個抽象方法

    [java] view plain copy
  • @Override??
  • public?AssetManager?getAssets()?{??
  • ????return?mAssetManager?==?null???super.getAssets()?:?mAssetManager;??
  • }??
  • ??
  • @Override??
  • public?Resources?getResources()?{??
  • ????return?mResources?==?null???super.getResources()?:?mResources;??
  • }??
  • okay,問題搞定。這樣一來,在apk中就可以通過R來訪問資源了。

    activity生命周期的管理

    這是本文開頭提到的另一個需要解決的難題。為什么會有這個問題,其實很好理解,apk被宿主程序調起以后,apk中的activity其實就是一個普通的對象,不具有activity的性質,因為系統啟動activity是要做很多初始化工作的,而我們在應用層通過反射去啟動activity是很難完成系統所做的初始化工作的,所以activity的大部分特性都無法使用包括activity的生命周期管理,這就需要我們自己去管理。談到activity生命周期,其實就是那幾個常見的方法:onCreate、onStart、onResume、onPause等,由于apk中的activity不是真正意義上的activity(沒有在宿主程序中注冊且沒有完全初始化),所以這幾個生命周期的方法系統就不會去自動調用了。針對此類問題,采用Fragment是一個不錯的方法,Fragment從3.0引入,通過support-v4包,可以兼容3.0以下的android版本。Fragment既有類似于Activity的生命周期,又有類似于View的界面,將Fragment加入到Activity中,activity會自動管理Fragment的生命周期,通過第一篇文章我們知道,apk中的activity是通過宿主程序中的代理activity啟動的,將Fragment加入到代理activity內部,其生命周期將完全由代理activity來管理,但是采用這種方法,就要求apk盡量采用Fragment來實現,還有就是在做頁面跳轉的時候有點麻煩,當然關于Fragment相關的內容我將在后面再做研究,本文不采用Fragment而是通過反射去手動管理activity的生命周期。


    我們要在代理activity中去反射apk中activity的所有生命周期的方法,然后將activity的生命周期和代理activity的生命周期進行同步。首先,反射activity生命周期的所有方法,還反射了onActivityResult這個方法,盡管它不是典型的生命周期方法,但是它很有用。

    [java] view plain copy
  • protected?void?instantiateLifecircleMethods(Class<?>?localClass)?{??
  • ????String[]?methodNames?=?new?String[]?{??
  • ????????????"onRestart",??
  • ????????????"onStart",??
  • ????????????"onResume",??
  • ????????????"onPause",??
  • ????????????"onStop",??
  • ????????????"onDestory"??
  • ????};??
  • ????for?(String?methodName?:?methodNames)?{??
  • ????????Method?method?=?null;??
  • ????????try?{??
  • ????????????method?=?localClass.getDeclaredMethod(methodName,?new?Class[]?{?});??
  • ????????????method.setAccessible(true);??
  • ????????}?catch?(NoSuchMethodException?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ????????mActivityLifecircleMethods.put(methodName,?method);??
  • ????}??
  • ??
  • ????Method?onCreate?=?null;??
  • ????try?{??
  • ????????onCreate?=?localClass.getDeclaredMethod("onCreate",?new?Class[]?{?Bundle.class?});??
  • ????????onCreate.setAccessible(true);??
  • ????}?catch?(NoSuchMethodException?e)?{??
  • ????????e.printStackTrace();??
  • ????}??
  • ????mActivityLifecircleMethods.put("onCreate",?onCreate);??
  • ??
  • ????Method?onActivityResult?=?null;??
  • ????try?{??
  • ????????onActivityResult?=?localClass.getDeclaredMethod("onActivityResult",??
  • ????????????????new?Class[]?{?int.class,?int.class,?Intent.class?});??
  • ????????onActivityResult.setAccessible(true);??
  • ????}?catch?(NoSuchMethodException?e)?{??
  • ????????e.printStackTrace();??
  • ????}??
  • ????mActivityLifecircleMethods.put("onActivityResult",?onActivityResult);??
  • }??
  • 其次,同步生命周期,主要看一下onResume和onPause,其他方法是類似的。看如下代碼,很好理解,就是當系統調用代理activity生命周期方法的時候,就通過反射去顯式調用apk中activity的對應方法。

    [java] view plain copy
  • @Override??
  • protected?void?onResume()?{??
  • ????super.onResume();??
  • ????Method?onResume?=?mActivityLifecircleMethods.get("onResume");??
  • ????if?(onResume?!=?null)?{??
  • ????????try?{??
  • ????????????onResume.invoke(mRemoteActivity,?new?Object[]?{?});??
  • ????????}?catch?(Exception?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ????}??
  • }??
  • ??
  • @Override??
  • protected?void?onPause()?{??
  • ????Method?onPause?=?mActivityLifecircleMethods.get("onPause");??
  • ????if?(onPause?!=?null)?{??
  • ????????try?{??
  • ????????????onPause.invoke(mRemoteActivity,?new?Object[]?{?});??
  • ????????}?catch?(Exception?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ????}??
  • ????super.onPause();??
  • }??
  • 插件apk的開發規范

    文章開頭提到,要想成為一個插件apk,是要滿足一定條件的,如下是采用本文機制開發插件apk所需要遵循的規范:

    1. 不能用this:因為this指向的是當前對象,即apk中的activity,但是由于activity已經不是常規意義上的activity,所以this是沒有意義的。

    2. 使用that:既然this不能用,那就用that,that是apk中activity的基類BaseActivity中的一個成員,它在apk安裝運行的時候指向this,而在未安裝的時候指向宿主程序中的代理activity,anyway,that is better than this。

    3. 不能直接調用activity的成員方法:而必須通過that去調用,由于that的動態分配特性,通過that去調用activity的成員方法,在apk安裝以后仍然可以正常運行。

    4. 啟動新activity的約束:啟動外部activity不受限制,啟動apk內部的activity有限制,首先由于apk中的activity沒注冊,所以不支持隱式調用,其次必須通過BaseActivity中定義的新方法startActivityByProxy和startActivityForResultByProxy,還有就是不支持LaunchMode。

    5. 目前暫不支持Service、BroadcastReceiver等需要注冊才能使用的組件。

    后續工作

    1. DLIntent的定義,通過自定義的intent,來完成activity的無約束調起

    2. 采用Fragment的生命周期管理

    3.?Service、BroadcastReceiver等組件的調起

    4. 性能優化

    效果

    首先宿主程序運行后,會把位于/mnt/sdcard/DynamicLoadHost目錄下的所有apk都加載進來,然后點擊列表就可以調起對應的apk,本文中的demo和第一篇文章中的demo看起來差不多,實際是有區別的,區別有兩點:activity具有生命周期、加載資源可以用R,具體的代碼實現請大家參見源碼。


    源碼下載:https://github.com/singwhatiwanna/dynamic-load-apk

    68
    4

    我的同類文章

    Android高手進階(50)
    • ?Android中MotionEvent的來源和ViewRootImpl2016-03-01閱讀4048
    • ?循環廣告位組件的實現2015-06-18閱讀13045
    • ?APK動態加載框架(DL)解析2014-10-10閱讀37819
    • ?Android View系統解析(上)2014-07-27閱讀15182
    • ?Android源碼分析-資源加載機制2014-04-26閱讀11325
    • ?Android的消息機制之ThreadLocal的工作原理2015-09-10閱讀6325
    • ?Android L中水波紋點擊效果的實現2015-01-12閱讀20860
    • ?Android View系統解析(下)2014-08-08閱讀20207
    • ?可下拉的PinnedHeaderExpandableListView的實現2014-05-12閱讀20096
    更多文章 猜你在找
    Qt基礎與Qt on Android入門
    3G Android實戰開發從入門到精通
    Android底層技術:Java層系統服務(Android Service)
    Android底層技術:Linux驅動框架與開發
    精講精練_參悟Android核心技術
    查看評論 52樓 sonnzy 2015-12-25 16:02發表 [回復]
    厲害,一直被無法獲取插件apk里的R煩惱,雖然網上也有類似dl,但是沒這么詳細,你說明了原理,還有源代碼,非常的難得,贊一個
    51樓 杭州山不高 2015-12-18 18:05發表 [回復]
    好文,轉了!
    50樓 andywuchuanlong 2015-07-13 14:24發表 [回復]
    LZ,你這個無法宿主apk無法調用插件apk
    49樓 xw568159764 2015-07-10 16:37發表 [回復]
    請教樓主一下,既然activity中跟context相關的操作都是通過mBase完成的,是不是可以直接調用attachBaseContext方法直接將宿主activity的context賦給插件?
    48樓 SanDiegoX 2015-05-12 23:50發表 [回復]
    感謝博主的分享,有點兒問題請教一下:
    1、資源文件的加載是不是在博主構造的 DL 框架(demo 中的 lib 目錄 ?)中處理?而每次殼程序通過去調用 DL 框架,來加載插件APK、同時完成對資源文件的動態加載??
    2、我用了另外一種方式來實現對APK的加殼,想按照博主的思路、通過殼的組件動態加載 APK 的資源文件。請問,除了創建AssetManager、Resources 對象外,還需要對 運行中的 ActivityThread 進行反射修改嗎?博主提重寫的 getAssets()、getResource() 方法,是在殼的主Activity、或者Application中重寫即可嗎?
    謝謝!
    47樓 godnessilove 2015-04-16 20:34發表 [回復]
    你好,我在學習你的插件化的時候碰到個問題,host無法調起pluga或者plugb
    報錯:
    04-16 11:46:26.962 2718-2718/? W/dalvikvm﹕ (Lcom/ryg/dynamicload/sample/mainplugin/MainActivity; had used a different Lcom/ryg/dynamicload/DLBasePluginActivity; during pre-verification)
    04-16 11:46:26.962 2718-2718/? W/dalvikvm﹕ Unable to resolve superclass of Lcom/ryg/dynamicload/sample/mainplugin/MainActivity; (723)
    我在研究后發現dexclassload找不到com/ryg/dynamicload/sample/mainplugin/MainActivity這個class,但是確實已經把這個apk給加載到app_dex目錄下了
    然后在需要用的時候從map里拿出對應的manager去Class.forName,這里就是不對,斷點跟蹤發現沒有獲得需要的class,然后我改成dexclassload.loadClass方法就報錯 java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation,我總覺得是不是因為插件里面包含了一份dl-lib的DLBasePluginActivity,然后host里面libs里面也有一份,結果最后執行查找他的子類MainActivity就出問題了,是不是我2個包打包不對?
    請問這個問題怎么解決啊~
    感激不盡啊~
    46樓 godnessilove 2015-04-16 20:32發表 [回復]
    你好,我在學習你的插件化的時候碰到個問題,host無法調起pluga或者plugb
    報錯:
    04-16 11:46:26.962 2718-2718/? W/dalvikvm﹕ (Lcom/ryg/dynamicload/sample/mainplugin/MainActivity; had used a different Lcom/ryg/dynamicload/DLBasePluginActivity; during pre-verification)
    04-16 11:46:26.962 2718-2718/? W/dalvikvm﹕ Unable to resolve superclass of Lcom/ryg/dynamicload/sample/mainplugin/MainActivity; (723)
    我在研究后發現dexclassload找不到com/ryg/dynamicload/sample/mainplugin/MainActivity這個class,但是確實已經把這個apk給加載到app_dex目錄下了
    然后在需要用的時候從map里拿出對應的manager去Class.forName,這里就是不對,斷點跟蹤發現沒有獲得需要的class,然后我改成dexclassload.loadClass方法就報錯 java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation,我總覺得是不是因為插件里面包含了一份dl-lib的DLBasePluginActivity,然后host里面libs里面也有一份,結果最后執行查找他的子類MainActivity就出問題了,是不是我2個包打包不對?
    請問這個問題怎么解決啊~
    感激不盡啊~
    45樓 cokepanm 2015-04-01 16:51發表 [回復]
    詢問下,當插件的資源已經加載后,怎么去釋放其內存呢
    44樓 余龍飛 2015-02-05 15:50發表 [回復]
    贊樓主的分享精神,想問一下,百度衛士里面用到了這種技術嗎?
    2013年底的時候,我們團隊碰到了這個問題,需要在宿主進程中訪問插件中的資源,當時交給我解決,我閱讀源碼調研了好幾天才調研出來,因為公司項目中使用了,所以一直沒有分享出來。

    一個宿主app的Context默認會關聯2個apk的資源:自身apk中資源和framework-res.apk中的資源
    我們只需要模擬android源碼關聯framework-res.apk資源的方式,把插件apk的資源也和宿主Context關聯上即可。
    這樣我們宿主app的Context就關聯上了3個apk的資源了。當然還可以關聯更多,只要resouce id夠用。 Re: fengzi422 2015-12-08 14:50發表 [回復]
    回復gemmem:按照你這么說,確實可以解決多個apk的resource的問題,但是你在host中如何拿到你所想拿到的資源的id?需要使用另外一個R文件么?而且資源id沖突了怎么辦?
    Re: singwhatiwanna 2015-02-05 18:47發表 [回復]
    回復gemmem:不是反射addAssetPath這個方法做的? Re: 余龍飛 2015-02-06 10:19發表 [回復]
    回復singwhatiwanna:我上面說的是實現原理,你多想想,應該能明白。
    實現方法就是用addAssetPath構造出一個resouces對象,這個resource對象關聯到宿主的Context環境中(具體做法就是重寫宿主Context的getResources等方法),讓宿主Context具備了解析插件apk資源的能力。 Re: fengzi422 2015-12-08 14:50發表 [回復]
    回復gemmem:按照你這么說,確實可以解決多個apk的resource的問題,但是你在host中如何拿到你所想拿到的資源的id?需要使用另外一個R文件么?而且資源id沖突了怎么辦? Re: 余龍飛 2015-12-29 15:35發表 [回復]
    回復fengzi422:重寫host app中的activity的getResources等函數,讓它們返回自己構造的那個包含了plugin apk path的resource對象。
    Re: for_perfect 2015-04-07 14:34發表 [回復]
    回復gemmem:您好,我現在的團隊產品的需求是,app1是打開狀態,需要在app1中讀取app2中存儲在sharedprference中的數據,wo使用這種重寫getAssets(),getResources(),getTheme()可以實現嗎 Re: 余龍飛 2015-04-08 20:51發表 [回復]
    回復u010359739:完全不相干的東西,當然不可以。 Re: 簡單才是美 2015-05-13 16:21發表 [回復]
    回復gemmem:使用反射AssetManager方式,在android 5.0上會報錯,會提示找不到資源的問題;請問一下你們有碰到過這種問題嗎? Re: AriaLyy 2015-09-19 14:50發表 [回復]
    回復waitingformysun:我也碰到了同樣的問題,我猜想原因可能是addAssetPath這個方法調用失敗了,我在5.0上用反射使用這個方法,一直返回0... Re: 余龍飛 2015-12-29 15:32發表 [回復]
    回復qwe511455842:5.0,我沒有試過。你看看源碼吧
    43樓 _自由人_ 2015-01-31 12:29發表 [回復]
    樓主,我研究這插件化也有短時間了,你這blog的思路跟我綜合起來的思路大概一致,但你講了,能使用getResource()來使用插件中的資源,這點是我沒有想到的,這里給你個贊!!!我剛大概看了你的代碼,但我發現,你并沒有使用getResources()的方法去使用插件apk中的資源!因此,我有個問題:你成功使用過getResource()引用過插件apk中的資源嗎?盼探討 Re: singwhatiwanna 2015-01-31 19:17發表 [回復]
    回復wuzhipeng1991:可以的,在插件中可以用R直接訪問插件的資源,同時插件是運行在宿主中的,所以宿主也可以直接訪問插件的資源,前提是知道id。 Re: _自由人_ 2015-02-02 09:04發表 [回復]
    回復singwhatiwanna:我自己嘗試了一下在你的代碼上修改。不過,我把插件的代碼單獨拿出來運行,卻一直報找不到類異常,這其中有什么問題需注意的嗎?望指出下。謝謝
    42樓 小胖 2015-01-07 11:13發表 [回復]
    請問一下,大牛們有沒有用過DevAppsDirect這個展示開源demo的軟件,原理是不是一樣的?
    41樓 yemin6666 2015-01-04 16:52發表 [回復]
    請教下,~getAssets() ,getResources()是在宿主程序,還是插件程序里重寫~?我復制了apk中的一份資源到宿主程序,然后在反射apk中用R來調用,發現也沒調用不到資源 Re: singwhatiwanna 2015-01-04 20:26發表 [回復]
    回復yemin6666:請參看dl的源碼
    40樓 sinat_23061139 2014-11-07 18:12發表 [回復]
    樓主良心!目前也在研究這一塊找了下資料,找了下資料,確實不多,研究的人估計也不少,也有一些已經商用的SDK,但是能把技術原理和細節實現分享出來的真的不多。 Re: 余龍飛 2015-02-06 10:25發表 [回復]
    回復sinat_23061139:同感,其實2013年底時,由于項目需要,我承擔了調研插件資源動態加載的任務,我費了好大勁調研出來的,但是一直舍不得分享。 Re: singwhatiwanna 2015-02-06 10:41發表 [回復]
    回復gemmem:覺得自己花了很多心思對吧,所以不舍得,也可以理解。不過我現在所推崇的是分享。
    39樓 尼古拉斯_趙四 2014-10-24 15:47發表 [回復]
    mark一下,我以前寫的動態加載技術一片文章,但是你mark了一下,apk插件的用途還是蠻大的,支付寶就是個好例子,還有微信的免安裝游戲試玩等,核心技術還是反射。。。
    38樓 amurocrash 2014-10-08 11:14發表 [回復]
    大神,你最新github的版本里的插件基類因為onStart等方法沒有super.onStart()等,插件直接運行的時候會導致程序崩潰,你把這些生命周期方法和setProxy方法抽取到了一個DLPlugin接口內我覺得意義不明,而且和Activity本身的生命周期方法是重復的,不知道你設計的思路是什么,個人覺得接口里只放setProxy這樣的方法就可以了,盼探討~ Re: singwhatiwanna 2014-10-08 16:08發表 [回復]
    回復amurocrash:215680213 加群探討。
    目前思路已經和博客上的有了不小改變,接下來我會重新發布說明文檔的。目前你是用sample/main下面的demo,是沒有問題的。如果想獨立運行,需要把dl-lib.jar放入到插件的libs目錄下。至于plugin接口的意義,是activity生命周期的管理所需,都是有用并且是非常有意義的。這一切都會讓dl更加好用更加方便調用。
    37樓 胖虎 2014-09-28 21:49發表 [回復]
    lz, 最近小弟也在研究這塊,我想請問下比如apk A 調起了 apk B中的MainActivity, 那按照這樣的處理,是不是在apk B中MainActivity 開啟的服務,或者注冊的廣播接受者都不能用?
    那MainActivity如果 startActivity呢?1.startActivity會受影響嗎? 2.start起來的那個Activity依舊用的是 是apk A的上下文嗎? Re: singwhatiwanna 2014-09-29 20:12發表 [回復]
    回復u011133213:目前暫時不支持service,廣播可以通過代碼注冊。 Re: 胖虎 2014-09-30 08:45發表 [回復]
    回復singwhatiwanna:那被我A調起的那個B MainActivity,如果要再啟動一個B OtherActivity 那需要用A的這種上下文來啟動咯?
    36樓 TigerBetree 2014-09-17 17:26發表 [回復]
    膜拜啊~
    35樓 花-開-花-謝 2014-09-09 18:30發表 [回復]
    帥哥,我也剛開始寫博客,自己弄得gif圖片怎么在博客中只能顯示第一偵,就不會動,請問是怎么回事,這是鏈接:http://blog.csdn.net/gaolei1201/article/details/39057057 Re: singwhatiwanna 2014-09-10 21:20發表 [回復]
    回復gaolei1201:首先要做一個gif圖,其次圖片尺寸不要太大,否則到csdn上動不了。 Re: 花-開-花-謝 2014-09-11 00:09發表 [回復]
    嗯,我用了包括GifCam等好幾種工具,制作成gif圖片,就是一傳到博客就不會動,只有100kb左右,請問這是為什么?你用的什么工具 Re: singwhatiwanna 2014-09-11 09:31發表 [回復]
    回復gaolei1201:gif maker.首先確認你的gif在本地是可以動的,其次寬高不要太大,基本就可以了。 Re: 花-開-花-謝 2014-09-11 14:00發表 [回復]
    謝謝,昨天我又試了試,豎屏的錄制的gif是可以的,橫屏錄制的gif在博客上不會動
    34樓 廠圩菠蘿菠蘿蜜 2014-09-09 14:31發表 [回復]
    博主知識博大精深,受教了。請問啟動service的問題解決了嗎?
    33樓 worthwhile001 2014-09-04 15:38發表 [回復]
    host里面,先期client里面的mainactivity,通過mainactivity,起testactivity,。我把client里面testactivity和mainactivity,換一下順序,怎么就不行了。。 Re: singwhatiwanna 2014-09-08 15:12發表 [回復]
    回復worthwhile001:startActivityByProxy
    用這個來起activity
    32樓 懷柔老紀 2014-08-19 10:46發表 [回復]
    有一個問題想問問,插件用了這么多反射,還能不能正常的混淆代碼了。宿主的代理Activity是不是也要從混淆中排除? Re: singwhatiwanna 2014-08-19 18:46發表 [回復]
    回復coolstar1204:android的framework默認就不能參與混淆,否則你的activity就跑不起來,所以,插件化不影響正常混淆。
    31樓 tanxiaojun 2014-07-29 11:14發表 [回復]
    最近在研究這個,樓主的Demo可以用,已經有人把插件模塊化做成SDK了,apkplug,不知道原理和樓主的是不是一樣
    http://www.apkplug.com/
    30樓 gejw116 2014-07-25 20:18發表 [回復]
    String[] methodNames = new String[] {
    "onRestart",
    "onStart",
    "onResume",
    "onPause",
    "onStop",
    "onDestory"
    };
    for (String methodName : methodNames) {
    Method method = null;
    try {
    method = localClass.getDeclaredMethod(methodName, new Class[] { });
    method.setAccessible(true);
    } catch (NoSuchMethodException e) {
    e.printStackTrace();
    }
    mActivityLifecircleMethods.put(methodName, method);
    }

    反射這6個函數的時候,method為空,我試了下例子,手機上不能跑 Re: singwhatiwanna 2014-07-27 10:13發表 [回復]
    回復gejw116:跑的時候是需要插件apk放在指定目錄的,demo是可以跑的。
    29樓 HiPhoneZhu 2014-07-24 16:45發表 [回復]
    真的很不錯,我知道阿里內部有個團隊也在做這個,完全拋棄了系統的,加油,文章寫得真的不錯! Re: HiPhoneZhu 2014-07-24 17:27發表 [回復]
    回復zhf198909:github上面最新的代碼,無法啟動插件 Re: singwhatiwanna 2014-07-25 18:54發表 [回復]
    回復zhf198909:是不是插件apk沒有放在指定目錄?
    28樓 shuaizhimin123 2014-07-22 18:58發表 [回復]
    為什么資源文件無法直接調用?求解。下載的是你gitHub上面的源碼 Re: singwhatiwanna 2014-07-25 18:56發表 [回復]
    回復shuaizhimin123:你按照文章上面說的步驟來
    27樓 赫賀鶴 2014-07-01 23:24發表 [回復]
    這么牛逼你爹知道嗎
    26樓 asking1233 2014-06-22 13:11發表 [回復]
    師父,請受徒兒一鞠躬
    25樓 colcat2010 2014-05-04 22:04發表 [回復]
    lz寫的非常好,可是源碼地址我們學校校園網打不開,不知道能不能發到我郵箱,謝謝!coldcat2010@126.com
    24樓 追風箏的孩子 2014-04-29 17:36發表 [回復]
    http://blogs.360.cn/blog/proxydelegate-application/

    他們已經能不安裝apk并且運行該apk了,不適合插件化,因為必須要在AndroidMainfest里面把需要的Activity插件話,但挺適合部門間合作。不用提供源碼并且做小幅度修改即可 Re: singwhatiwanna 2014-04-29 22:01發表 [回復]
    回復A328240784:個人覺得,360那個很受限制,而且很容易有問題,太深入底層了。 Re: com360 2014-08-14 16:33發表 [回復]
    回復singwhatiwanna:牛逼!和我們現在用的類似。可以在安全上和打包上再搞一搞。
    23樓 cornivylove 2014-04-26 20:49發表 [回復]
    相關技術方法我也整過,唉!越整越沒脾氣……
    22樓 anbiandezacao 2014-04-25 10:03發表 [回復]
    如果你能在DynamicLoadHost直接調用DynamicLoadClient里的res文件,那你解決了做jar包人糾結了四五年的問題 Re: singwhatiwanna 2014-04-25 10:14發表 [回復]
    回復anbiandezacao:你要搞清楚,host是要把jar包調起來,而host根本不知道jar包里有什么資源,怎么能訪問jar包的資源?而且host調起jar包后,jar包是可以訪問到自己的資源的。換句話來說,你在host里面訪問一個未知jar包的資源干什么?也許我們理解的有偏差
    21樓 anbiandezacao 2014-04-25 09:53發表 [回復]
    額,JAVA基礎好的都知道,class文件可以用反射調用,android的dex文件也可以用反射調用,做jar包最痛苦的是不能調用res里面的文件,看了你的代碼,你也根本沒解決... Re: singwhatiwanna 2014-04-25 10:19發表 [回復]
    回復anbiandezacao:關于資源的加載問題,我做了處理,你可以再仔細看一下。
    20樓 MrSimp1e 2014-04-24 18:35發表 [回復]
    樓主,宿主apk能否獲取到被加載apk的資源?多謝 Re: singwhatiwanna 2014-04-25 10:15發表 [回復]
    回復bboyfeiyu:從動態加載來說,宿主加載apk后可以訪問apk里的資源。 Re: MrSimp1e 2014-04-25 13:12發表 [回復]
    回復singwhatiwanna:只需加載apk中的Activity類到虛擬機中,不需要onCreate就OK嗎 ?
    19樓 Lee堅持 2014-04-21 22:51發表 [回復]
    厲害 Re: singwhatiwanna 2014-04-21 23:14發表 [回復]
    回復lxcay:徒弟 Re: 追風箏的孩子 2014-05-15 17:00發表 [回復]
    回復singwhatiwanna:你徒弟也是黑馬的啊。。 Re: mephistodemon1 2014-10-13 23:29發表 [回復]
    回復A328240784:黑馬?幾期?
    18樓 Simon_Lanzhou 2014-04-18 15:21發表 [回復]
    mark
    17樓 l114624915 2014-04-17 14:51發表 [回復]
    最好能在宿主和插件包之間定義一套接口IInterface,把
    "onRestart","onStart"...定義在接口中,這樣就可以不用反射那么麻煩了。類加載實例后Object instance = localConstructor.newInstance(new Object[] {});可以這樣調用方法(IInterface)instance .onRestart。 Re: singwhatiwanna 2014-04-25 10:15發表 [回復]
    回復l114624915:可以考慮下 Re: qq744765669 2014-05-23 14:39發表 [回復]
    回復singwhatiwanna:在宿主和插件之間建立接口的思路是否走過?我在建立這套接口,將目標Instance轉化為接口的時候發生強轉錯誤
    16樓 zhenxiong25 2014-04-14 17:13發表 [回復]
    henniu
    15樓 szltoy123 2014-04-13 13:37發表 [回復]
    不過 你的 方法少重載了 gettheme 如果插件資源里面的 資源layout 關聯了其他資源 例如圖片 沒有gettheme的方法是報錯的 我測試過 Re: singwhatiwanna 2014-04-13 15:09發表 [回復]
    回復szltoy123:你說的對,getTheme我有重寫,你看下源碼就知道了。 Re: szltoy123 2014-04-14 16:39發表 [回復]
    回復singwhatiwanna:有個問題 就是 如果插件布局用到了自定義view 自定義view的實現肯定是放在插件里面了,這樣子用您的方法去實現這個view的話就會報錯 ,因為用that 去實例化 查找這個布局的時候找到這個view的類名 本程序并沒有這個類的實現。所以就報錯了。有什么辦法解決這個問題呢。 Re: singwhatiwanna 2014-04-14 23:20發表 [回復]
    回復szltoy123:請看github上最新提交,已經支持在xml使用自定義view了,遺憾的是目前不支持在代碼中find自定義view(會報類型轉換失敗),待后面再解決。 Re: szltoy123 2014-04-15 10:48發表 [回復]
    回復singwhatiwanna:加上getClassloader 的確可以顯示自定義view了,不過我沒遇到您的問題我實例化的時候也可以順利的吧自定義view實例化出來。
    雖然這樣可是遇到一個比較怪的問題就是,
    所以如果主程序有一份自定義view的代碼插件也有一份一樣的,加載實例化的時候居然不會報錯,而是主程序的那份把插件的覆蓋了。主程序要是沒有就執行插件的。 Re: singwhatiwanna 2014-04-15 11:55發表 [回復]
    回復szltoy123:那我那個問題可能是mui的bug。你遇到的這個問題:首先不要定義同一個類名,其次那個classloader寫的有問題,應該先從插件中去加載類,加群討論215680213
    Re: singwhatiwanna 2014-04-14 17:20發表 [回復]
    回復szltoy123:override getClassloader,然后返回dexclassloader,后面會更新到github。 Re: peacepassion 6天前 09:10發表 [回復]
    回復singwhatiwanna:關于theme,我也遇到一個問題。我在嘗試擴展對v7包中的AppCompatActivity進行支持,于是分別實現了DLProxyAppCompatActivity和DLBasePluginAppCompatActivity,在DLPluginImpl中將插件activity的主題設置給宿主activity的時候Activity#setTheme(),發現只有對AppCompatActivity主題的設置無效,其它兩種類型的Activity都是OK的。
    請問博主有遇到這個問題么?
    14樓 szltoy123 2014-04-13 13:35發表 [回復]
    非常開心看到您的文章動態加載資源這一塊的確空白 我找了一年時間終于看到你的文章解決了所有的問題。謝謝 哈哈 Re: singwhatiwanna 2014-04-13 15:09發表 [回復]
    回復szltoy123:至于找一年那么久? Re: szltoy123 2014-04-14 09:46發表 [回復]
    回復singwhatiwanna:唉 斷斷續續找 差不多啦 以前在書上找 網上找都說需要改源碼,所以一直沒去研究這部分的源碼
    13樓 scion_KK 2014-04-12 23:18發表 [回復]
    不錯的文章呀。有時候需要的就是這種功能
    12樓 zwt069074237 2014-04-12 21:06發表 [回復]
    mark
    11樓 KennethYo 2014-04-12 18:03發表 [回復]
    目前業務上還用不到,但是在這種技術上我還是一片空白,先mark上,日后來仔細研究。
    10樓 pageTan 2014-04-12 12:17發表 [回復]
    學習了
    9樓 yjiyjige 2014-04-11 22:57發表 [回復]
    不錯,有時候解決問題最好的方法就是去讀源碼了。
    之前想實現一個功能,就是動態下載語言包。
    實現的方法就是使用反射去自己構造出一個Resource出來。這方法的研究確實還比較少。
    8樓 綠領巾童鞋 2014-04-11 21:56發表 [回復]
    膜拜啊~
    7樓 蘭亭風雨 2014-04-11 21:40發表 [回復]
    大神就是大神啊!真心膜拜!! Re: singwhatiwanna 2014-04-11 22:36發表 [回復]
    回復mmc_maodun:嘿嘿
    6樓 RowandJJ 2014-04-11 19:22發表 [回復]
    贊~
    5樓 Tony2005 2014-04-11 16:20發表 [回復]
    非常不錯~!頂上
    4樓 soledadzz 2014-04-11 12:17發表 [回復]
    您的文章已被推薦到CSDN首頁,感謝您的分享。 Re: singwhatiwanna 2014-04-11 16:25發表 [回復]
    回復soledadzz:謝謝啦
    3樓 時之沙 2014-04-11 11:37發表 [回復]
    不錯,頂一下 Re: singwhatiwanna 2014-04-11 16:25發表 [回復]
    回復t12x3456:沙兄
    2樓 zhouqian88423 2014-04-11 11:26發表 [回復]
    昨晚本來就想拜讀了,結果12點半就睡覺去了,剛瀏覽一遍不是很懂,周末認真研究下
    1樓 萬境絕塵 2014-04-11 10:29發表 [回復]
    apk文件還能這么玩啊 有相關的資料或者書籍嗎 參考下 Re: singwhatiwanna 2014-04-11 10:34發表 [回復]
    回復han1202012:沒有書籍,相關資料你可以搜一下,不過多半都沒用,目前這種技術還相對空白。

    總結

    以上是生活随笔為你收集整理的Android apk动态加载机制的研究(二):资源加载和activity生命周期管理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。