Android 使用代理載入外掛
阿新 • • 發佈:2019-02-20
public class PluginActivity extends Activity implements Attachable { public static final String TAG=new String("PluginActivity"); private Activity mProxyActivity; @Override public void attach(Activity activity) { this.mProxyActivity=activity; } @Override public View findViewById(int id) { return mProxyActivity.findViewById(id); } public void onCreate(Bundle paramBundle){ mProxyActivity.setContentView(R.layout.plugin_layout); mImgView=(ImageView) mProxyActivity.findViewById(R.id.pic); mImgView.setImageResource(R.drawable.imgd); mButton1=(Button) mProxyActivity.findViewById(R.id.button1); mButton2=(Button) mProxyActivity.findViewById(R.id.button2); mButtond=(Button) mProxyActivity.findViewById(R.id.buttond); mButton1.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mImgView.setImageResource(R.drawable.img1); } }); mButton2.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mImgView.setImageResource(R.drawable.img2); } }); mButtond.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mImgView.setImageResource(R.drawable.imgd); } }); } @Override public void setContentView(int layoutResID){ mProxyActivity.setContentView(layoutResID); } @Override public void onDestroy() { } @Override public void onPause() { } @Override public void onRestart() { } @Override public void onResume() { } @Override public void onStart() {} @Override public void onStop() {} }
外掛Activity只是簡單的實現了點選Button,並切換圖片的功能。可以看到,在其內部,所有的動作都是由代理Activity來替它完成的。這就是使用代理進行動態載入的基本思想。
9 代理Activity的實現,並管理外掛的生命週期
public class ProxyActivity extends Activity{ private ProxyActivity mSelf; private Attachable mPluginActivity; private AssetManager mAssetManager; private Resources mResources; //……… //……其他的成員變數 @Override public Resources getResources() { return mResources==null ? super.getResources():mResources; } private PackageInfo getUninstalledApkInfo(String archiveFilePath){//上文中已實現………… } private boolean initPlugin(){ //上文中已實現………… } private void loadResources(){ //上文中已實現………… } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mSelf=this; if (!loadApk("plugindemo.apk")){ //載入apk出現問題時,呼叫setContentView,將頁面轉置出錯狀態 setContentView(R.layout.load_plugin_error); return; } if (!initPlugin()){ //初始化外掛出問題時,呼叫setContentView,將頁面轉置出錯狀態 setContentView(R.layout.load_plugin_error); return; } } private boolean loadApk(String apkFile){ //獲取sdcard上apk包的完整路徑 mApkPath=Environment.getExternalStorageDirectory().getAbsolutePath()+ File.separator+apkFile; mPkgInfo=getUninstalledApkInfo(mApkPath); if (mPkgInfo==null){ Log.d(TAG, "loadApk: can't get package information"); return false; } //獲取apk包中package的名稱 String packageName=mPkgInfo.packageName; //建立DexClassLoader的優化目錄,在機器的內部儲存中 File optimizedDirectoryFile=mSelf.getDir("dex", Context.MODE_PRIVATE); DexClassLoader dexClassLoader=new DexClassLoader(mApkPath,optimizedDirectoryFile.toString(),null,mSelf.getClassLoader()); try { mPluginClass=dexClassLoader.loadClass(packageName+".PluginActivity"); } catch (ClassNotFoundException e) { Log.d(TAG, "loadApk: loading class errors."); e.printStackTrace(); return false; } //獲取apk資源 loadResources(); if (mResources==null){ return false; } Log.d(TAG, "loadApk: load apk successfully."); return true; } @Override protected void onDestroy() { super.onDestroy(); if (mPluginActivity!=null) mPluginActivity.onDestroy(); } @Override protected void onStart() { super.onStart(); if (mPluginActivity!=null) mPluginActivity.onStart(); } // 其餘的生命週期方法不再一一列出…………… //……………………………
上述即為代理Activity的實現。在onCreate中進行了apk的載入和外掛的初始化。若出錯則將Activity顯示為出錯介面。
可以看到,通過代理Activity的生命週期方法間接的呼叫了外掛Activity的生命週期方法。從而實現了代理“套殼”的作用。
效果
內建sdcard裡外部儲存中存放外掛apk的位置,sdcard的根目錄下:執行效果: