Android 插件化开发(三)—— hook式插件化开发

本文介绍了Android插件化开发中的hook式方法,通过绕过AMS检测,使用ProxyActivity替换并恢复PluginActivity,以及将插件与宿主app合并加载。涉及关键步骤包括创建HookApplication、ProxyActivity,将插件放入assets目录,以及在MainActivity中启动插件Activity。注意在Android-29环境下运行,可能存在兼容性问题,需自行调试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目前插件化加载库VirtualApk使用的就是这种原理,使用很方便,并且功能很强大

原理:
startActivity —> PluginActivity – (Hook ProxyActivity)(AMS)检测,当前要启动的Activity是否注册了)ok —》
ActivityThread(即将加载启动Activity)----(要把这个ProxyActivity 换回来 --> PluginActivity)
这里使用了两次Hook,最后启动PluginActivity的时候也会报错,因为插件并没有安装,这时候就需要将插件和宿主app合在一起加载,所以需要三部
1、绕过AMS检测,使用ProxyActivity替换PluginActivity
2、将ProxyActivity换回PluginActivity
3、将两个apk文件一起加载

tips:仍然需要申请权限,否则插件无法启动

下面是具体步骤
1、创建HookApplication

public class HookApplication extends Application {
   

    public static String pluginPath;

    @Override
    public void onCreate() {
   
        super.onCreate();

        pluginPath = getPluginPath(this,"plugin.apk");
        try {
   
            hookAMSAction();
        } catch (Exception e) {
   
            e.printStackTrace();
        }

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

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

    /**
     * 将assets中的文件(plugin-debug.apk)拷贝到app的缓存目录,然后返回拷贝之后文件的路径
     * @param context
     * @param fileName
     * @return 例如/data/user/0/com.netease.pluginhookandroid9/cache/plugin-debug.apk
     */
    private String getPluginPath(Context context, String fileName) {
   
        File cacheDir = context.getCacheDir();
        if (!cacheDir.exists()){
   
            cacheDir.mkdirs();//没有缓存目录,就创建目录
        }

        File outPath = new File(cacheDir,fileName);//创建输出的文件位置
        if (outPath.exists()){
   
            outPath.delete(); //如果已经存在了就删除
        }

        InputStream is = null;
        FileOutputStream fos = null;

        try {
   
            boolean newFile = outPath.createNewFile();
            if (newFile){
   
                is = context.getAssets().open(fileName);
                fos = new FileOutputStream(outPath);
                byte[] buf = new byte[is.available()];
                int byteCount;

                while ((byteCount = is.read())!=-1){
   
                    fos.write(buf,0,byteCount);
                }
                return outPath.getAbsolutePath();
            }
        }catch (Exception e){
   
            e.printStackTrace(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值