package com.v7lin.android.env; import java.io.InputStream; import java.util.concurrent.atomic.AtomicBoolean; import android.annotation.TargetApi; import android.content.Context; import android.content.res.AssetFileDescriptor; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.TextUtils; import android.util.TypedValue; /** * 同名同类型资源 优先级:皮肤插件资源 > 应用自带资源 * * 皮肤插件,不建议换布局,所以这里不重写 {@link Resources#getLayout(int)} 方法 * * @author v7lin E-mail:v7lin@qq.com */ public final class EnvSkinResourcesWrapper extends EnvSystemResourcesWrapper { private final Context mContext; private final String mPackageName; private final EnvResourcesManager mResourcesManager; private final AtomicBoolean mInitSkinRes = new AtomicBoolean(false); private String mSkinPath; private String mSkinPkg; private Resources mSkinRes; public EnvSkinResourcesWrapper(Context context, Resources res, EnvResourcesManager manager) { super(context, res, manager); mContext = context; mPackageName = context.getPackageName(); mResourcesManager = manager; } private synchronized void ensureSkinRes(Context context) { if (mInitSkinRes.compareAndSet(false, true) || mResourcesManager.isSkinChanged(context, mSkinPath)) { mSkinPath = mResourcesManager.getSkinPath(context); mSkinPkg = mResourcesManager.getSkinPkg(context); mSkinRes = mResourcesManager.getSkinRes(context); } } /** * 映射同名同类型资源 * * 皮肤插件包中并不包含所有资源,这导致 R 文件上的资源 id 无法一一对应。 所以这里需要做一次资源映射 */ private EnvRes mappingSkinRes(int resid) { EnvRes mapping = null; if (mSkinRes != null) { String packageName = getResourcePackageName(resid); if (TextUtils.equals(packageName, mPackageName)) { String typeName = getResourceTypeName(resid); String entryName = getResourceEntryName(resid); final int mappingid = mSkinRes.getIdentifier(entryName, typeName, mSkinPkg/*packageName*/); mapping = new EnvRes(mappingid); } } return mapping; } @Override public String getString(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.getString(mapping.getResid()); } catch (NotFoundException e) { } } return super.getString(id); } @Override public String getString(int id, Object... formatArgs) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.getString(mapping.getResid(), formatArgs); } catch (NotFoundException e) { } } return super.getString(id, formatArgs); } @Override public CharSequence getText(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.getText(mapping.getResid()); } catch (NotFoundException e) { } } return super.getText(id); } @Override public CharSequence getQuantityText(int id, int quantity) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.getQuantityText(mapping.getResid(), quantity); } catch (NotFoundException e) { } } return super.getQuantityText(id, quantity); } @Override public CharSequence getText(int id, CharSequence def) { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.getText(mapping.getResid()); } catch (NotFoundException e) { } } return super.getText(id, def); } @Override public CharSequence[] getTextArray(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.getTextArray(mapping.getResid()); } catch (NotFoundException e) { } } return super.getTextArray(id); } @Override public String[] getStringArray(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.getStringArray(mapping.getResid()); } catch (NotFoundException e) { } } return super.getStringArray(id); } @Override public int[] getIntArray(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.getIntArray(mapping.getResid()); } catch (NotFoundException e) { } } return super.getIntArray(id); } @Override public float getDimension(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSystemRes(id);// 系统资源->APP资源 if (mapping != null && mapping.isValid()) { EnvRes mappingSkinRes = mappingSkinRes(mapping.getResid());// APP资源->Skin资源 if (mappingSkinRes != null && mappingSkinRes.isValid()) { mapping = mappingSkinRes; } } else { mapping = mappingSkinRes(id); } if (mapping != null && mapping.isValid()) { try { if (mSkinRes != null) { try { return mSkinRes.getDimension(mapping.getResid()); } catch (NotFoundException e) { return super.getDimension(mapping.getResid()); } } else { return super.getDimension(mapping.getResid()); } } catch (NotFoundException e) { } } return super.getDimension(id); } @Override public int getDimensionPixelOffset(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSystemRes(id);// 系统资源->APP资源 if (mapping != null && mapping.isValid()) { EnvRes mappingSkinRes = mappingSkinRes(mapping.getResid());// APP资源->Skin资源 if (mappingSkinRes != null && mappingSkinRes.isValid()) { mapping = mappingSkinRes; } } else { mapping = mappingSkinRes(id); } if (mapping != null && mapping.isValid()) { try { if (mSkinRes != null) { try { return mSkinRes.getDimensionPixelOffset(mapping.getResid()); } catch (NotFoundException e) { return super.getDimensionPixelOffset(mapping.getResid()); } } else { return super.getDimensionPixelOffset(mapping.getResid()); } } catch (NotFoundException e) { } } return super.getDimensionPixelOffset(id); } @Override public int getDimensionPixelSize(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSystemRes(id);// 系统资源->APP资源 if (mapping != null && mapping.isValid()) { EnvRes mappingSkinRes = mappingSkinRes(mapping.getResid());// APP资源->Skin资源 if (mappingSkinRes != null && mappingSkinRes.isValid()) { mapping = mappingSkinRes; } } else { mapping = mappingSkinRes(id); } if (mapping != null && mapping.isValid()) { try { if (mSkinRes != null) { try { return mSkinRes.getDimensionPixelSize(mapping.getResid()); } catch (NotFoundException e) { return super.getDimensionPixelSize(mapping.getResid()); } } else { return super.getDimensionPixelSize(mapping.getResid()); } } catch (NotFoundException e) { } } return super.getDimensionPixelSize(id); } @Override public float getFraction(int id, int base, int pbase) { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.getFraction(mapping.getResid(), base, pbase); } catch (NotFoundException e) { } } return super.getFraction(id, base, pbase); } @Override public Drawable getDrawable(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSystemRes(id);// 系统资源->APP资源 if (mapping != null && mapping.isValid()) { EnvRes mappingSkinRes = mappingSkinRes(mapping.getResid());// APP资源->Skin资源 if (mappingSkinRes != null && mappingSkinRes.isValid()) { mapping = mappingSkinRes; } } else { mapping = mappingSkinRes(id); } if (mapping != null && mapping.isValid()) { try { if (mSkinRes != null) { try { return mSkinRes.getDrawable(mapping.getResid()); } catch (NotFoundException e) { return super.getDrawable(mapping.getResid()); } } else { return super.getDrawable(mapping.getResid()); } } catch (NotFoundException e) { } } return super.getDrawable(id); } @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) @Override public Drawable getDrawableForDensity(int id, int density) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSystemRes(id);// 系统资源->APP资源 if (mapping != null && mapping.isValid()) { EnvRes mappingSkinRes = mappingSkinRes(mapping.getResid());// APP资源->Skin资源 if (mappingSkinRes != null && mappingSkinRes.isValid()) { mapping = mappingSkinRes; } } else { mapping = mappingSkinRes(id); } if (mapping != null && mapping.isValid()) { try { if (mSkinRes != null) { try { return mSkinRes.getDrawableForDensity(mapping.getResid(), density); } catch (Exception e) { return super.getDrawableForDensity(mapping.getResid(), density); } } else { return super.getDrawableForDensity(mapping.getResid(), density); } } catch (NotFoundException e) { } } return super.getDrawableForDensity(id, density); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public Drawable getDrawable(int id, Theme theme) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSystemRes(id);// 系统资源->APP资源 if (mapping != null && mapping.isValid()) { EnvRes mappingSkinRes = mappingSkinRes(mapping.getResid());// APP资源->Skin资源 if (mappingSkinRes != null && mappingSkinRes.isValid()) { mapping = mappingSkinRes; } } else { mapping = mappingSkinRes(id); } if (mapping != null && mapping.isValid()) { try { if (mSkinRes != null) { try { return mSkinRes.getDrawable(mapping.getResid(), theme); } catch (NotFoundException e) { return super.getDrawable(mapping.getResid(), theme); } } else { return super.getDrawable(mapping.getResid(), theme); } } catch (NotFoundException e) { } } return super.getDrawable(id, theme); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public Drawable getDrawableForDensity(int id, int density, Theme theme) { ensureSkinRes(mContext); EnvRes mapping = mappingSystemRes(id);// 系统资源->APP资源 if (mapping != null && mapping.isValid()) { EnvRes mappingSkinRes = mappingSkinRes(mapping.getResid());// APP资源->Skin资源 if (mappingSkinRes != null && mappingSkinRes.isValid()) { mapping = mappingSkinRes; } } else { mapping = mappingSkinRes(id); } if (mapping != null && mapping.isValid()) { try { if (mSkinRes != null) { try { return mSkinRes.getDrawableForDensity(mapping.getResid(), density, theme); } catch (Exception e) { return super.getDrawableForDensity(mapping.getResid(), density, theme); } } else { return super.getDrawableForDensity(mapping.getResid(), density, theme); } } catch (NotFoundException e) { } } return super.getDrawableForDensity(id, density, theme); } @Override public int getColor(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSystemRes(id);// 系统资源->APP资源 if (mapping != null && mapping.isValid()) { EnvRes mappingSkinRes = mappingSkinRes(mapping.getResid());// APP资源->Skin资源 if (mappingSkinRes != null && mappingSkinRes.isValid()) { mapping = mappingSkinRes; } } else { mapping = mappingSkinRes(id); } if (mapping != null && mapping.isValid()) { try { if (mSkinRes != null) { try { return mSkinRes.getColor(mapping.getResid()); } catch (NotFoundException e) { return super.getColor(mapping.getResid()); } } else { return super.getColor(mapping.getResid()); } } catch (NotFoundException e) { } } return super.getColor(id); } @Override public ColorStateList getColorStateList(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSystemRes(id);// 系统资源->APP资源 if (mapping != null && mapping.isValid()) { EnvRes mappingSkinRes = mappingSkinRes(mapping.getResid());// APP资源->Skin资源 if (mappingSkinRes != null && mappingSkinRes.isValid()) { mapping = mappingSkinRes; } } else { mapping = mappingSkinRes(id); } if (mapping != null && mapping.isValid()) { try { if (mSkinRes != null) { try { return mSkinRes.getColorStateList(mapping.getResid()); } catch (NotFoundException e) { return super.getColorStateList(mapping.getResid()); } } else { return super.getColorStateList(mapping.getResid()); } } catch (NotFoundException e) { } } return super.getColorStateList(id); } @TargetApi(Build.VERSION_CODES.M) @Override public int getColor(int id, Theme theme) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSystemRes(id);// 系统资源->APP资源 if (mapping != null && mapping.isValid()) { EnvRes mappingSkinRes = mappingSkinRes(mapping.getResid());// APP资源->Skin资源 if (mappingSkinRes != null && mappingSkinRes.isValid()) { mapping = mappingSkinRes; } } else { mapping = mappingSkinRes(id); } if (mapping != null && mapping.isValid()) { try { if (mSkinRes != null) { try { return mSkinRes.getColor(mapping.getResid(), theme); } catch (NotFoundException e) { return super.getColor(mapping.getResid(), theme); } } else { return super.getColor(mapping.getResid(), theme); } } catch (NotFoundException e) { } } return super.getColor(id, theme); } @TargetApi(Build.VERSION_CODES.M) @Override public ColorStateList getColorStateList(int id, Theme theme) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSystemRes(id);// 系统资源->APP资源 if (mapping != null && mapping.isValid()) { EnvRes mappingSkinRes = mappingSkinRes(mapping.getResid());// APP资源->Skin资源 if (mappingSkinRes != null && mappingSkinRes.isValid()) { mapping = mappingSkinRes; } } else { mapping = mappingSkinRes(id); } if (mapping != null && mapping.isValid()) { try { if (mSkinRes != null) { try { return mSkinRes.getColorStateList(mapping.getResid(), theme); } catch (NotFoundException e) { return super.getColorStateList(mapping.getResid(), theme); } } else { return super.getColorStateList(mapping.getResid(), theme); } } catch (NotFoundException e) { } } return super.getColorStateList(id, theme); } @Override public boolean getBoolean(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.getBoolean(mapping.getResid()); } catch (NotFoundException e) { } } return super.getBoolean(id); } @Override public int getInteger(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.getInteger(mapping.getResid()); } catch (NotFoundException e) { } } return super.getInteger(id); } @Override public XmlResourceParser getAnimation(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.getAnimation(mapping.getResid()); } catch (NotFoundException e) { } } return super.getAnimation(id); } @Override public XmlResourceParser getXml(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.getXml(mapping.getResid()); } catch (NotFoundException e) { } } return super.getXml(id); } @Override public TypedArray obtainTypedArray(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.obtainTypedArray(mapping.getResid()); } catch (NotFoundException e) { } } return super.obtainTypedArray(id); } @Override public InputStream openRawResource(int id, TypedValue value) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.openRawResource(mapping.getResid(), value); } catch (NotFoundException e) { } } return super.openRawResource(id, value); } @Override public AssetFileDescriptor openRawResourceFd(int id) throws NotFoundException { ensureSkinRes(mContext); EnvRes mapping = mappingSkinRes(id); if (mapping != null && mapping.isValid() && mSkinRes != null) { try { return mSkinRes.openRawResourceFd(mapping.getResid()); } catch (NotFoundException e) { } } return super.openRawResourceFd(id); } }