Android DynamicLoadApk 开源插件开发项目代码剖析
Posted zhangjiaofa
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android DynamicLoadApk 开源插件开发项目代码剖析相关的知识,希望对你有一定的参考价值。
目前的代码的目录结构是:
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文件)
以上是关于Android DynamicLoadApk 开源插件开发项目代码剖析的主要内容,如果未能解决你的问题,请参考以下文章
Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )
Android 逆向Android 权限 ( Android 逆向中使用的 android.permission 权限 | Android 系统中的 Linux 用户权限 )