栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【Android】获取其它apk资源

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Android】获取其它apk资源

1,前置条件

path:apk路径

packageName:apk包名

2,如何获取?

可以通过绑定服务时传参;

或者进程间主动通信获取;

3,核心注入类

(1)核心思想是把ContextImpl中mResources替换成咱们自定义的拦截类(ResourcesProxy),就可以实现拦截操作了。而ContextImpl位于ContextWrapper中mBase成员,因为Application是ContextWrapper子类,因此可以通过反射拿到ContextImpl,进而实现依赖注入,完成代理操作。

(2)其次,需要把其它apk路径传给AssetManager,即AssetManager#addAssetPath(String)方法,将路径传入。咱们可以看下源码。

跟进到#addAssetPathInternal,传入overlay参数为false,继续跟进#ApkAssets.loadFromPath()

private int addAssetPathInternal(String path, boolean overlay, boolean appAsLib) {
        Objects.requireNonNull(path, "path");
        synchronized (this) {
            ensureOpenLocked();
            final int count = mApkAssets.length;

            // See if we already have it loaded.
            for (int i = 0; i < count; i++) {
                if (mApkAssets[i].getAssetPath().equals(path)) {
                    return i + 1;
                }
            }

            final ApkAssets assets;
            try {
                if (overlay) {
                    // TODO(b/70343104): This hardcoded path will be removed once
                    // addAssetPathInternal is deleted.
                    final String idmapPath = "/data/resource-cache/"
                            + path.substring(1).replace('/', '@')
                            + "@idmap";
                    assets = ApkAssets.loadOverlayFromPath(idmapPath, 0 );
                } else {
                    assets = ApkAssets.loadFromPath(path,
                            appAsLib ? ApkAssets.PROPERTY_DYNAMIC : 0);
                }
            } catch (IOException e) {
                return 0;
            }

            mApkAssets = Arrays.copyOf(mApkAssets, count + 1);
            mApkAssets[count] = assets;
            nativeSetApkAssets(mObject, mApkAssets, true);
            invalidateCachesLocked(-1);
            return count + 1;
        }
    }

(3)跟进#ApkAssets.loadFromPath(),创建ApkAssets类,进而在native层加载path路径中apk资源,

private ApkAssets(@FormatType int format, @NonNull String path, @PropertyFlags int flags,
            @Nullable AssetsProvider assets) throws IOException {
        Objects.requireNonNull(path, "path");
        mFlags = flags;
        mNativePtr = nativeLoad(format, path, flags, assets);
        mStringBlock = new StringBlock(nativeGetStringBlock(mNativePtr), true );
        mAssets = assets;
    }
4,资源工具类
package com.incall.apps.navi.service.util;

import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;


public final class ResourcesHelper {

    private static final String TAG = "ResourcesUtils";

    private static Resources sOtherResources = null;
    private static AssetManager sOtherAssetManager = null;

    private static final int INVALID_ID = -1;
    private static String sOtherPackageName;

    public static void inject(Context context, String path, String otherPackageName) {
        try {
            //创建assetManager
            sOtherAssetManager = AssetManager.class.newInstance();R
            Method addAssetPath = sOtherAssetManager.getClass().getMethod("addAssetPath", String.class);
            addAssetPath.invoke(sOtherAssetManager, path);

            //创建resources
            Context app = context.getApplicationContext();
            sOtherResources = new Resources(sOtherAssetManager, app.getResources().getDisplayMetrics(), app.getResources().getConfiguration());

            //获取包名
            sOtherPackageName = otherPackageName;

            //注入代理
            injectResourcesProxy(app);
        } catch (Exception e) {
            Log.e(TAG, e.getMessage());
        }
    }

