package skin.support;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.os.AsyncTask;
import android.text.TextUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import skin.support.app.SkinLayoutInflater;
import skin.support.observe.SkinObservable;
import skin.support.utils.SkinConstants;
import skin.support.utils.SkinFileUtils;
import skin.support.utils.SkinLog;
import skin.support.utils.SkinPreference;
import skin.support.content.res.SkinCompatResources;
/**
* Created by ximsfei on 17-1-10.
*/
public class SkinCompatManager extends SkinObservable {
private static volatile SkinCompatManager sInstance;
private final Context mAppContext;
private List<SkinLayoutInflater> mInflaters = new ArrayList<>();
public interface SkinLoaderListener {
void onStart();
void onSuccess();
void onFailed(String errMsg);
}
public static SkinCompatManager init(Context context) {
if (sInstance == null) {
synchronized (SkinCompatManager.class) {
if (sInstance == null) {
sInstance = new SkinCompatManager(context);
}
}
}
return sInstance;
}
public static SkinCompatManager getInstance() {
return sInstance;
}
private SkinCompatManager(Context context) {
mAppContext = context.getApplicationContext();
SkinPreference.init(mAppContext);
SkinCompatResources.init(mAppContext);
}
public void addInflater(SkinLayoutInflater inflater) {
mInflaters.add(inflater);
}
public List<SkinLayoutInflater> getInflaters() {
return mInflaters;
}
public String getCurSkinName() {
return SkinPreference.getInstance().getSkinName();
}
public void restoreDefaultTheme() {
SkinPreference.getInstance().setSkinName("").commitEditor();
SkinCompatResources.getInstance().setSkinResource(mAppContext.getResources(), mAppContext.getPackageName());
notifyUpdateSkin();
}
public void loadSkin() {
String skin = SkinPreference.getInstance().getSkinName();
if (TextUtils.isEmpty(skin)) {
return;
}
loadSkin(skin, null);
}
public void loadSkin(String skinName) {
loadSkin(skinName, null);
}
public void loadSkin(SkinLoaderListener listener) {
String skin = SkinPreference.getInstance().getSkinName();
if (TextUtils.isEmpty(skin)) {
return;
}
loadSkin(skin, listener);
}
public void loadSkin(String skinName, final SkinLoaderListener listener) {
if (TextUtils.isEmpty(skinName)) {
restoreDefaultTheme();
return;
}
new SkinLoadTask(listener).execute(skinName);
}
private class SkinLoadTask extends AsyncTask<String, Void, Boolean> {
private final SkinLoaderListener mListener;
public SkinLoadTask(SkinLoaderListener listener) {
mListener = listener;
}
protected void onPreExecute() {
if (mListener != null) {
mListener.onStart();
}
}
@Override
protected Boolean doInBackground(String... params) {
try {
if (params.length == 1) {
SkinLog.d("skinPkgPath", params[0]);
String skinPkgPath = SkinFileUtils.getSkinDir(mAppContext) + File.separator + params[0];
// ToDo 方便调试, 每次点击都从assets中读取
// if (!isSkinExists(params[0])) {
copySkinFromAssets(params[0]);
if (!isSkinExists(params[0])) {
return false;
}
// }
PackageManager mPm = mAppContext.getPackageManager();
PackageInfo mInfo = mPm.getPackageArchiveInfo(skinPkgPath, PackageManager.GET_ACTIVITIES);
String pkgName = mInfo.packageName;
AssetManager assetManager = AssetManager.class.newInstance();
Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
addAssetPath.invoke(assetManager, skinPkgPath);
Resources superRes = mAppContext.getResources();
Resources resources = null;
try {
resources = new Resources(assetManager, superRes.getDisplayMetrics(), superRes.getConfiguration());
} catch (Exception e) {
e.printStackTrace();
}
SkinPreference.getInstance().setSkinName(params[0]).commitEditor();
if (resources != null) {
SkinCompatResources.getInstance().setSkinResource(resources, pkgName);
return true;
}
SkinCompatResources.getInstance().setSkinResource(
mAppContext.getResources(), mAppContext.getPackageName());
return false;
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
protected void onPostExecute(Boolean result) {
SkinLog.e("result = " + result);
if (result != null && result) {
if (mListener != null) mListener.onSuccess();
notifyUpdateSkin();
} else {
if (mListener != null) mListener.onFailed("皮肤资源获取失败");
}
}
}
private String copySkinFromAssets(String name) {
String skinDir = SkinFileUtils.getSkinDir(mAppContext);
String skinPath = skinDir + File.separator + name;
try {
InputStream is = mAppContext.getAssets().open(
SkinConstants.SKIN_DEPLOY_PATH
+ File.separator
+ name);
File fileDir = new File(skinDir);
if (!fileDir.exists()) {
fileDir.mkdirs();
}
OutputStream os = new FileOutputStream(skinPath);
int byteCount;
byte[] bytes = new byte[1024];
while ((byteCount = is.read(bytes)) != -1) {
os.write(bytes, 0, byteCount);
}
os.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
}
return skinPath;
}
public boolean isSkinExists(String skinName) {
return !TextUtils.isEmpty(skinName)
&& new File(SkinFileUtils.getSkinDir(mAppContext) + File.separator + skinName).exists();
}
}