Android 插件化

什么是插件化

在这里插入图片描述

占位式插件化

宿主App无法直接加载插件apk的Activity,因此需要一个代理的Activity,所以称之为占位式插件化。
在这里插入图片描述
具体看操作,开始上代码:

宿主App:
MainActivity:

宿主Activity 调用插件Activity 不能直接startActivity 所以只能通过start ProxyActivity来开启插件Activity。

	//开启插件Activity
	 public void startPlugin(View view) {

        String path = Environment.getExternalStorageDirectory().getPath()+ File.separator+"plugin.apk";
        // 获取插件包 里面的 Activity
        PackageInfo packageArchiveInfo = getPackageManager().getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES);
        ActivityInfo activity = packageArchiveInfo.activities[packageArchiveInfo.activities.length-1];
        Intent intent = new Intent(this,ProxyActivity.class);
        intent.putExtra("className",activity.name);
        startActivity(intent);
    }

//加载插件	
 public void loadPlugin(View view) {
        PluginManager.getInstance(this).loadPlugin();
    }
	
PluginManager:
	//加载插件
	 public void loadPlugin(){
        String path = Environment.getExternalStorageDirectory().getPath()+File.separator+"plugin.apk";
        File file = new File(path);
        if (!file.exists()){
            return;
        }
        // dexClassLoader需要一个缓存目录   /data/data/当前应用的包名/plugin
        File fileDir = context.getDir("plugin", Context.MODE_PRIVATE);
        classLoader = new DexClassLoader(path,fileDir.getPath(),null,context.getClassLoader());


        try {
            // 加载资源
            AssetManager assetManager = AssetManager.class.newInstance();
            Method addAssetPathMethod = assetManager.getClass().getMethod("addAssetPath", String.class);
            addAssetPathMethod.invoke(assetManager, path); // 插件包的路径   pluginPaht
            Resources r = context.getResources(); // 宿主的资源配置信息
            // 特殊的 Resources,加载插件里面的资源的 Resources
            resources = new Resources(assetManager, r.getDisplayMetrics(), r.getConfiguration()); // 参数2 3  资源配置信息
        } catch (Exception e){
            e.printStackTrace();
        }

    }
ProxyActivity

ProxyActivity 通过宿主APP 和 插件APP定义的标准 (ActivityInterface )通过反射创建插件Activity对象,并调用插件的onCreate 方法

	 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_proxy);
        // 真正的加载 插件里面的 Activity
        String className = getIntent().getStringExtra("className");
        try {
            Class<?> mPluginActivityClass = getClassLoader().loadClass(className);
            Constructor<?> mPluginActivityConstructor = mPluginActivityClass.getConstructor(new Class[]{});
            Object mPluginActivity = mPluginActivityConstructor.newInstance(new Object[]{});
            ActivityInterface activityInterface = (ActivityInterface) mPluginActivity;

            // 注入
            activityInterface.mainAppContext(this);

            Bundle bundle = new Bundle();
            bundle.putString("appName", "我是宿主传递过来的信息");

            // 执行插件里面的onCreate方法
            activityInterface.onCreate(bundle);


        } catch (Exception e) {
            e.printStackTrace();
        }

    }
    
    @Override
    public void startActivity(Intent intent) {
        String className = intent.getStringExtra("className");

        Intent proxyIntent = new Intent(this, ProxyActivity.class);
        proxyIntent.putExtra("className", className); // 包名+插件中的activity

        super.startActivity(proxyIntent);

    }
	
	//替换成插件的 ClassLoader
    @Override
    public ClassLoader getClassLoader() {
        return PluginManager.getInstance(this).getClassLoader();
    }

	//替换成插件的 资源文件
    @Override
    public Resources getResources() {
        return PluginManager.getInstance(this).getResources();
    }

宿主和插件定义的标准 standard(mode) 宿主和插件同时依赖
	
public interface ActivityInterface {
   
    void mainAppContext(Activity activity);
    void onCreate(Bundle savedInstanceState);
    void onStart();
    void onResume();
    void onDestroy();

}

插件APK
BaseActivity
	public class BaseActivity extends Activity implements ActivityInterface {
	
	//宿主Activity 对象
    protected Activity mainActivity;
    @Override
    public void mainAppContext(Activity activity) {
        this.mainActivity = activity;
    }

    @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 onDestroy() {

    }

    public void setContentView(int resId) {
        mainActivity.setContentView(resId);
    }

    public View findViewById(int layoutId) {
        return mainActivity.findViewById(layoutId);
    }

    @Override
    public void startActivity(Intent intent) {

        Intent intentNew= new Intent();
        intentNew.putExtra("className", intent.getComponent().getClassName());
        mainActivity.startActivity(intentNew);
    }

}

PluginMainActivity

当代理Activity 调用 PluginMainActivity的onCreate方法的时候,setContentView(R.layout.activity_main) 其实就相当于代理Activity 调用了setContentView(R.layout.activity_main);方法。
插件apk 跳转自己包中的Activity时其实就是代理Activity 开启一个自身Activity。

	public class PluginMainActivity extends BaseActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toast.makeText(mainActivity, "我是插件", Toast.LENGTH_SHORT).show();

        findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(mainActivity,PluginActivity2.class);
                startActivity(intent);
            }
        });
    }

}

未完待续。。。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值