android加载第三方图标机制分析

android加载第三方图标机制分析

 

系统如何获取图片等资源

当我们调用Resources.java 来获取图片等资源的时候会调用getDrawable 方法, getDrawable最终把这还是使用loadDrawable 方法来处理.

Resources.java

public Drawable getDrawable(int id) throws NotFoundException {

TypedValue value;

synchronized (mAccessLock) {

            value = mTmpValue;

            if (value == null) {

                value = new TypedValue();

            } else {

                mTmpValue = null;

            }

            getValue(id, value, true);

}

 Drawable res = loadDrawable(value, id);

synchronized (mAccessLock) {

            if (mTmpValue == null) {

                mTmpValue = value;

            }

}

return res;

}

 

loadDrawable 方法在获取资源的时候会先判断该资源是否在缓存中,如果在缓存中就直接获取返回,如果没有就继续查询.同时使用color配置的图片的资源也会先去缓存中读取,这样可以提高代码的效率.如果还是没有找到就会调用AssetManager.java 的openNonAsset 方法,再接着分析会发现调用的是Jni 的一个方法openNonAssetNative,Jni 最终会去调用AssetManager.cpp 的openNonAsset的方法来根据不同主题去获取对应的资源.

 

frameworks/base/core/jni/android_util_AssetManager.cpp  àopenNonAssetNative

static jint android_content_AssetManager_openNonAssetNative(JNIEnv* env, jobject clazz,

jint cookie,

                                                         jstring fileName,

jint mode)

{

    AssetManager* am = assetManagerForJavaObject(env, clazz);

if (am == NULL) {

return 0;

}

 

ALOGV("openNonAssetNative in %p (Java object %p)\n", am, clazz);

 

ScopedUtfChars fileName8(env, fileName);

if (fileName8.c_str() == NULL) {

return -1;

}

 

if (mode != Asset::ACCESS_UNKNOWN && mode != Asset::ACCESS_RANDOM

&& mode != Asset::ACCESS_STREAMING && mode != Asset::ACCESS_BUFFER) {

jniThrowException(env, "java/lang/IllegalArgumentException", "Bad access mode");

return -1;

}

 

    Asset* a = cookie

        ? am->openNonAsset((void*)cookie, fileName8.c_str(), (Asset::AccessMode)mode)

        : am->openNonAsset(fileName8.c_str(), (Asset::AccessMode)mode);

 

if (a == NULL) {

jniThrowException(env, "java/io/FileNotFoundException", fileName8.c_str());

return -1;

}

 

//printf("Created Asset Stream: %p\n", a);

 

return (jint)a;

}

 

Resources.java

Drawable loadDrawable(TypedValue value, int id)

            throws NotFoundException {

 

         if (TRACE_FOR_PRELOAD) {

                   // Log only framework resources

                   if ((id >>> 24) == 0x1) {//framework resources id 是以0x1 开头, mediatek Resource id 是一0x2 开头3方资源一般以0x7 开头

                            final String name = getResourceName(id);

                            if (name != null) android.util.Log.d("PreloadDrawable", name);

                   }

         }

 

         boolean isColorDrawable = false;

         if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&

                            value.type <= TypedValue.TYPE_LAST_COLOR_INT) {

                   isColorDrawable = true;

         }

         final long key = isColorDrawable ? value.data :

                            (((long) value.assetCookie) << 32) | value.data;

 

         Drawable dr = getCachedDrawable(isColorDrawable ? mColorDrawableCache : mDrawableCache, key);//从缓存中读取,如果缓存中已经存在,就直接获取并返回,缓存中没有的话就继续执行下面的代码去查询获取对应的资源文件.

 

         if (dr != null) {

                   return dr;

         }

         Drawable.ConstantState cs = null;

 

         /// M: Theme manager @{

         Boolean checkPreload = true;

         if (FeatureOption.MTK_THEMEMANAGER_APP) {

                   String skin= Configuration.getSkin();

                   if ((skin != null) &&

                            !(skin.equals(sDefaultSkin))){

                            checkPreload = false;

                   }

         }

         /// @}

 