    private static void injectResourcesProxy(Context app) {
        try {
            Class contextImplClass = Class.forName("android.app.ContextImpl");
            Class contextWrapperClass = Class.forName("android.content.ContextWrapper");
            if (contextImplClass.isInstance(app)) {
                Field mResources = app.getClass().getDeclaredField("mResources");
                mResources.setAccessible(true);

                Resources proxyResources = new ProxyResources(app);
                mResources.set(app, proxyResources);

                Log.d(TAG, "inject resources success");
            } else if (contextWrapperClass.isInstance(app)) {
                //这个是ContextImpl
                Field contextImpl = contextWrapperClass.getDeclaredField("mBase");
                contextImpl.setAccessible(true);
                Object contextImplObj = contextImpl.get(app);

                if (contextImplObj == null) {
                   Log.e(TAG, "check android version :contextImplObj == null");
                    return;
                }

                Field mResources = contextImplObj.getClass().getDeclaredField("mResources");
                mResources.setAccessible(true);

                Resources proxyResources = new ProxyResources(app);
                mResources.set(contextImplObj, proxyResources);

                Log.d(TAG, "inject resources success");
            }
        } catch (Exception e) {
           Log.e(TAG, e.getMessage());
        }
    }

    private static int getResourcesId(String resName, String defType) {
        if (sOtherResources == null) {
            return INVALID_ID;
        }

        return sOtherResources.getIdentifier(resName, defType, sOtherPackageName);
    }

    public static AssetManager getOtherAssetManager() {
        return sOtherAssetManager;
    }

    public static Drawable getDrawable(String resName, String defType) {
        int resourcesId = getResourcesId(resName, defType);
        if (resourcesId == INVALID_ID) {
            return null;
        }

        return sOtherResources.getDrawable(resourcesId);
    }

    public static int getColor(String resName, String defType) {
        int resourcesId = getResourcesId(resName, defType);
        if (resourcesId == INVALID_ID) {
            return 0;
        }
        return sOtherResources.getColor(resourcesId);
    }

    
    private static class ProxyResources extends Resources {

        private final Set ids = new HashSet<>();

        public ProxyResources(Context context) {
            super(context.getAssets(), context.getResources().getDisplayMetrics(), context.getResources().getConfiguration());
        }

        @Override
        public Drawable getDrawable(int id, @Nullable Theme theme) throws NotFoundException {
            if (sOtherResources != null && ids.contains(id)) {
                try {
                    Drawable drawable = sOtherResources.getDrawable(id, theme);
                    if (drawable != null) {
                        return drawable;
                    }
                } catch (NotFoundException e) {
                   Log.d(TAG, e.getMessage());
                }
            }
            return super.getDrawable(id, theme);
        }

        @Override
        public int getColor(int id, @Nullable Theme theme) throws NotFoundException {
            if (sOtherResources != null && ids.contains(id)) {
                try {
                    int color = sOtherResources.getColor(id, theme);
                    if (color != 0) {
                        return color;
                    }
                } catch (NotFoundException e) {
                   Log.d(TAG, e.getMessage());
                }
            }
            return super.getColor(id, theme);
        }

        @Override
        public int getColor(int id) throws NotFoundException {
            if (sOtherResources != null && ids.contains(id)) {
                try {
                    int color = sOtherResources.getColor(id);
                    if (color != 0) {
                        return color;
                    }
                } catch (NotFoundException e) {
                   Log.d(TAG, e.getMessage());
                }
            }
            return super.getColor(id);
        }

        @Override
        public Drawable getDrawable(int id) throws NotFoundException {
            if (sOtherResources != null && ids.contains(id)) {
                try {
                    Drawable drawable = sOtherResources.getDrawable(id);
                    if (drawable != null) {
                        return drawable;
                    }
                } catch (NotFoundException e) {
                   Log.d(TAG, e.getMessage());
                }
            }
            return super.getDrawable(id);
        }

        @Override
        public int getIdentifier(String name, String defType, String defPackage) {
            if (sOtherResources != null && ids.contains(id)) {
                int resId = sOtherResources.getIdentifier(name, defType, sOtherPackageName);
                if (resId != 0) {
                    ids.add(resId);
                    return resId;
                }
            }
            return super.getIdentifier(name, defType, defPackage);
        }

        @Override
        public AssetFileDescriptor openRawResourceFd(int id) throws NotFoundException {
            if (sOtherResources != null && ids.contains(id)) {
                return sOtherResources.openRawResourceFd(id);
            }
            return super.openRawResourceFd(id);
        }


        @NonNull
        @Override
        public InputStream openRawResource(int id, TypedValue value) throws NotFoundException {
            if (sOtherResources != null && ids.contains(id)) {
 
                return sOtherResources.openRawResource(id, value);
                
            }
            return super.openRawResource(id, value);
        }
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/978115.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号