android加載第三方圖標機制分析

分類:編程 時間:2017-02-15

android加載第三方圖標機制分析

 

系統如何獲取圖片等資源

當我們調用Resources.Java 來獲取圖片等資源的時候會調用getDrawable 方法, getDrawable最終把這還是使用loadDrawable 方法來處理.

Resources.java

public Drawable getDrawable(int id) throws NotFoundException {

TypedValue value;

synchronized (mAccessLock) {

            value = http://www.ithao123.cn/mTmpValue;

            if (value =http://www.ithao123.cn/= null) {

                value = http://www.ithao123.cn/new TypedValue();

            } else {

                mTmpValue = http://www.ithao123.cn/null;

            }

            getValue(id, value, true);

}

 Drawable res = loadDrawable(value, id);

synchronized (mAccessLock) {

            if (mTmpValue =http://www.ithao123.cn/= null) {

                mTmpValue = http://www.ithao123.cn/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


Tags: android 第三方 return color null

文章來源:


ads
ads

相關文章
ads

相關文章

ad