美文网首页
Android插件化demo

Android插件化demo

作者: Android刘东 | 来源:发表于2020-07-17 14:31 被阅读0次

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);
    }
}

参考

相关文章

网友评论

      本文标题:Android插件化demo

      本文链接:https://www.haomeiwen.com/subject/fayghktx.html