Android DynamicLoadApk 開源外掛程式開發項目代碼剖析,androidstudio外掛程式
目前的代碼的目錄結構是:
1、com.ryg.dynamicload.internal
2、com.ryg.dynamicload.service
3、com.ryg.dynamicload
4、com.ryg.dynamicload.utils
先看com.ryg.dynamicload.internal包下面的幾個類:
1、DLAttachable
DL是DynamicLoad的縮寫,Attachable是可串連的,整體的意思就是動態載入可以串連的。本質上這是一個介面,介面裡面有一個方法,attach,其中的參數是外掛程式開發所需要的代理DLPlugin,以及外掛程式開發管理器DLPluginManager。
/**
* when the proxy impl ( {@see DLProxyImpl#launchTargetActivity()} ) launch
* the plugin activity , dl will call this method to attach the proxy activity
* and pluginManager to the plugin activity. the proxy activity will load
* the plugin's resource, so the proxy activity is a resource delegate for
* plugin activity.
*
* @param proxyActivity a instance of DLPlugin, {@see DLBasePluginActivity}
* and {@see DLBasePluginFragmentActivity}
* @param pluginManager DLPluginManager instance, manager the plugins
*/
大致翻譯一下文檔上面的這段英文:
當代理實作類別啟動了外掛程式的Activity,DL將會調用這個方法將代理Activity與外掛程式管理器串連到外掛程式Activity中,代理Activity將會載入外掛程式的資源,所以代理Activity是外掛程式內部的Activity的一個資源託管。
2、DLIntent
DLIntent是Intent的子類,它內部含有兩個成員變數,分別是需要啟動的外掛程式的包名以及需要啟動的外掛程式的類名。
3、DLPluginManager
先分析其內部的成員變數,
先是三個整型常量:
START_RESULT_SUCCESS
START_RESULT_NO_PKG
START_RESULT_NO_CLASS
START_RESULT_TYPE_ERROR
分別表示 外掛程式啟動成功、沒有找到指定的外掛程式的包名、沒有找到需要啟動的外掛程式的其中某一個class,還有就是指定的class的類型錯誤
還有一個變數是指定外掛程式的so的目錄
其中的方法無外乎 擷取Dex,啟動服務、停止服務、綁定服務、解除綁定定服務、啟動Activity、載入指定class名的class、拷貝so檔案等。
3、DLPluginPackage
字面意思看,指定的是一個外掛程式的Apk。
看一下其中的註解:
* A plugin apk. Activities in a same apk share a same AssetManager, Resources
* and DexClassLoader.
一個外掛程式的Apk,在一個相同的Apk中的一系列的Activities共用一個相同的AssetManager、Resources以及DexClassLoader。
成員變數如下:
1、外掛程式的完整包名
2、預設的Activity的名稱
3、Dex類載入器
4、AssetManager對象
5、資源Resources對象
5、包的相關描述對象 PackageInfo對象
4、DLProxyImpl
字面意思是外掛程式代理的實現。
註解如下:
* This is a plugin activity proxy, the proxy will create the plugin activity
* with reflect, and then call the plugin activity's attach、onCreate method, at
* this time, the plugin activity is running.
這是一個外掛程式Activity的代理,代理將會利用反射建立外掛程式Activity,同時調用外掛程式Activity的attach以及onCreate的方法,此時外掛程式Activity就處於啟動並執行狀態了。
成員變數如下:
private String mClass;
private String mPackageName;
private DLPluginPackage mPluginPackage;
private DLPluginManager mPluginManager;
private AssetManager mAssetManager;
private Resources mResources;
private Theme mTheme;
private ActivityInfo mActivityInfo;
private Activity mProxyActivity;
protected DLPlugin mPluginActivity;
public ClassLoader mPluginClassLoader;
1、當前的外掛程式Activity的類名
2、當前外掛程式Activity的包名
3、標識當前的外掛程式Apk的對象
4、外掛程式管理器
5、Asset管理器
6、資源管理員
7、主題對象
8、描述當前的外掛程式Activity的相關的資訊的對象
9、代理Activity的對象
10、外掛程式的介面
11、類載入器
5、DLServiceAttachable
這個類與DLAttachable的功能是類似的,只不過是一個是針對Activity,一個是針對service。
6、DLServiceProxyImpl
在建構函式中,其中需要的參數是代理服務物件。
初始化init的函數是一個intent的對象。
內部的流程簡介如下:
1、利用類載入器載入指定的外掛程式內部的服務的名稱,實際上是利用反射建立對象
2、將外掛程式內部的Service對象綁定到代理Service對象上面
3、直接調用外掛程式Service的onCreate的方法
接下來再看com.ryg.dynamicload包下面的幾個類:
1、DLBasePluginActivity
其中成員變數如下:
/**
* 代理activity,可以當作Context來使用,會根據需要來決定是否指向this
*/
protected Activity mProxyActivity;
/**
* 等同於mProxyActivity,可以當作Context來使用,會根據需要來決定是否指向this<br/>
* 可以當作this來使用
*/
protected Activity that;
protected DLPluginManager mPluginManager;
protected DLPluginPackage mPluginPackage;
1、代理Activity是真正運行中的Activity
2、外掛程式管理器
3、外掛程式的包名
4、預設是來自於外掛程式的內部
下面對這個類中的主要方法做下面的介紹:
1、代理Activity的賦值
2、指向外掛程式Apk對象的本身的賦值
3、同時發現,類似onCreate、setContentView等與Activity相關的方法,判斷是內部啟動還是外部啟動,如果是內部啟動,完全可以不需要代理Activity的處理,如果是外部
啟動,凡是與Activity相關的,均需要代理Activity處理
4、有一點要注意,凡是調用了onAttach,均是屬於外部的啟動
2、DLBasePluginFragmentActivity
這個類與DLBasePluginActivity同理,不再進行贅述。
3、DLPlugin
這是一個外掛程式開發的介面,介面中的方法如下:
public void onCreate(Bundle savedInstanceState);
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 attach(Activity proxyActivity, DLPluginPackage pluginPackage);
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();
public boolean onCreateOptionsMenu(Menu menu);
public boolean onOptionsItemSelected(MenuItem item);
基本上囊括了Activity中的所有系統的方法。
4、DLProxyActivity
外掛程式Activity的代理類。
其中的成員變數包括:1、DLPlugin 2、DLProxyImpl 一個是指向外掛程式對象 一個是指向代理的實現的對象
既然是外掛程式的代理類,很顯然,這裡面的實現方法我們都能夠猜測的到,凡是與Activity相關的方法,一方面會調用外掛程式自身Activity的方法,另一個方面,在同樣的方法中,會調用代理Activity中的方法。
5、DLProxyFragmentActivity
與DLProxyActivity類似,不再贅述。
6、DLProxyService
這個是Service代理服務。
從上面的變數看,主要包括下面的三點:
1、Service的代理實現
2、外掛程式內部本身的Service
3、外掛程式的管理器
在功能的實現上,其實與Activity的代理實現是一樣的,凡是關鍵性的內部方法均是代理類與外掛程式類同時調用,其餘不再贅述。
7、DLServicePlugin
囊括了Service的關鍵性的方法的介面,不再贅述。
最後再來看com.ryg.dynamicload.util包下面的幾個類:
1、DLConfigs
儲存與擷取so的修改時間
2、DLConstants
在這個常量類中,主要是配置下面幾大類常量
1、內部啟動還是外部啟動
2、Dex路徑 以及相關的包名 儲存的Tag
3、Activity的相關的類型
4、CPU的相關的體繫結構
3、DLUtils
這個一個工具類
包含下面一組功能
1、擷取在Sdk目錄下指定外掛程式Apk檔案的包名 getPackageInfo
2、擷取在Sdk目錄下指定外掛程式Apk檔案的應用表徵圖 getAppIcon
3、擷取在Sdk目錄下指定外掛程式Apk檔案的應用程式名稱 getAppLabel
4、還有就是利用反射機制擷取指定的外掛程式Activity中的類型
4、SoLibManager
1、擷取CPU相關的資訊 2、線上程中將外掛程式的so檔案拷貝到 當前工程目錄的so檔案的目錄檔案夾中(根據當前的cpu體繫結構,拷貝合適的so檔案)
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。