//使用color配置的图片可以也直接从缓存中读取,提高效率.

         if (checkPreload) {/// M: Theme manager

                   if (isColorDrawable) {

                            cs = sPreloadedColorDrawables.get(key);

                   } else {

                            cs = sPreloadedDrawables[mConfiguration.getLayoutDirection()].get(key);

                   }

         }/// M: Theme manager

 

         if (cs != null) {

                   dr = cs.newDrawable(this);

         } else {

                   if (isColorDrawable) {

                            dr = new ColorDrawable(value.data);

                   }

 

                   if (dr == null) {

                            if (value.string == null) {

                                     throw new NotFoundException(

                                                        "Resource is not a Drawable (color or path): " + value);

                            }

 

                            String file = value.string.toString();

 

                            if (TRACE_FOR_MISS_PRELOAD) {

                                     // Log only framework resources

                                     if ((id >>> 24) == 0x1) {

                                               final String name = getResourceName(id);

                                               if (name != null) android.util.Log.d(TAG, "Loading framework drawable #"

                                                                 + Integer.toHexString(id) + ": " + name

                                                                 + " at " + file);

                                     }

                            }

 

                            if (DEBUG_LOAD) Log.v(TAG, "Loading drawable for cookie "

                                               + value.assetCookie + ": " + file);

 

                            if (file.endsWith(".xml")) {

                                     Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);

                                     try {

                                               XmlResourceParser rp = loadXmlResourceParser(

                                                                 file, id, value.assetCookie, "drawable");

                                               dr = Drawable.createFromXml(this, rp);

                                               rp.close();

                                     } catch (Exception e) {

                                               Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);

                                               NotFoundException rnf = new NotFoundException(

                                                        "File " + file + " from drawable resource ID #0x"

                                                        + Integer.toHexString(id));

                                               rnf.initCause(e);

                                               throw rnf;

                                     }

                                     Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);

 

                            } else {

                                     Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, file);

                                     try {

                                               InputStream is = mAssets.openNonAsset(

                                                                 value.assetCookie, file, AssetManager.ACCESS_STREAMING);

         //System.out.println("Opened file " + file + ": " + is);

                                               dr = Drawable.createFromResourceStream(this, value, is,

                                                                 file, null);

                                               is.close();

         //System.out.println("Created stream: " + dr);

                                     } catch (Exception e) {

                                               Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);

                                               NotFoundException rnf = new NotFoundException(

                                                        "File " + file + " from drawable resource ID #0x"

                                                        + Integer.toHexString(id));

                                               rnf.initCause(e);

                                               throw rnf;

                                     }

                                     Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);

                            }

                   }

         }

 

         if (dr != null) {

                   dr.setChangingConfigurations(value.changingConfigurations);

                   cs = dr.getConstantState();

                   if (cs != null) {

                            if (mPreloading) {

                                     final int changingConfigs = cs.getChangingConfigurations();

                                     if (isColorDrawable) {

                                               if (verifyPreloadConfig(changingConfigs, 0, value.resourceId,

                                                                 "drawable")) {

                                                        sPreloadedColorDrawables.put(key, cs);

                                               }

                                     } else {

                                               if (verifyPreloadConfig(changingConfigs,

                                                                 LAYOUT_DIR_CONFIG, value.resourceId, "drawable")) {

                                                        if ((changingConfigs&LAYOUT_DIR_CONFIG) == 0) {

                                                                  // If this resource does not vary based on layout direction,

                                                                 // we can put it in all of the preload maps.

                                                                 sPreloadedDrawables[0].put(key, cs);

                                                                 sPreloadedDrawables[1].put(key, cs);

                                                        } else {

                                                                 // Otherwise, only in the layout dir we loaded it for.

                                                                 final LongSparseArray<Drawable.ConstantState> preloads

                                                                                    = sPreloadedDrawables[mConfiguration.getLayoutDirection()];

                                                                 preloads.put(key, cs);

                                                        }

                                               }

                                     }

                            } else {

                                     synchronized (mAccessLock) {

                                               //Log.i(TAG, "Saving cached drawable @ #" +

                                               //        Integer.toHexString(key.intValue())

                                               //        + " in " + this + ": " + cs);

                                               if (isColorDrawable) {

                                                        mColorDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));

                                               } else {

                                                        mDrawableCache.put(key, new WeakReference<Drawable.ConstantState>(cs));

                                               }

                                     }

                            }

                   }

         }

 

         return dr;

}

 

 

如何替换第三方应用里面的资源

 

frameworks/base/libs/androidfw/AssetManager.cpp

  
  
  1. bool AssetManager::addAssetPath(constString8& path,void** cookie)
  2. {
  3. ......
  4. // add overlay packages for /system/framework; apps are handled by the
  5. // (Java) package manager
  6. if(strncmp(path.string(),"/system/framework/",18)==0){
  7. // When there is an environment variable for /vendor, this
  8. // should be changed to something similar to how ANDROID_ROOT
  9. // and ANDROID_DATA are used in this file.
  10. String8 overlayPath("/vendor/overlay/framework/");
  11. overlayPath.append(path.getPathLeaf());
  12. if(TEMP_FAILURE_RETRY(access(overlayPath.string(), R_OK))==0){
  13. asset_path oap;
  14. oap.path = overlayPath;
  15. oap.type =::getFileType(overlayPath.string());
  16. bool addOverlay =(oap.type == kFileTypeRegular);// only .apks supported as overlay
  17. if(addOverlay){
  18. oap.idmap = idmapPathForPackagePath(overlayPath);
  19. if(isIdmapStaleLocked(ap.path, oap.path, oap.idmap)){
  20. addOverlay = createIdmapFileLocked(ap.path, oap.path, oap.idmap);
  21. }
  22. }
  23. if(addOverlay){
  24. mAssetPaths.add(oap);
  25. }else{
  26. ALOGW("failed to add overlay package %s\n", overlayPath.string());
  27. }
  28. }
  29. }
  30. returntrue;
  31. }

 

比如将上面的代码改成

-if (strncmp(path.string(), "/system/framework/", 18) == 0) {

+if (strncmp(path.string(), "/system/app/", 12) == 0) {

// When there is an environment variable for /vendor, this

// should be changed to something similar to how ANDROID_ROOT

// and ANDROID_DATA are used in this file.

-String8 overlayPath("/vendor/overlay/framework/");

+String8 overlayPath("/system/vendor/thirds/");

overlayPath.append(path.getPathLeaf());

if (TEMP_FAILURE_RETRY(access(overlayPath.string(), R_OK)) == 0) {

然后再vendor目录下面放对应的文件

vendor/mediatek/eastaeon92_wet_tdd/artifacts/out/target/product/eastaeon92_wet_tdd/system/vendor/thirds/iReader.apk

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值