思路:打开插件包里边的activity时 统一都用 一个ProxyActivity作为代理
1、首先宿主APP提供ProxyActivity,当宿主需要打开插件包中的Activity时,一律是启动的ProxyActivity,
在启动ProxyActivity的intent中携带我们真正需要去打开的插件包中Activity的类全名。
public class ProxyActivity extends Activity {
private IPluginActivity mPluginActivity;//用来接收插件包所有Activity的接口对象
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String className = getIntent().getStringExtra("className");
try {
Class activityClass = getClassLoader().loadClass(className);
Constructor constructor = activityClass.getConstructor(new Class[]{});
Object instance = constructor.newInstance(new Object[]{});
mPluginActivity = (PluginBaseActivity) instance;
mPluginActivity.onCreate(savedInstanceState);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void onStart() {
super.onStart();
mPluginActivity.onStart();
}
@Override
protected void onResume() {
super.onResume();
mPluginActivity.onResume();
}
@Override
protected void onPause() {
super.onPause();
mPluginActivity.onPause();
}
@Override
protected void onStop() {
super.onStop();
mPluginActivity.onStop();
}
@Override
protected void onDestroy() {
super.onDestroy();
mPluginActivity.onDestroy();
}
}
在Activity中有很重要的两个回调方法:
@Override
public ClassLoader getClassLoader() {
return PluginManager.getInstance().getPluginBean().getDexClassLoader();
}
@Override
public Resources getResources() {
return PluginManager.getInstance().getPluginBean().getResources();
}
- getClassLoader返回的是ClassLoader 对象,Activity内部在使用反射new对象时,都会去使用这里返回的ClassLoader 来进行反射,所以我们ProxyActivity中需要提供的应该是当前加载插件包对应的ClassLoader 。
- getResources返回的是Resources 对象,Activity内部在使用资源文件时,都会去使用这里返回的Resources 来获取资源,所以我们ProxyActivity中需要提供的应该是当前加载插件包对应的Resources 。
我们宿主APP提供了一个ProxyActivity,我们打开插件包Activity其实都是打开的ProxyActivity,只不过ProxyActivity不做任何其他事情,只负责实例化插件包Activity,并且将ProxyActivity中的所有事 件驱动通知给插件包Activity,也就是ProxyActivity调用了插件包Activity中的代码来实现插件包要实现的功能。
获得classLoader和resource:
File pluginFile;//插件包文件
PackageManager packageManager = context.getPackageManager();
PackageInfo packageInfo = packageManager.getPackageArchiveInfo(pluginFile.getAbsolutePath(), PackageManager.GET_ACTIVITIES);
File dexOutFile = context.getDir("dex", Context.MODE_PRIVATE);
DexClassLoader dexClassLoader = new DexClassLoader(pluginFile.getAbsolutePath(), dexOutFile.getAbsolutePath()
, null, context.getClassLoader());
AssetManager assetManager = AssetManager.class.newInstance();
Method addAssetPath = AssetManager.class.getMethod("addAssetPath", String.class);
addAssetPath.invoke(assetManager, pluginFile.getAbsolutePath());
Resources resources = new Resources(assetManager, context.getResources().getDisplayMetrics(), context.getResources().getConfiguration());
PackageInfo 可以获取插件包manifest中所有注册了的组件信息,例如主Activity的全类名的获取为:
packageInfo.activities[0].name
下面是完整的
public abstract class PluginBaseActivity extends AppCompatActivity implements IPluginActivity {
protected Activity that;//宿主Activity
@Override
public void attach(ProxyActivity proxyActivity) {
if (that != null)
throw new RuntimeException("Plugin's activity already has been attached!");
this.that = proxyActivity;
attachBaseContext(proxyActivity);
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
if (that == null) {
super.onCreate(savedInstanceState);
}
}
@Override
public void onStart() {
if (that == null) {
super.onStart();
}
}
@Override
public void onResume() {
if (that == null) {
super.onResume();
}
}
@Override
public void onPause() {
if (that == null) {
super.onPause();
}
}
@Override
public void onStop() {
if (that == null) {
super.onStop();
}
}
@Override
public void onDestroy() {
if (that == null) {
super.onDestroy();
}
}
@Override
public void onSaveInstanceState(Bundle outState) {
if (that == null) {
super.onSaveInstanceState(outState);
}
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
if (that == null) {
super.onRestoreInstanceState(savedInstanceState);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (that == null) {
return super.onTouchEvent(event);
}
return false;
}
@Override
public void onBackPressed() {
if (that == null) {
super.onBackPressed();
}
}
@Override
public void setContentView(View view) {
if (that == null) {
super.setContentView(view);
} else {
that.setContentView(view);
}
}
@Override
public void setContentView(int layoutResID) {
if (that == null) {
super.setContentView(layoutResID);
} else {
that.setContentView(layoutResID);
}
}
@Override
public void startActivity(Intent intent) {
if (that == null) {
super.startActivity(intent);
} else {//篡改intent打开页面为proxyActivity
intent.putExtra("className", intent.getComponent().getClassName());
intent.setClassName(intent.getComponent().getPackageName(), ProxyActivity.class.getName());
that.startActivity(intent);
}
}
@Override
public ComponentName startService(Intent intent) {
if (that == null) {
return super.startService(intent);
} else {
intent.putExtra("className", intent.getComponent().getClassName());
intent.setClassName(intent.getComponent().getPackageName(), ProxyService.class.getName());
return that.startService(intent);
}
}
@Override
public View findViewById(int id) {
if (that == null) {
return super.findViewById(id);
} else {
return that.findViewById(id);
}
}
@Override
public Intent getIntent() {
if (that == null) {
return super.getIntent();
} else {
return that.getIntent();
}
}
@Override
public Window getWindow() {
if (that == null) {
return super.getWindow();
} else {
return that.getWindow();
}
}
@Override
public WindowManager getWindowManager() {
if (that == null) {
return super.getWindowManager();
} else {
return that.getWindowManager();
}
}
}
public interface IPluginActivity {
void attach(ProxyActivity proxyActivity);
void onCreate(@Nullable Bundle savedInstanceState);
void onStart();
void onResume();
void onPause();
void onStop();
void onDestroy();
void onSaveInstanceState(Bundle outState);
void onRestoreInstanceState(Bundle savedInstanceState);
boolean onTouchEvent(MotionEvent event);
void onBackPressed();
void setContentView(View view);
void setContentView(int layoutResID);
void startActivity(Intent intent);
ComponentName startService(Intent intent);
View findViewById(int id);
Intent getIntent();
Window getWindow();
WindowManager getWindowManager();
}
以上步骤实则每次新打开的插件里的页面其实都是ProxyActivity 做的代理
浙公网安备 33010602011771号