「Skin」
1、修复皮肤包MD5不一致导致换肤加载失败的情况
This commit is contained in:
@@ -85,18 +85,18 @@ public class MainActivity extends AppCompatActivity {
|
|||||||
btnChangeSkin.setOnCheckedChangeListener((view, isCheck) -> {
|
btnChangeSkin.setOnCheckedChangeListener((view, isCheck) -> {
|
||||||
Skin skin;
|
Skin skin;
|
||||||
if (isCheck) {
|
if (isCheck) {
|
||||||
skin = new Skin(
|
|
||||||
"ee3e1b0ed6e33a51366949294b07787d",
|
|
||||||
"YiXin-skin_v1_2024_10_25.zip",
|
|
||||||
"https://carlife-static-1255510688.cos.ap-beijing.myqcloud.com/MoGoEagleEye/YiXin-skin_v1_2024_10_25.zip"
|
|
||||||
);
|
|
||||||
|
|
||||||
// skin = new Skin(
|
// skin = new Skin(
|
||||||
// "a841e8819f06cfefa646f7adc697e070",
|
// "ee3e1b0ed6e33a51366949294b07787d",
|
||||||
// "DeQing-skin_v1_2024_10_25.apk",
|
// "YiXin-skin_v1_2024_10_25.zip",
|
||||||
// "https://carlife-static-1255510688.cos.ap-beijing.myqcloud.com/MoGoEagleEye/DeQing-skin_v1_2024_10_25.apk"
|
// "https://carlife-static-1255510688.cos.ap-beijing.myqcloud.com/MoGoEagleEye/YiXin-skin_v1_2024_10_25.zip"
|
||||||
// );
|
// );
|
||||||
|
|
||||||
|
skin = new Skin(
|
||||||
|
"465a214dcbc65bdfbe860bdbcde95879",
|
||||||
|
"DeQing-skin_v1_2024_10_28.apk",
|
||||||
|
"https://carlife-static-1255510688.cos.ap-beijing.myqcloud.com/MoGoEagleEye/DeQing-skin_v1_2024_10_28.zip"
|
||||||
|
);
|
||||||
|
|
||||||
//换肤
|
//换肤
|
||||||
SkinManager.getInstance().downloadSkin(this, skin, new SkinManager.SkinLoadListener() {
|
SkinManager.getInstance().downloadSkin(this, skin, new SkinManager.SkinLoadListener() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ MOGO_TELEMATIC_VERSION=1.4.7.42
|
|||||||
# v2x
|
# v2x
|
||||||
MOGO_V2X_VERSION=1.4.7.42
|
MOGO_V2X_VERSION=1.4.7.42
|
||||||
# SKIN
|
# SKIN
|
||||||
MOGO_SKIN_VERSION=1.4.7.49.19-debug
|
MOGO_SKIN_VERSION=1.4.7.49.19
|
||||||
# SDK
|
# SDK
|
||||||
SDK_VERSION=1.4.7.49.18-debug
|
SDK_VERSION=1.4.7.49.18-debug
|
||||||
SDK_NATIVE_VERSION=1.4.7.49.18-debug
|
SDK_NATIVE_VERSION=1.4.7.49.18-debug
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
package com.mogo.skin;
|
package com.mogo.skin;
|
||||||
|
|
||||||
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import com.mogo.skin.utils.SkinUtils;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ public class SkinManager extends Observable {
|
|||||||
Log.d(TAG, "加载皮肤路径:" + skinPath);
|
Log.d(TAG, "加载皮肤路径:" + skinPath);
|
||||||
|
|
||||||
if (TextUtils.isEmpty(skinPath)) {
|
if (TextUtils.isEmpty(skinPath)) {
|
||||||
Log.d(TAG, "还原默认皮肤包,开始换肤……");
|
Log.d(TAG, "皮肤包路径为空,还原默认皮肤包,开始还原换肤。");
|
||||||
//还原默认皮肤包
|
//还原默认皮肤包
|
||||||
SkinPreference.getInstance().setSkin("");
|
SkinPreference.getInstance().setSkin("");
|
||||||
SkinResources.getInstance().reset();
|
SkinResources.getInstance().reset();
|
||||||
@@ -97,7 +97,7 @@ public class SkinManager extends Observable {
|
|||||||
else {
|
else {
|
||||||
// 判断是否已经加载同样皮肤,如果已经加载则不再重复加载,防止因为重复加载导致ImageView之类的设置了src、background的控件被重制
|
// 判断是否已经加载同样皮肤,如果已经加载则不再重复加载,防止因为重复加载导致ImageView之类的设置了src、background的控件被重制
|
||||||
try {
|
try {
|
||||||
Log.d(TAG, "切换的皮肤与之前不一样,开始换肤……");
|
Log.d(TAG, "皮肤路径非空,开始换肤。");
|
||||||
//反射创建AssetManager 与 Resource
|
//反射创建AssetManager 与 Resource
|
||||||
AssetManager assetManager = AssetManager.class.newInstance();
|
AssetManager assetManager = AssetManager.class.newInstance();
|
||||||
// 资源路径设置 目录或压缩包
|
// 资源路径设置 目录或压缩包
|
||||||
@@ -151,11 +151,18 @@ public class SkinManager extends Observable {
|
|||||||
File skinFile = skin.getSkinFile(theme);
|
File skinFile = skin.getSkinFile(theme);
|
||||||
// 判断是否存在
|
// 判断是否存在
|
||||||
if (skinFile.exists()) {
|
if (skinFile.exists()) {
|
||||||
Log.d(TAG, "皮肤已存在,开始换肤……skin=" + skin);
|
// 检验皮肤包完整性,即MD5是否一致,不一致则删除
|
||||||
SkinManager.getInstance().loadSkin(skin.getPathLocal());
|
String localSkinFileMd5 = SkinUtils.getSkinMD5(skinFile);
|
||||||
return;
|
if (!TextUtils.equals(localSkinFileMd5, skin.md5)) {
|
||||||
|
Log.w(TAG, "皮肤包 皮肤文件 MD5校验出错, 本地文件 MD5 = " + localSkinFileMd5 + " 与云端文件 MD5 = " + skin.md5 + " 不一致。删除本地皮肤包,重新下载。");
|
||||||
|
skinFile.delete();
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "皮肤包 皮肤文件 MD5校验成功, 本地文件 MD5 =" + localSkinFileMd5 + " 与云端文件 MD5 = " + skin.md5 + " 开始换肤……skin=" + skin);
|
||||||
|
SkinManager.getInstance().loadSkin(skin.getPathLocal());
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Log.e(TAG, "皮肤不存在,开始下载……skin=" + skin);
|
Log.w(TAG, "皮肤不存在,开始下载……skin=" + skin);
|
||||||
DownloadManager manager = getDownloadManager(skin, theme, skinLoadListener);
|
DownloadManager manager = getDownloadManager(skin, theme, skinLoadListener);
|
||||||
// 启动文件下载
|
// 启动文件下载
|
||||||
manager.startDownload();
|
manager.startDownload();
|
||||||
@@ -167,34 +174,35 @@ public class SkinManager extends Observable {
|
|||||||
@Override
|
@Override
|
||||||
public void onProgressUpdate(int progress) {
|
public void onProgressUpdate(int progress) {
|
||||||
// 更新UI或日志
|
// 更新UI或日志
|
||||||
Log.d(TAG, "DownloadManager onProgressUpdate progress = " + progress);
|
Log.d(TAG, "皮肤包下载进度 onProgressUpdate progress = " + progress);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDownloadSuccess() {
|
public void onDownloadSuccess() {
|
||||||
// 下载成功后的处理
|
// 下载成功后的处理
|
||||||
Log.d(TAG, "DownloadManager onDownloadSuccess");
|
Log.d(TAG, "皮肤包 下载成功 onDownloadSuccess");
|
||||||
File skinFile = skin.getSkinFile(themeDirectory);
|
File skinFile = skin.getSkinFile(themeDirectory);
|
||||||
try {
|
try {
|
||||||
//下载成功,将皮肤包信息insert已下载数据库
|
//下载成功,将皮肤包信息insert已下载数据库
|
||||||
Log.e(TAG, "DownloadManager 皮肤包下载完成开始校验");
|
Log.d(TAG, "皮肤包下载完成开始校验……");
|
||||||
//皮肤包的md5校验 防止下载文件损坏(但是会减慢速度。从数据库查询已下载皮肤表数据库中保留md5字段)
|
//皮肤包的md5校验 防止下载文件损坏(但是会减慢速度。从数据库查询已下载皮肤表数据库中保留md5字段)
|
||||||
String localSkinFileMd5 = SkinUtils.getSkinMD5(skinFile);
|
String localSkinFileMd5 = SkinUtils.getSkinMD5(skinFile);
|
||||||
if (TextUtils.equals(localSkinFileMd5, skin.md5)) {
|
if (TextUtils.equals(localSkinFileMd5, skin.md5)) {
|
||||||
Log.d(TAG, "DownloadManager 校验成功,修改文件名。");
|
Log.d(TAG, "皮肤包 MD5 校验成功,本地文件 MD5 = " + localSkinFileMd5 + " 与云端文件 MD5 = " + skin.md5 + " 删除其它皮肤包。");
|
||||||
// 加载指定皮肤包
|
// 加载指定皮肤包
|
||||||
SkinManager.getInstance().loadSkin(skin.getPathLocal());
|
SkinManager.getInstance().loadSkin(skin.getPathLocal());
|
||||||
// 回调给使用方成功
|
|
||||||
skinLoadListener.onLoadSuccess();
|
|
||||||
// 校验文件签名没问题后删除其他主题
|
// 校验文件签名没问题后删除其他主题
|
||||||
deleteFilesExcept(themeDirectory, skin.getSkinFileName());
|
deleteFilesExcept(themeDirectory, skin.getSkinFileName());
|
||||||
} else {
|
|
||||||
// 回调给使用方成功
|
// 回调给使用方成功
|
||||||
skinLoadListener.onLoadFailed(new Exception("皮肤文件校验出错,本地文件MD5 与云端文件MD5 不一致。"));
|
skinLoadListener.onLoadSuccess();
|
||||||
Log.e(TAG, "DownloadManager 皮肤文件校验出错,本地文件 MD5 = " + localSkinFileMd5 + " 与云端文件 MD5 = " + skin.md5 + " 不一致。");
|
} else {
|
||||||
|
Log.e(TAG, "皮肤包 皮肤文件 MD5校验出错, 本地文件 MD5 = " + localSkinFileMd5 + " 与云端文件 MD5 = " + skin.md5 + " 不一致。");
|
||||||
Toast.makeText(mApplication, "皮肤文件校验出错,本地文件 MD5 = " + localSkinFileMd5 + " 与云端文件 MD5 = " + skin.md5 + " 不一致。", Toast.LENGTH_LONG).show();
|
Toast.makeText(mApplication, "皮肤文件校验出错,本地文件 MD5 = " + localSkinFileMd5 + " 与云端文件 MD5 = " + skin.md5 + " 不一致。", Toast.LENGTH_LONG).show();
|
||||||
// TODO 删除本地皮肤文件,并重新下载(这个操作比较危险,需要严格保证配置文件中的md5与实际皮肤包一致,否则将是灾难)
|
// TODO 删除本地皮肤文件,并重新下载(这个操作比较危险,需要严格保证配置文件中的md5与实际皮肤包一致,否则将是灾难)
|
||||||
|
skinFile.delete();
|
||||||
|
|
||||||
|
// 回调给使用方成功
|
||||||
|
skinLoadListener.onLoadFailed(new Exception("皮肤文件校验出错,本地文件MD5 与云端文件MD5 不一致。"));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
skinLoadListener.onLoadFailed(e);
|
skinLoadListener.onLoadFailed(e);
|
||||||
@@ -205,7 +213,7 @@ public class SkinManager extends Observable {
|
|||||||
@Override
|
@Override
|
||||||
public void onDownloadFailed(Exception e) {
|
public void onDownloadFailed(Exception e) {
|
||||||
// 下载失败后的处理
|
// 下载失败后的处理
|
||||||
Log.e(TAG, "DownloadManager onDownloadFailed");
|
Log.e(TAG, "皮肤包下载出错 onDownloadFailed");
|
||||||
skinLoadListener.onLoadFailed(e);
|
skinLoadListener.onLoadFailed(e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -213,7 +221,7 @@ public class SkinManager extends Observable {
|
|||||||
@Override
|
@Override
|
||||||
public void onAlreadyDownloading(String url) {
|
public void onAlreadyDownloading(String url) {
|
||||||
// 处理重复下载的情况
|
// 处理重复下载的情况
|
||||||
Log.w(TAG, "DownloadManager onAlreadyDownloading url=" + url);
|
Log.w(TAG, "皮肤包 onAlreadyDownloading url=" + url);
|
||||||
skinLoadListener.onLoadFailed(new Exception("DownloadManager onAlreadyDownloading url=" + url));
|
skinLoadListener.onLoadFailed(new Exception("DownloadManager onAlreadyDownloading url=" + url));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package com.mogo.skin.net;
|
package com.mogo.skin.net;
|
||||||
|
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -12,6 +13,8 @@ import java.util.HashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class DownloadManager {
|
public class DownloadManager {
|
||||||
|
private static final String TAG = "DownloadManager";
|
||||||
|
|
||||||
private static final int BUFFER_SIZE = 1024 * 1024; // 1MB
|
private static final int BUFFER_SIZE = 1024 * 1024; // 1MB
|
||||||
private static final Map<String, DownloadTask> activeDownloads = new HashMap<>();
|
private static final Map<String, DownloadTask> activeDownloads = new HashMap<>();
|
||||||
private String downloadUrl;
|
private String downloadUrl;
|
||||||
@@ -32,6 +35,7 @@ public class DownloadManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DownloadManager(String url, String skinFileName, File directory, DownloadListener listener) {
|
public DownloadManager(String url, String skinFileName, File directory, DownloadListener listener) {
|
||||||
|
Log.d(TAG, "皮肤包下载参数……url = " + url + " skinFileName = " + skinFileName + " directory = " + directory);
|
||||||
this.downloadUrl = url;
|
this.downloadUrl = url;
|
||||||
this.outputDir = directory;
|
this.outputDir = directory;
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
@@ -39,11 +43,24 @@ public class DownloadManager {
|
|||||||
|
|
||||||
// 确保输出目录存在
|
// 确保输出目录存在
|
||||||
if (!outputDir.exists()) {
|
if (!outputDir.exists()) {
|
||||||
|
Log.d(TAG, "输出目录不存在,创建目录 outputDir = " + outputDir);
|
||||||
outputDir.mkdirs();
|
outputDir.mkdirs();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果文件不存在,则创建空文件
|
// 如果文件不存在,则创建空文件
|
||||||
if (!outputFile.exists()) {
|
if (!outputFile.exists()) {
|
||||||
|
Log.d(TAG, "皮肤包不存在,创建 outputFile = " + outputFile);
|
||||||
|
try {
|
||||||
|
outputFile.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (listener != null) {
|
||||||
|
listener.onDownloadFailed(e);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "皮肤包已存在,删除后创建 outputFile = " + outputFile);
|
||||||
|
outputFile.delete();
|
||||||
try {
|
try {
|
||||||
outputFile.createNewFile();
|
outputFile.createNewFile();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@@ -92,9 +109,10 @@ public class DownloadManager {
|
|||||||
connection.setRequestMethod("GET");
|
connection.setRequestMethod("GET");
|
||||||
connection.setConnectTimeout(15000); // 15 seconds
|
connection.setConnectTimeout(15000); // 15 seconds
|
||||||
connection.setReadTimeout(15000); // 15 seconds
|
connection.setReadTimeout(15000); // 15 seconds
|
||||||
if (downloadedLength > 0) {
|
// if (downloadedLength > 0) {
|
||||||
connection.setRequestProperty("Range", "bytes=" + downloadedLength + "-");
|
// Log.d(TAG, "皮肤包下载中……,之前有未下载完成的任务,继续下载。 downloadedLength =" + downloadedLength);
|
||||||
}
|
// connection.setRequestProperty("Range", "bytes=" + downloadedLength + "-");
|
||||||
|
// }
|
||||||
InputStream in = connection.getInputStream();
|
InputStream in = connection.getInputStream();
|
||||||
byte[] buffer = new byte[BUFFER_SIZE];
|
byte[] buffer = new byte[BUFFER_SIZE];
|
||||||
int read;
|
int read;
|
||||||
|
|||||||
Reference in New Issue
Block a user