1.主App
插件apk需要放入手机内存,模拟一下
adb push /Users/admin/Downloads/plugin-debug.apk /storage/emulated/0/Android/data/com.github.xch168.plugindemo/files/pluginmodule-debug2.apk
1)MainActivity.java
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void launchPluginActivity(View view) {
// adb push /Users/admin/Downloads/plugin-debug.apk /storage/emulated/0/Android/data/com.github.xch168.plugindemo/files/pluginmodule-debug2.apk
Intent intent = new Intent();//com.github.xch168.plugin.TestActivity com.github.xch168.plugin
intent.putExtra(ProxyActivity.PLUGIN_DEX_PATH,
"/storage/emulated/0/Android/data/com.github.xch168.plugindemo/files/pluginmodule-debug2.apk");
intent.putExtra(ProxyActivity.PLUGIN_ACTIIVTY_CLASS_NAME, "com.github.xch168.plugin.TestActivity");
intent.setClass(MainActivity.this, ProxyActivity.class);
startActivity(intent);
}
}
2)ProxyActivity.java
核心类
import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import dalvik.system.DexClassLoader;
public class ProxyActivity extends AppCompatActivity {
public static final String PLUGIN_DEX_PATH = "plugin.dex.path";
public static final String PLUGIN_ACTIIVTY_CLASS_NAME = "plugin.activity.class.name";
Activity mPluginActivity = null;
Resources mPluginResourcs = null;
String mPluginDexPath;
String mPluginActivityClassName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
test(savedInstanceState);
}
void test(Bundle savedInstanceState) {
Intent intent = getIntent();
if (intent != null) {
// 从Intent中获得要启动的功能Apk的路径和Activity完整类名
mPluginDexPath = intent.getStringExtra(PLUGIN_DEX_PATH);
mPluginActivityClassName = intent.getStringExtra(PLUGIN_ACTIIVTY_CLASS_NAME);
if (TextUtils.isEmpty(mPluginDexPath) || TextUtils.isEmpty(mPluginActivityClassName)) {
return;
}
loadApkResources(); // 加载资源
// 根据apk路径加载apk代码到DexClassLoader中
File dexOutputDir = this.getDir("dex", 0);
DexClassLoader dexClassLoader = new DexClassLoader(mPluginDexPath,
dexOutputDir.getAbsolutePath(), null, ClassLoader.getSystemClassLoader());
if (dexClassLoader == null) {
return;
}
// 从DexClassLoader中获得功能Activity Class对象并通过反射创建一个功能Activity实例
Class pluginActivityClass = null;
try {
pluginActivityClass = dexClassLoader.loadClass(mPluginActivityClassName);
mPluginActivity = (Activity) pluginActivityClass.newInstance();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
// 调用功能Activity的setProxyActivity方法,给其设置代理Activity
try {
Method setProxyActivityMethod = pluginActivityClass.getDeclaredMethod("setProxyActivity", Activity.class);
setProxyActivityMethod.invoke(mPluginActivity, this);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
// 调用功能Activity实例的onCreate方法
try {
Method onCreateMethod = Activity.class.getDeclaredMethod("onCreate", Bundle.class);
onCreateMethod.setAccessible(true);
onCreateMethod.invoke(mPluginActivity, savedInstanceState);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
// 加载插件Apk的资源
private void loadApkResources() {
try {
AssetManager assetManager = AssetManager.class.newInstance(); // 通过反射创建一个AssetManager对象
Method addAssetPathMethod = AssetManager.class.getDeclaredMethod("addAssetPath", String.class); // 获得AssetManager对象的addAssetPath方法
addAssetPathMethod.invoke(assetManager, mPluginDexPath); // 调用AssetManager的addAssetPath方法,将apk的资源添加到AssetManager中管理
mPluginResourcs = new Resources(assetManager,
super.getResources().getDisplayMetrics(),
super.getResources().getConfiguration()); // 根据AssetMananger创建一个Resources对象
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
// 重写ProxyActivity的getResources方法,让其返回插件Apk的资源对象
@Override
public Resources getResources() {
if (mPluginResourcs != null) {
return mPluginResourcs;
}
return super.getResources();
}
}
2.插件App
1)TestActivity.java
import android.app.Activity;
import android.os.Bundle;
public class TestActivity extends Activity {
Activity mProxyActivity = null;
public void setProxyActivity(Activity proxyActivity) {
mProxyActivity = proxyActivity;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
// super.onCreate(savedInstanceState);
mProxyActivity.setContentView(R.layout.activity_plugin);
}
}
网友评论