六、" 依赖库 " 模块代码
1、插件 Activity 接口
package com.example.plugin_core; import android.app.Activity; import android.os.Bundle; import android.view.MotionEvent; import androidx.annotation.NonNull; public interface PluginActivityInterface { /** * 绑定代理 Activity * @param proxyActivity */ void attach(Activity proxyActivity); void onCreate(Bundle savedInstanceState); void onStart(); void onResume(); void onPause(); void onStop(); void onDestroy(); void onSaveInstanceState(Bundle outState); boolean onTouchEvent(MotionEvent event); void onBackPressed(); }
2、插件 Activity 基类
package com.example.plugin_core; import android.annotation.SuppressLint; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import androidx.appcompat.app.AppCompatActivity; /** * " 插件 " 模块中的 Activity 类都继承该类 * 具体的 Activity 业务类的父类 */ public class BaseActivity extends AppCompatActivity implements PluginActivityInterface { /** * 注入的 Activity , 代理该 Activity 类作为上下文 */ private Activity proxyActivity; /** * 注入代理 Activity * 在 ProxyActivity 中将代理 Activity 组件注入进来 * @param proxyActivity */ @Override public void attach(Activity proxyActivity) { this.proxyActivity = proxyActivity; } @Override public void setContentView(int layoutResID) { // 调用代理 Activity 中的 setContentView 方法 if (proxyActivity != null) { proxyActivity.setContentView(layoutResID); }else{ super.setContentView(layoutResID); } } @Override public void setContentView(View view) { // 调用代理 Activity 中的 setContentView 方法 if (proxyActivity == null) { proxyActivity.setContentView(view); }else{ super.setContentView(view); } } @Override public <T extends View> T findViewById(int id) { if (proxyActivity == null) { return proxyActivity.findViewById(id); }else{ return super.findViewById(id); } } @Override public void startActivity(Intent intent) { if (proxyActivity == null) { intent.putExtra("className", intent.getComponent().getClassName()); proxyActivity.startActivity(intent); }else{ super.startActivity(intent); } } @SuppressLint("MissingSuperCall") @Override public void onCreate(Bundle savedInstanceState) { } @SuppressLint("MissingSuperCall") @Override public void onStart() { } @SuppressLint("MissingSuperCall") @Override public void onResume() { } @SuppressLint("MissingSuperCall") @Override public void onPause() { } @SuppressLint("MissingSuperCall") @Override public void onStop() { } @SuppressLint("MissingSuperCall") @Override public void onDestroy() { } @SuppressLint("MissingSuperCall") @Override public void onSaveInstanceState(Bundle outState) { } }
3、代理 Activity ( 桩 )
package com.example.plugin_core; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.AssetManager; import android.content.res.Resources; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import dalvik.system.DexClassLoader; /** * 插件化框架核心类 */ public class PluginManager { /** * 类加载器 * 用于加载插件包 apk 中的 classes.dex 文件中的字节码对象 */ private DexClassLoader mDexClassLoader; /** * 从插件包 apk 中加载的资源 */ private Resources mResources; /** * 插件包信息类 */ private PackageInfo mPackageInfo; /** * 加载插件的上下文对象 */ private Context mContext; /** * PluginManager 单例 */ private static PluginManager instance; private PluginManager(){ } /** * 获取单例类 * @return */ public static PluginManager getInstance(){ if (instance == null) { instance = new PluginManager(); } return instance; } /** * 加载插件 * @param context 加载插件的应用的上下文 * @param loadPath 加载的插件包地址 */ public void loadPlugin(Context context, String loadPath) { this.mContext = context; // DexClassLoader 的 optimizedDirectory 操作目录必须是私有的 // ( 模式必须是 Context.MODE_PRIVATE ) File optimizedDirectory = context.getDir("cache_plugin", Context.MODE_PRIVATE); // 创建 DexClassLoader mDexClassLoader = new DexClassLoader( loadPath, // 加载路径 optimizedDirectory.getAbsolutePath(), // apk 解压缓存目录 null, context.getClassLoader() // DexClassLoader 加载器的父类加载器 ); // 加载资源 try { // 通过反射创建 AssetManager AssetManager assetManager = AssetManager.class.newInstance(); // 通过反射获取 AssetManager 中的 addAssetPath 隐藏方法 Method addAssetPathMethod = assetManager. getClass(). getDeclaredMethod("addAssetPath", String.class); // 调用反射方法 addAssetPathMethod.invoke(assetManager, loadPath); // 获取资源 mResources = new Resources( assetManager, context.getResources().getDisplayMetrics(), context.getResources().getConfiguration() ); // 获取插件包中的 Activity 类信息 mPackageInfo = context.getPackageManager().getPackageArchiveInfo( loadPath, // 加载的插件包路径 PackageManager.GET_ACTIVITIES); // 获取的包信息类名 } catch (IllegalAccessException e) { // 调用 AssetManager.class.newInstance() 反射构造方法异常 e.printStackTrace(); } catch (InstantiationException e) { // 调用 AssetManager.class.newInstance() 反射构造方法异常 e.printStackTrace(); } catch (NoSuchMethodException e) { // getDeclaredMethod 反射方法异常 e.printStackTrace(); } catch (InvocationTargetException e) { // invoke 执行反射方法异常 e.printStackTrace(); } } /** * 获取类加载器 * @return */ public DexClassLoader getmDexClassLoader() { return mDexClassLoader; } /** * 获取插件包中的 Package 信息 * @return */ public PackageInfo getmPackageInfo() { return mPackageInfo; } /** * 获取插件包中的资源 * @return */ public Resources getmResources() { return mResources; } }
4、插件管理器
package com.example.plugin_core; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.AssetManager; import android.content.res.Resources; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import dalvik.system.DexClassLoader; /** * 插件化框架核心类 */ public class PluginManager { /** * 类加载器 * 用于加载插件包 apk 中的 classes.dex 文件中的字节码对象 */ private DexClassLoader mDexClassLoader; /** * 从插件包 apk 中加载的资源 */ private Resources mResources; /** * 插件包信息类 */ private PackageInfo mPackageInfo; /** * 加载插件的上下文对象 */ private Context mContext; /** * PluginManager 单例 */ private static PluginManager instance; private PluginManager(){ } /** * 获取单例类 * @return */ public static PluginManager getInstance(){ if (instance == null) { instance = new PluginManager(); } return instance; } /** * 加载插件 * @param context 加载插件的应用的上下文 * @param loadPath 加载的插件包地址 */ public void loadPlugin(Context context, String loadPath) { this.mContext = context; // DexClassLoader 的 optimizedDirectory 操作目录必须是私有的 // ( 模式必须是 Context.MODE_PRIVATE ) File optimizedDirectory = context.getDir("cache_plugin", Context.MODE_PRIVATE); // 创建 DexClassLoader mDexClassLoader = new DexClassLoader( loadPath, // 加载路径 optimizedDirectory.getAbsolutePath(), // apk 解压缓存目录 null, context.getClassLoader() // DexClassLoader 加载器的父类加载器 ); // 加载资源 try { // 通过反射创建 AssetManager AssetManager assetManager = AssetManager.class.newInstance(); // 通过反射获取 AssetManager 中的 addAssetPath 隐藏方法 Method addAssetPathMethod = assetManager. getClass(). getDeclaredMethod("addAssetPath", String.class); // 调用反射方法 addAssetPathMethod.invoke(assetManager, loadPath); // 获取资源 mResources = new Resources( assetManager, context.getResources().getDisplayMetrics(), context.getResources().getConfiguration() ); // 获取插件包中的 Activity 类信息 mPackageInfo = context.getPackageManager().getPackageArchiveInfo( loadPath, // 加载的插件包路径 PackageManager.GET_ACTIVITIES); // 获取的包信息类名 } catch (IllegalAccessException e) { // 调用 AssetManager.class.newInstance() 反射构造方法异常 e.printStackTrace(); } catch (InstantiationException e) { // 调用 AssetManager.class.newInstance() 反射构造方法异常 e.printStackTrace(); } catch (NoSuchMethodException e) { // getDeclaredMethod 反射方法异常 e.printStackTrace(); } catch (InvocationTargetException e) { // invoke 执行反射方法异常 e.printStackTrace(); } } /** * 获取类加载器 * @return */ public DexClassLoader getmDexClassLoader() { return mDexClassLoader; } /** * 获取插件包中的 Package 信息 * @return */ public PackageInfo getmPackageInfo() { return mPackageInfo; } /** * 获取插件包中的资源 * @return */ public Resources getmResources() { return mResources; } }