magic-dynamic_plugin
主要提供了下面三个用途
- 动态加载jar文件
- 动态加载带有资源文件的apk 主要满足换皮肤需求
- 加载apk 满足动态加载activity和service的需求
特点
只需要把magic_plugin.jar文件放入lib目录下面 直接方便
使用:
增加权限
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
1. 动态加载java文件
也就是不涉及到资源文件 在demo中的dynamicclient项目里面 举了一个简单的例子
1. 定义了一个接口IDynamic 只有一个简单的方法getName
通过 在android studio中 生产jar包的方法 我已经在build.gradle中完成了 可以直接使用 通过下面的两部
在terminal中 首先要使目录到dynamicclient下面 cd dynamicclient gradle clean build gradle makeJar
通过上面的三部 我们可以在build/libs目录下面得到一个dynamic.jar文件 我们可以得到想使用的jar包 其实里面只有一个DynamicImpl.class文件
最后一个使用android studio自带的dx工具 把.jar文件转换为dex文件 这样dalvik虚拟机才可以识别并加载
dx --dex --output=dynamicdex.jar dynamic.jar
2. 把生产的dynamicdex.jar文件放到你指定的位置 一般使用的时候应该是从服务器端下载
这里为了简便就直接放在了sd卡上 拷贝一份 IDynamic接口
使用实例的demo 如下
private void loadDexJar() {
new Thread(new Runnable() {
@Override
public void run() {
Context mContext = MainActivity.this;
String dexPath = PluginDemoHelper.getApkPath(PluginDemoHelper.DynamicJar);
PluginInfo mPluginInfo = new PluginInfo(dexPath, PluginDemoHelper.DynamicKey);
PluginManager.loadDexFile(mContext, mPluginInfo);
PluginResource pluginResource = PluginManager.getResourceBean(mContext, PluginDemoHelper.DynamicKey);
if (pluginResource != null) {
try {
Class<?> clazz = pluginResource.mClassLoader.loadClass("com.leaf.dynamicclient.dynamicjar.DynamicImpl");
IDynamic myDynamic = (IDynamic) clazz.newInstance();
if(myDynamic!=null){
Log.d(TAG, "name = " + myDynamic.getName());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
}
2. 带有资源的apk文件
1. 客户端
1. 引用jar包 注意需要使用provided 引用这个jar包
provided files('libs/magic_plugin.jar')
2. activity和service 必须分别继承PluginClientActivity service必须继承PluginClientService
对应activity 必须注意这个对象mProxyActivity mProxyActivity.setContentView(R.layout.activity_main); Activity的跳转使用startPluginActivity
3. 注意在布局文件中的引用字符串和drawable图片资源是不可以的
只能在代码里面类似下面的 mImage = (ImageView) mProxyActivity.findViewById(R.id.image); mImage.setImageResource(R.drawable.image_girl);
4. 在pluginClient目录下 使用gradle clean build 得到apk文件 这里为了简化 直接把apk文件放入sdcard下面
2. 宿主端
1. 在maniefst中
<activity android:name="com.magic.plugin.proxy.PluginProxyActivity"/>
<service android:name="com.magic.plugin.proxy.PluginProxyService"/>
2. 实例: 直接在宿主中启动一个activity
private void loadApkResource() {
new Thread(new Runnable() {
@Override
public void run() {
Context mContext = MainActivity.this;
String dexPath = PluginDemoHelper.getApkPath(PluginDemoHelper.DynamicApk);
PluginInfo mPluginInfo = new PluginInfo(dexPath, PluginDemoHelper.DynamicAPKKey);
PluginManager.loadApk(mContext, mPluginInfo);
Intent intentPlugin = new Intent();
intentPlugin.setClass(MainActivity.this, PluginProxyActivity.class);
Bundle bundle = new Bundle();
bundle.putString(PluginProxyHelper.PLUGIN_CLASS_NAME, "com.leaf.apkpluginclient.MainActivity");
bundle.putString(PluginProxyHelper.PLUGIN_KEY, PluginDemoHelper.DynamicAPKKey);
intentPlugin.putExtras(bundle);
startActivity(intentPlugin);
}
}).start();
}
3. 在宿主端访问资源 一般换皮肤的需求需要在宿主端获取资源
下面的例子 是获取字符串和图片资源的例子 通过PluginManager.getDrawable和PluginManager.getString方法获取 需要注意的一点 如果自己的R文件不是包名+R 如com.leaf.dynamicclient.extra.R 那么在PluginInfo的时候需要使用 去指定准备的R.java路径 如
PluginInfo mPluginInfo = new PluginInfo(dexPath, PluginDemoHelper.DynamicAPKKey,PluginDemoHelper.DynamicPkgR);
private void loadApkResource() {
new Thread(new Runnable() {
@Override
public void run() {
Context mContext = MainActivity.this;
String dexPath = PluginDemoHelper.getApkPath(PluginDemoHelper.DynamicApk);
PluginInfo mPluginInfo = new PluginInfo(dexPath, PluginDemoHelper.DynamicAPKKey);
PluginManager.loadApk(mContext, mPluginInfo);
Drawable pluginDrawable = PluginManager.getDrawable(MainActivity.this, PluginDemoHelper.DynamicAPKKey, "image_girl");
mHandler.obtainMessage(MSG_UPDATE_PLUGIN_IMAGE, pluginDrawable).sendToTarget();
String plugStr = PluginManager.getString(MainActivity.this, PluginDemoHelper.DynamicAPKKey, "app_name");
mHandler.obtainMessage(MSG_UPDATE_PLUGIN_STRING, plugStr).sendToTarget();
}
}).start();
}