package com.tws.plugin.core; import java.lang.reflect.Field; import java.util.HashSet; import tws.component.log.TwsLog; import android.content.res.AssetManager; import android.content.res.ColorStateList; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.Resources.NotFoundException; import android.content.res.Resources.Theme; import android.graphics.drawable.Drawable; import android.text.TextUtils; import android.util.DisplayMetrics; import com.tws.plugin.content.PluginDescriptor; import com.tws.plugin.util.ResourceUtil; /** * 根据不同的rom,可能需要重写更多的方法,目前发现的几个机型的问题暂时只需要重写下面2个方法。 * * @author yongchen * */ public class PluginResourceWrapper extends Resources { private static final String TAG = "rick_Print:PluginResourceWrapper"; private HashSet<Integer> idCaches = new HashSet<Integer>(5); private PluginDescriptor mPluginDescriptor; public PluginResourceWrapper(AssetManager assets, DisplayMetrics metrics, Configuration config, PluginDescriptor pluginDescriptor) { super(assets, metrics, config); this.mPluginDescriptor = pluginDescriptor; } @Override public String getResourcePackageName(int resid) throws NotFoundException { if (idCaches.contains(resid)) { return PluginLoader.getApplication().getPackageName(); } try { return super.getResourcePackageName(resid); } catch (NotFoundException e) { TwsLog.e(TAG, "NotFoundException Try Following resid=" + Integer.toHexString(resid)); // 就目前测试的情况来看,只有Coolpad、vivo、oppo等手机会在上面抛异常,走到这里来, // 华为、三星、小米等手机不会到这里来。 if (ResourceUtil.isMainResId(resid)) { idCaches.add(resid); return PluginLoader.getApplication().getPackageName(); } TwsLog.e(TAG, "NotFoundException Try Following resid=" + Integer.toHexString(resid), e); throw new NotFoundException("Unable to find resource ID #0x" + Integer.toHexString(resid)); } } @Override public String getResourceName(int resid) throws NotFoundException { try { return super.getResourceName(resid); } catch (NotFoundException e) { TwsLog.e(TAG, "NotFoundException Try Following"); // 就目前测试的情况来看,只有Coolpad、vivo、oppo等手机会在上面抛异常,走到这里来, // 华为、三星、小米等手机不会到这里来。 if (ResourceUtil.isMainResId(resid)) { return PluginLoader.getApplication().getResources().getResourceName(resid); } throw new NotFoundException("Unable to find resource ID #0x" + Integer.toHexString(resid)); } } @Override public String getResourceEntryName(int resid) { try { return super.getResourceEntryName(resid); } catch (NotFoundException e) { // vivo if (ResourceUtil.isMainResId(resid)) { return PluginLoader.getApplication().getResources().getResourceEntryName(resid); } TwsLog.e(TAG, "NotFoundException Try Following"); throw new NotFoundException("Unable to find resource ID #0x" + Integer.toHexString(resid)); } } @Override public String getResourceTypeName(int resid) { try { return super.getResourceTypeName(resid); } catch (NotFoundException e) { // vivo if (ResourceUtil.isMainResId(resid)) { return PluginLoader.getApplication().getResources().getResourceTypeName(resid); } TwsLog.e(TAG, "NotFoundException Try Following"); throw new NotFoundException("Unable to find resource ID #0x" + Integer.toHexString(resid)); } } /** * 重写这个方法主要是为了解决非独立插件可以反查宿主资源id的问题 */ @Override public int getIdentifier(String name, String defType, String defPackage) { if (TextUtils.isDigitsOnly(name)) { return super.getIdentifier(name, defType, defPackage); } // 传了packageName,而且不是宿主的packageName, 则直接返回 if (!TextUtils.isEmpty(defPackage) && !PluginLoader.getApplication().getPackageName().equals(defPackage)) { return super.getIdentifier(name, defType, defPackage); } // package:type/entry // 第一段 “package:“ 第二段 ”type/“ 第三段 “entry” String packageName = null; String type = null; String entry = null; String[] pte = name.split(":"); String[] te; if (pte.length == 2) { packageName = pte[0]; te = pte[1].split("/"); } else { te = pte[0].split("/"); } if (te.length == 2) { type = te[0]; entry = te[1]; } else { entry = te[0]; } if (packageName == null) { packageName = defPackage; } if (type == null) { type = defType; } // 传了宿主的packageName if (PluginLoader.getApplication().getPackageName().equals(packageName)) { if (mPluginDescriptor.isStandalone()) { // 如果是独立插件, 取不到宿主资源, 这里强制切换到插件 packageName = mPluginDescriptor.getPackageName(); } else { // 判断是否在真的在宿主中 Class rClass = null; try { String className = packageName + ".R$" + type; rClass = this.getClass().getClassLoader().loadClass(className); Field field = rClass.getDeclaredField(entry); if (field == null) { // 不在宿主中,切换到插件 packageName = mPluginDescriptor.getPackageName(); } else { // 在宿主中, 通过宿主的Context获取 return PluginLoader.getApplication().getResources().getIdentifier(entry, type, packageName); } } catch (Exception e) { // 不在宿主中,切换到插件 packageName = mPluginDescriptor.getPackageName(); } } } return super.getIdentifier(entry, type, packageName); } @Override @Deprecated public Drawable getDrawable(int id) throws NotFoundException { try { return super.getDrawable(id); } catch (Exception e) { TwsLog.e(TAG, "NotFoundException Try Following"); // 7.1 Nexus 6p会跑到这里来 if (ResourceUtil.isMainResId(id)) { return PluginLoader.getApplication().getResources().getDrawable(id); } throw new NotFoundException("Unable to find Drawable resource ID #0x" + Integer.toHexString(id)); } } @Override public Drawable getDrawable(int id, Theme theme) throws NotFoundException { try { return super.getDrawable(id, theme); } catch (Exception e) { TwsLog.e(TAG, "NotFoundException Try Following"); // 7.1 Nexus 6p会跑到这里来 if (ResourceUtil.isMainResId(id)) { return PluginLoader.getApplication().getResources().getDrawable(id, theme); } throw new NotFoundException("Unable to find Drawable resource ID #0x" + Integer.toHexString(id)); } } @Override public int getColor(int id) throws NotFoundException { try { return super.getColor(id); } catch (Exception e) { TwsLog.e(TAG, "NotFoundException Try Following"); // 7.1 Nexus 6p会跑到这里来 if (ResourceUtil.isMainResId(id)) { return PluginLoader.getApplication().getResources().getColor(id); } throw new NotFoundException("Unable to find Color resource ID #0x" + Integer.toHexString(id)); } } @Override public ColorStateList getColorStateList(int id) throws NotFoundException { try { return super.getColorStateList(id); } catch (Exception e) { TwsLog.e(TAG, "NotFoundException Try Following"); // 7.1 Nexus 6p会跑到这里来 if (ResourceUtil.isMainResId(id)) { return PluginLoader.getApplication().getResources().getColorStateList(id); } throw new NotFoundException("Unable to find Color resource ID #0x" + Integer.toHexString(id)); } } }