當前位置:首頁 » 安卓系統 » android遇到的問題

android遇到的問題

發布時間: 2024-07-21 05:07:27

Ⅰ 用android會遇到什麼關鍵技術問題及可行性解決方案

1.資源訪問

我們知道,宿主程序調起未安裝的插件apk,一個很大的問題就是資源如何訪問,具體來說就是插件中凡是以R開頭的資源都不能訪問了。這是因為宿主程序中並沒有插件的資源,所以通過R來載入插件的資源是行不通的,程序會拋出異常:無法找到某某id所對應的資源。

針對這個問題,有人提出了將插件中的資源在宿主程序中也預置一份,這雖然能解決問題,但是這樣就會產生一些弊端。首先,這樣就需要宿主和插件同時持有一份相同的資源,增加了宿主apk的大小;其次,在這種模式下,每次發布一個插件都需要將資源復制到宿主程序中,這意味著每發布一個插件都要更新一下宿主程序,這就和插件化的思想相違背了。

因為插件化的目的就是要減小宿主程序apk包的大小,同時降低宿主程序的更新頻率並做到自由裝載模塊,所以這種方法不可取,它限制了插件的線上更新這一重要特性。還有人提供了另一種方式,首先將插件中的資源解壓出來,然後通過文件流去讀取資源,這樣做理論上是可行的,但是實際操作起來還是有很大難度的。首先不同資源有不同的文件流格式,比如圖片、XML等,其次針對不同設備載入的資源可能是不一樣的,如何選擇合適的資源也是一個需要解決的問題,基於這兩點,這種方法也不建議使用,因為它實現起來有較大難度。為了方便地對插件進行資源管理,下面給出一種合理的方式。

我們知道,Activity的工作主要是通過ContextImpl來完成的,
Activity中有一個叫mBase的成員變數,它的類型就是ContextImpl。注意到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中的資源,如下所示。
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());
}

