锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

【Android】获取其它apk资源

时间:2023-01-22 21:00:00 28zjw印制板连接器

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 /* flags */);                 } 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 /*useSparse*/);         mAssets = assets;     }

四、资源工具类

package com.zjw.demo.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(pp)) {
                //这个是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);
        }
    }
}
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章