package ren.solid.skinloader.load; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.AssetManager; import android.content.res.ColorStateList; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.util.Log; import java.io.File; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import ren.solid.skinloader.util.L; import ren.solid.skinloader.config.SkinConfig; import ren.solid.skinloader.listener.ILoaderListener; import ren.solid.skinloader.listener.ISkinLoader; import ren.solid.skinloader.listener.ISkinUpdate; /** * Created by _SOLID * Date:2016/4/13 * Time:21:07 */ public class SkinManager implements ISkinLoader { private List<ISkinUpdate> mSkinObservers; private static volatile SkinManager mInstance; private Context context; private Resources mResources; private boolean isDefaultSkin = false;//当前的皮肤是否是默认的 private String skinPackageName;//皮肤的包名 private String skinPath;//皮肤路径 private SkinManager() { } public void init(Context ctx) { context = ctx.getApplicationContext(); } public int getColorPrimaryDark() { if (mResources != null) { int identify = mResources.getIdentifier("colorPrimaryDark", "color", skinPackageName); return mResources.getColor(identify); } return -1; } /** * 判断当前使用的皮肤是否来自外部 * * @return */ public boolean isExternalSkin() { return !isDefaultSkin && mResources != null; } /** * 得到当前的皮肤路径 * * @return */ public String getSkinPath() { return skinPath; } /** * 得到当前皮肤的包名 * * @return */ public String getSkinPackageName() { return skinPackageName; } public Resources getResources() { return mResources; } /** * 恢复到默认主题 */ public void restoreDefaultTheme() { SkinConfig.saveSkinPath(context, SkinConfig.DEFALT_SKIN); isDefaultSkin = true; mResources = context.getResources(); skinPackageName = context.getPackageName(); notifySkinUpdate(); } public static SkinManager getInstance() { if (mInstance == null) { synchronized (SkinManager.class) { if (mInstance == null) { mInstance = new SkinManager(); } } } return mInstance; } @Override public void attach(ISkinUpdate observer) { if (mSkinObservers == null) { mSkinObservers = new ArrayList<>(); } if (!mSkinObservers.contains(mSkinObservers)) { mSkinObservers.add(observer); } } @Override public void detach(ISkinUpdate observer) { if (mSkinObservers == null) return; if (mSkinObservers.contains(observer)) { mSkinObservers.remove(observer); } } @Override public void notifySkinUpdate() { if (mSkinObservers == null) return; for (ISkinUpdate observer : mSkinObservers) { observer.onThemeUpdate(); } } public void load() { String skin = SkinConfig.getCustomSkinPath(context); load(skin, null); } public void load(ILoaderListener callback) { String skin = SkinConfig.getCustomSkinPath(context); if (SkinConfig.isDefaultSkin(context)) { return; } load(skin, callback); } public void load(String skinPackagePath, final ILoaderListener callback) { new AsyncTask<String, Void, Resources>() { protected void onPreExecute() { if (callback != null) { callback.onStart(); } } @Override protected Resources doInBackground(String... params) { try { if (params.length == 1) { String skinPkgPath = params[0]; Log.i("loadSkin", skinPkgPath); File file = new File(skinPkgPath); if (file == null || !file.exists()) { return null; } PackageManager mPm = context.getPackageManager(); PackageInfo mInfo = mPm.getPackageArchiveInfo(skinPkgPath, PackageManager.GET_ACTIVITIES); skinPackageName = mInfo.packageName; AssetManager assetManager = AssetManager.class.newInstance(); Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class); addAssetPath.invoke(assetManager, skinPkgPath); Resources superRes = context.getResources(); Resources skinResource = new Resources(assetManager, superRes.getDisplayMetrics(), superRes.getConfiguration()); SkinConfig.saveSkinPath(context, skinPkgPath); skinPath = skinPkgPath; isDefaultSkin = false; return skinResource; } return null; } catch (Exception e) { e.printStackTrace(); return null; } } protected void onPostExecute(Resources result) { mResources = result; if (mResources != null) { if (callback != null) callback.onSuccess(); notifySkinUpdate(); } else { isDefaultSkin = true; if (callback != null) callback.onFailed(); } } }.execute(skinPackagePath); } public int getColor(int resId) { int originColor = context.getResources().getColor(resId); if (mResources == null || isDefaultSkin) { return originColor; } String resName = context.getResources().getResourceEntryName(resId); int trueResId = mResources.getIdentifier(resName, "color", skinPackageName); int trueColor = 0; try { trueColor = mResources.getColor(trueResId); } catch (Resources.NotFoundException e) { e.printStackTrace(); trueColor = originColor; } return trueColor; } public Drawable getDrawable(int resId) { Drawable originDrawable = context.getResources().getDrawable(resId); if (mResources == null || isDefaultSkin) { return originDrawable; } String resName = context.getResources().getResourceEntryName(resId); int trueResId = mResources.getIdentifier(resName, "drawable", skinPackageName); Drawable trueDrawable = null; try { L.i("SkinManager getDrawable", "SDK_INT = " + android.os.Build.VERSION.SDK_INT); if (android.os.Build.VERSION.SDK_INT < 22) { trueDrawable = mResources.getDrawable(trueResId); } else { trueDrawable = mResources.getDrawable(trueResId, null); } } catch (Resources.NotFoundException e) { e.printStackTrace(); trueDrawable = originDrawable; } return trueDrawable; } /** * 加载指定资源颜色drawable,转化为ColorStateList,保证selector类型的Color也能被转换。</br> * 无皮肤包资源返回默认主题颜色 * * @param resId * @return * @author pinotao */ public ColorStateList convertToColorStateList(int resId) { boolean isExtendSkin = true; if (mResources == null || isDefaultSkin) { isExtendSkin = false; } String resName = context.getResources().getResourceEntryName(resId); if (isExtendSkin) { int trueResId = mResources.getIdentifier(resName, "color", skinPackageName); ColorStateList trueColorList = null; if (trueResId == 0) { // 如果皮肤包没有复写该资源,但是需要判断是否是ColorStateList try { ColorStateList originColorList = context.getResources().getColorStateList(resId); return originColorList; } catch (Resources.NotFoundException e) { e.printStackTrace(); L.e("resName = " + resName + " NotFoundException : " + e.getMessage()); } } else { try { trueColorList = mResources.getColorStateList(trueResId); return trueColorList; } catch (Resources.NotFoundException e) { e.printStackTrace(); L.e("resName = " + resName + " NotFoundException :" + e.getMessage()); } } } else { try { ColorStateList originColorList = context.getResources().getColorStateList(resId); return originColorList; } catch (Resources.NotFoundException e) { e.printStackTrace(); L.e("resName = " + resName + " NotFoundException :" + e.getMessage()); } } int[][] states = new int[1][1]; return new ColorStateList(states, new int[]{context.getResources().getColor(resId)}); } }