從loadResources()的實現可以看出,載入資源的方法是通過反射,通過調用AssetManager中的addAssetPath方法,我們可以將一個apk中的資源載入到Resources對象中,由於addAssetPath是隱藏API我們無法直接調用,所以只能通過反射。下面是它的聲明,通過注釋我們可以看出,傳遞的路徑可以是zip文件也可以是一個資源目錄,而apk就是一個zip,所以直接將apk的路徑傳給它,資源就載入到AssetManager中了。然後再通過AssetManager來創建一個新的Resources對象,通過這個對象我們就可以訪問插件apk中的資源了,這樣一來問題就解決了。
/**

* 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) {

synchronized (this) {

int res = addAssetPathNative(path);

makeStringBlocks(mStringBlocks);

return res;

}

}

接著在代理Activity中實現getAssets()和getResources(),如下所示。關於代理Activity的含義請參看DL開源插件化框架的實現細節,這里不再詳細描述了。
@Override

public AssetManager getAssets() {

return mAssetManager == null ? super.getAssets() : mAssetManager;

}

@Override

public Resources getResources() {

return mResources == null ? super.getResources() : mResources;

}

通過上述這兩個步驟,就可以通過R來訪問插件中的資源了。

2.Activity生命周期的管理

管理Activity生命周期的方式各種各樣,這里只介紹兩種:反射方式和介面方式。反射的方式很好理解,首先通過Java的反射去獲取Activity的各種生命周期方法,比如onCreate、onStart、onResume等,然後在代理Activity中去調用插件Activity對應的生命周期方法即可,如下所示。
@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();

}

使用反射來管理插件Activity的生命周期是有缺點的,一方面是反射代碼寫起來比較復雜,另一方面是過多使用反射會有一定的性能開銷。下面介紹介面方式,介面方式很好地解決了反射方式的不足之處,這種方式將Activity的生命周期方法提取出來作為一個介面(比如叫DLPlugin),然後通過代理Activity去調用插件Activity的生命周期方法,這樣就完成了插件Activity的生命周期管理,並且沒有採用反射,這就解決了性能問題。同時介面的聲明也比較簡單,下面是DLPlugin的聲明:
public interface DLPlugin {

public void onStart();

public void onRestart();

public void onActivityResult(int requestCode, int resultCode, Intent

data);

public void onResume();

public void onPause();

public void onStop();

public void onDestroy();

public void onCreate(Bundle savedInstanceState);

public void setProxy(Activity proxyActivity, String dexPath);

public void onSaveInstanceState(Bundle outState);

public void onNewIntent(Intent intent);

public void onRestoreInstanceState(Bundle savedInstanceState);

public boolean onTouchEvent(MotionEvent event);

public boolean onKeyUp(int keyCode, KeyEvent event);

public void onWindowAttributesChanged(LayoutParams params);

public void onWindowFocusChanged(boolean hasFocus);

public void onBackPressed();



}

在代理Activity中只需要按如下方式即可調用插件Activity的生命周期方法,這就完成了插件Activity的生命周期的管理。
...

@Override

protected void onStart() {

mRemoteActivity.onStart();

super.onStart();

}

@Override

protected void onRestart() {

mRemoteActivity.onRestart();

super.onRestart();

}

@Override

protected void onResume() {

mRemoteActivity.onResume();

super.onResume();

}

...

通過上述代碼應該不難理解介面方式對插件Activity生命周期的管理思想,其中mRemoteActivity就是DLPlugin的實現。

Ⅱ Android瑙f瀽鍖呮椂鐨勯棶棰樿В鍐蟲柟妗(瑙e寘鏈綆鍗曠殑鏂規硶)



鐩鎬俊寰堝氫嬌鐢ˋndroid鏅鴻兘鎵嬫満鐨勭敤鎴峰湪瀹夎匒pk鍒嗘瀽鍖呮椂錛屾垨澶氭垨灝戦兘浼氶亣鍒拌繖縐嶉棶棰樸傗斺斿垎鏋愬寘鏈夐敊璇銆傞偅涔堝備綍瑙e喅榪欐牱鐨勯棶棰樺憿錛熷叾瀹濧pk紼嬪簭瀹夎呭け璐ョ殑鍘熷洜鏈夊緢澶氾紝鍩烘湰閮藉綊緇撲簬鍒嗘瀽鍖呯殑涓鐐圭偣閿欒銆傚洜姝わ紝鎴戜滑鍙鑳介愪竴璋冩煡錛屾壘鍑篈pk紼嬪簭鑳藉 涓嶈佸畨瑁呫備互涓嬫槸瑙e喅姝ょ被闂棰樼殑涓浜涙柟娉曘


鏂規硶/姝ラ


絎涓姝ワ細閫氳繃姝h勬笭閬撹幏鍙栫煡鍚嶅害楂樼殑緗戠珯鐢寵楓傚己鐑堟帹鑽愮殑杞浠朵笅杞藉湴鐐規槸鎵嬫満瀹夊崜甯傚満銆傜綉絝欎笂鐨勮蔣浠舵槸緇忚繃涓ユ牸嫻嬭瘯鍚庡彂甯冪殑銆備笅杞藉埌鎵嬫満涓婂悗錛屼竴鑸閮借兘瀹夎呰繍琛岃壇濂姐傚ぇ閮ㄥ垎杞浠墮兘鍙浠ュ厤璐逛嬌鐢錛屾病鏈夋伓鎰忔彃浠躲


絎浜屾ワ細apk鐗堟湰涓嶅吋瀹廣備竴鑸鏉ヨ達紝褰撲粠緗戜笂涓嬭澆鐨刟pk紼嬪簭鐗堟湰楂樹簬褰撳墠鎵嬫満鐗堟湰鏃跺巻钄斤紝鍦ㄥ畨瑁呯▼搴忔椂鍒嗘瀽鍖呮椂浼氭湁閿欒鎻愮ず銆傝繖縐嶆儏鍐電殑瑙e喅鏂規硶鏄鍦ㄥ畨鍗撳競鍦烘壘涓涓綾諱技鐨勫簲鐢錛屼絾鑺瑰閥鏄鐗堟湰涓嶈兘楂樹簬鐜板湪鐨勬墜鏈虹増鏈錛岀敤浜庝笅杞姐佸畨瑁呭拰鍔熻兘銆


絎涓夋ワ細apk璁″垝涓嶅畬鏁淬傛湁浜涙墜鏈轟笅杞藉伐鍏蜂笉 娌℃湁鏂鐐圭畫浼犵殑鍔熻兘錛屾墍浠ヤ笅杞界殑紼嬪簭鍙鑳戒細涓嶅畬鏁達紝閮ㄥ垎紼嬪簭浼氬厛涓㈠け銆傚逛簬榪欑被闂棰橈紝寤鴻閲嶆柊涓嬭澆錛屾垨鑰呴氳繃鐢佃剳涓嬭澆錛岀劧鍚庡熷姪鏁版嵁綰垮皢apk紼嬪簭澶嶅埗鍒版墜鏈哄瓨鍌ㄥ崱涓婅繘琛屽畨瑁呫


絎鍥涙ワ細鐩鍓嶆墜鏈轟笉鏀鎸佷腑鏂囧悕瀛楁垨璺寰勶紝涔熶笉鏀鎸侀暱鏂囦歡鍚嶃傝В鍐崇殑鍔炴硶鏄閲嶅懡鍚嶆枃浠訛紝騫朵笖鍚嶅瓧鍙鍖呭惈鑻辨枃瀛楁瘝錛屽 quotabc.apk quot銆傚苟鍦ㄦ洿鏀瑰悗閲嶆柊縐誨姩瀹夎呯▼搴忋


絎浜旀ワ細apk璁″垝鍙浠 鐢變簬鎵嬫満鍐呭瓨涓嶈凍銆佹墜鏈哄瓨鍌ㄥ崱鎺ヨЕ涓嶈壇銆佸瓨鍌ㄥ崱璐ㄩ噺涓嶅悎鏍肩瓑鍥犵礌瀵艱嚧鏃犳硶姝e父瀹夎呫傝佽В鍐蟲ょ被闂棰橈紝鍙浠ュ皾璇曞啀嬈℃彃鎷旀墜鏈虹殑鎵╁睍瀛樺偍鍗°傚傛灉鍋氫笉鍒拌繖涓鐐癸紝閭e氨鎹涓涓楂樿川閲忕殑鍐呭瓨鍗°傚傛灉鎵嬫満涓婄敤鐨勬槸姘磋揣鎴栬呭姡璐ㄥ唴瀛樺崱錛屽嵆浣垮唴瀛樺崱瀛樺偍鐨勬暟鎹瀹歸噺澶т簬瀹為檯鍐呭瓨瀹歸噺錛岀▼搴忎篃涓嶄細鎶ラ敊錛屽彧鏄鏁版嵁宸茬粡涓㈠け銆傚湪榪欑嶆儏鍐典笅錛宎pk紼嬪簭鏃犳硶鎴愬姛瀹夎呫


姝ラ6:鎸囧畾鐨勬枃浠惰礬寰勪笉瀛樺湪鎴栨寚瀹氫簡閿欒鐨勮礬寰勩傞氬父錛岃繖浜涚▼搴忓彲浠 鐢變簬RE Manager璁劇疆涓嶅綋瀵艱嚧鏃犳硶鍦ㄧ嚎瀹夎咃細瑙e喅鏂規硶鏄錛氳繘鍏RE Manager錛岀偣鍑昏劇疆-涓閿璁劇疆-涓繪枃浠跺す閫夐」銆傚傛灉璁劇疆涓簊dcard錛屽皢鍑虹幇涓鏉¢敊璇娑堟伅錛屾寚鍑哄垎鏋愬寘鏈夐棶棰樸傚傛灉璁劇疆涓猴紝鍒欏彲浠ユ垚鍔熷畨瑁呫


絎7姝ワ細apk瀹夎呯▼搴忓彲鑳戒笉鍏煎規垨鎸囩ず瀹夎呫傝繖閫氬父鍙戠敓鍦≧OM鎵嬫満涓娿傚洜涓烘墜鏈哄埛瀹屼箣鍚庯紝緋葷粺閲屾湁涓浜涘繀澶囩殑杞浠訛紝姣斿侶ulk錛宨nstall錛屽洜涓洪渶瑕佺畝鍖栨墍浠ユ病鏈夊畨瑁咃紝apk紼嬪簭涔熸棤娉曟e父瀹夎呫傝В鍐蟲柟娉曟槸鍦ㄥ畨鍗撳競鍦轟笅杞界浉鍏崇殑apk瀹夎呯▼搴忥紝鐒跺悗閫氳繃apk瀹夎呯▼搴忓畨瑁卆pk搴旂敤銆


絎鍏姝ワ細鎵嬫満鍙鑳戒腑姣掋備粠瀹夊崜瀚岀儌閿甯傚満涓嬭澆36鎵嬫満0瀹夊叏鍗澹錛屾煡鏉鎵嬫満鐥呮瘨錛屼繚璇佹墜鏈哄勪簬鏈浣沖畨鍏ㄨ繍琛岀姸鎬併


閫氳繃鑰冭檻鍜屾秷闄よ繖浜涙ラわ紝鎮ㄥ彲浠ュ揩閫熻В鍐沖畨瑁卆pk鍒嗘瀽鍖呮椂鐨勯敊璇闂棰樸傚笇鏈涘逛綘鏈夊府鍔┿

鐜嬭呬箣蹇2鐐瑰嚮璇曠帺

熱點內容
共享雲源碼 發布:2024-09-08 10:01:10 瀏覽:395
ios應用上傳 發布:2024-09-08 09:39:41 瀏覽:439
ios儲存密碼哪裡看 發布:2024-09-08 09:30:02 瀏覽:873
opensslcmake編譯 發布:2024-09-08 09:08:48 瀏覽:653
linux下ntp伺服器搭建 發布:2024-09-08 08:26:46 瀏覽:744
db2新建資料庫 發布:2024-09-08 08:10:19 瀏覽:173
頻率計源碼 發布:2024-09-08 07:40:26 瀏覽:780
奧迪a6哪個配置帶後排加熱 發布:2024-09-08 07:06:32 瀏覽:101
linux修改apache埠 發布:2024-09-08 07:05:49 瀏覽:209
有多少個不同的密碼子 發布:2024-09-08 07:00:46 瀏覽:566