private class RxUpdateManager {
private CompositeDisposable disposables = new CompositeDisposable();
private PublishSubject<String> progressSubject = PublishSubject.create();
private PublishSubject<Integer> resultSubject = PublishSubject.create();
public void startUpdate() {
Observable<Integer> updateObservable = Observable.create(emitter -> {
try {
// 阶段1: 备份数据
if (emitter.isDisposed()) return;
currentPhase.set(PHASE_BACKUP);
notifyProgress("开始备份数据...");
backupDir = new File(cacheDir, "backup");
if (backupDir.exists()) {
if (!FileUtils.deleteRecursive(backupDir)) {
emitter.onError(new IOException("删除备份文件失败"));
return;
}
}
if (!backupDir.mkdirs()) {
emitter.onError(new IOException("创建备份目录失败"));
return;
}
backupSize = FileUtils.getDirectorySize(storageDir);
if (backupSize > 0) {
if (!singlecopydirectory.copyDirectoryWithProgress(storageDir, backupDir, (copied, total) -> {
currentCopiedBytes = copied;
notifyProgress("备份中: " + formatSize(copied) + "/" + formatSize(total));
})) {
emitter.onError(new IOException("备份失败"));
return;
}
if (!backupDir.renameTo(backupAlreadyDir)) {
emitter.onError(new IOException("重命名备份目录失败"));
return;
}
} else {
currentCopiedBytes = 1;
backupSize = 1;
notifyProgress("无数据需要备份");
}
// 阶段2: 处理升级包
currentPhase.set(PHASE_COPYING);
File[] updatePackages = getUpdatePackages();
for (int i = 0; i < updatePackages.length; i++) {
if (isCancelled) {
emitter.onError(new IOException("用户取消"));
return;
}
while (isPaused) {
if (emitter.isDisposed()) return;
Thread.sleep(500);
}
File packageFile = updatePackages[i];
String packageName = packageFile.getName();
// 拷贝
currentPhase.set(PHASE_COPYING);
File destFile = new File(storageDir, packageName);
boolean copyResult = FileUtils.copyFileWithProgress(packageFile, destFile, (copied, total) -> {
currentCopiedBytes = copied;
notifyProgress("拷贝中: " + formatSize(copied) + "/" + formatSize(total));
});
if (!copyResult) {
emitter.onError(new IOException("拷贝失败"));
return;
}
// 解密验签
currentPhase.set(PHASE_CHECKING);
DecryptUtil.ProgressCallback decryptCallback = (processed, total) -> {
currentVerifiedBytes = processed;
notifyProgress("解密中: " + formatSize(processed) + "/" + formatSize(total));
};
if (!dataVerification(destFile.getAbsolutePath(), decryptCallback)) {
emitter.onError(new IOException("解密失败"));
return;
}
// 解压
currentPhase.set(PHASE_EXTRACTING);
boolean extractResult = FileUtils.extractZipWithProgress(destFile, storageDir, (extracted, total) -> {
currentExtractedBytes = extracted;
notifyProgress("解压中: " + formatSize(extracted) + "/" + formatSize(total));
});
if (!extractResult) {
emitter.onError(new IOException("解压失败"));
return;
}
if (!destFile.delete()) {
Log.w(TAG, "删除升级包失败");
}
}
if (!mapDataController.checkInstallationStatus()) {
notifyProgress("校验失败");
emitter.onError(new IOException("校验失败"));
return;
}
// 清理
currentPhase.set(PHASE_CLEANUP);
notifyProgress("清理缓存...");
if (backupDir.exists() && !FileUtils.deleteRecursive(backupDir)) {
Log.w(TAG, "删除备份文件失败");
}
notifyProgress("更新完成");
emitter.onNext(SUCCESS);
emitter.onComplete();
} catch (Exception e) {
emitter.onError(e);
}
});
Disposable disposable = updateObservable
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
result -> {
if (result == SUCCESS) {
if (backupAlreadyDir != null && backupAlreadyDir.exists()) {
if (!FileUtils.deleteRecursive(backupAlreadyDir)) {
Log.w(TAG, "删除备份文件失败");
}
}
notifyListener(SUCCESS, "更新成功");
currentPhase.set(PHASE_IDLE);
}
},
error -> {
if (error instanceof IOException && error.getMessage().contains("用户取消")) {
notifyListener(ERROR_USER_CANCELED, "用户取消");
} else {
handleFailure(ERROR_UNEXPECTED);
}
}
);
disposables.add(disposable);
}
public void cancelUpdate() {
disposables.clear(); // 取消所有任务
rollback(); // 执行回滚
}
private void rollback() {
// 执行回滚逻辑
Log.i(TAG, "执行回滚操作");
}
}
// // ================== 核心更新逻辑 ==================
private class UpdateTask extends AsyncTask<Void, Void, Integer> {
// private File backupFile;//zwx-s
private File[] updatePackages;
@Override
protected void onPreExecute() {
currentPhase.set(PHASE_DETECTING);
isCancelled = false;
isPaused = false;
currentCopiedBytes = 0;
currentExtractedBytes = 0;
mProgress = 0; // 重置进度为0
}
@Override
protected Integer doInBackground(Void... voids) {
try {
// 阶段1: 备份数据
currentPhase.set(PHASE_BACKUP);
notifyProgress("开始备份数据...");
backupDir = new File(cacheDir, "backup");
Log.i(TAG, "初始化备份目录为:" + backupDir.getAbsolutePath());//ZWX
if (backupDir.exists()) {
if (!FileUtils.deleteRecursive(backupDir)) {
throw new IOException("删除备份文件失败: " + backupDir.getAbsolutePath());
}
}
if (!backupDir.mkdirs()) {
throw new IOException("创建备份目录失败: " + backupDir.getAbsolutePath());
}
// 计算实际备份大小
Log.i(TAG, "核对实际需要备份的数据大小");
backupSize = FileUtils.getDirectorySize(storageDir);
Log.i(TAG, "需要备份的数据大小:[" + formatSize(backupSize) + "]");
Log.i(TAG, "storage目录为:" + storageDir.getAbsolutePath());//ZWX
if (backupSize > 0) {
Log.i(TAG, "开始进行数据备份");
try {
// 执行目录复制
if (!singlecopydirectory.copyDirectoryWithProgress(storageDir, backupDir, (copied, total) -> {
currentCopiedBytes = copied;
notifyProgress("备份中: " + formatSize(copied) + "/" + formatSize(total));
})) {
throw new IOException("备份失败: " + storageDir.getAbsolutePath() + " -> " + backupDir.getAbsolutePath());
}
notifyProgress("数据备份完成");//P4
if (!backupDir.renameTo(backupAlreadyDir)) {
throw new IOException("重命名备份目录失败: " + backupDir.getAbsolutePath() + " -> " + backupAlreadyDir.getAbsolutePath());
}
Log.i(TAG, "重命名备份目录成功");
} catch (Exception e) {
Log.e(TAG, "备份过程中发生错误", e);
// 可选:尝试二次备份或记录日志,这里直接抛出错误
return ERROR_COPY_FAILED;
}
} else {
// 无数据需要备份,直接标记完成
Log.i(TAG, "无备份数据,直接进行数据更新");
currentCopiedBytes = 1;
backupSize = 1;
notifyProgress("无数据需要备份");
}
// 检查是否被取消(场景1)
if (isCancelled) {
return ERROR_USER_CANCELED;
}
// 阶段2: 处理升级包
//p5:更新前清理压缩包
// if (storageDir.exists() && storageDir.isDirectory()) {
// if (!singlecopydirectory.clearDirectoryContentsOnly(storageDir.toPath())) {
//
// throw new IOException("无法清空目标目录: " + storageDir.getAbsolutePath());
//
// }
// }
updatePackages = getUpdatePackages();
Log.i(TAG, "开始处理升级包【拷贝、解密验签、解压】");
for (currentPackageIndex = 0; currentPackageIndex < updatePackages.length; currentPackageIndex++) {
if (isCancelled) return ERROR_USER_CANCELED;
// 处理暂停状态
while (isPaused) {
Thread.sleep(500);
}
File packageFile = updatePackages[currentPackageIndex];
UpdateSize = updatePackages[currentPackageIndex].length();
String packageName = packageFile.getName();
long packageSize = packageFile.length();
// 备份完成后重置拷贝计数器
currentCopiedBytes = 0;
// 阶段3: 拷贝升级包
currentPhase.set(PHASE_COPYING);
File destFile = new File(storageDir, packageName);
// 拷贝时更新进度(修改)
boolean copyResult = FileUtils.copyFileWithProgress(
packageFile,
destFile,
(copied, total) -> {
currentCopiedBytes = copied;
notifyProgress(String.format("拷贝 %s: %s/%s",
packageName,
formatSize(copied),
formatSize(total)));
}
);
if (!copyResult) {
lastErrorMessage = "拷贝失败: " + packageName;
return ERROR_COPY_FAILED;
}
// 阶段4:解密验签
currentPhase.set(PHASE_CHECKING);
currentVerifiedBytes = 0; // 重置验签计数器
// 创建进度回调适配器
DecryptUtil.ProgressCallback decryptCallback = new DecryptUtil.ProgressCallback() {
@Override
public void onProgress(long processed, long total) {
// 直接更新验签进度计数器
currentVerifiedBytes = processed;
// 触发进度通知
notifyProgress(String.format("解密验签 %s: %s/%s",
packageName,
formatSize(processed),
formatSize(total)));
}
};
// 执行解密验签(传入回调)
if (!dataVerification(destFile.getAbsolutePath(), decryptCallback)) {
if (!isCancelled) {
return ERROR_DECRYPT_OR_SIGN_FAILED;
}
}
// 确保进度设置为100%
currentVerifiedBytes = UpdateSize;
// 阶段5: 解压升级包
currentPhase.set(PHASE_EXTRACTING);
// 修复:重置解压计数器
currentExtractedBytes = 0; // 重置计数器
notifyProgress("解压升级包: " + packageName);
// 解压时更新进度(修改)
boolean extractResult = FileUtils.extractZipWithProgress(
destFile,
storageDir,
(extracted, total) -> {
currentExtractedBytes = extracted;
notifyProgress(String.format("解压 %s: %s/%s",
packageName,
formatSize(extracted),
formatSize(total)));
}
);
if (!extractResult) {
lastErrorMessage = "解压失败: " + packageName;
return ERROR_EXTRACT_FAILED;
}
// 删除已解压的升级包以节省空间
if (!destFile.delete()) {
Log.w(TAG, "删除升级包失败: " + destFile.getName());
}
// 更新解压进度(完成当前包)
currentExtractedBytes += packageSize;
}
if (!mapDataController.checkInstallationStatus()) {
notifyProgress("校验失败");
return ERROR_FILE_VERIFY_FAILED;
} else {
notifyProgress("校验成功");
}
// MapDownloader.fromEngineAsync(sdkNativeEngine, new MapDownloaderConstructionCallback() {
// @Override
// public void onMapDownloaderConstructedCompleted(@NonNull MapDownloader downloader) {
// Log.i(TAG, "数据同步成功");
// }
// });
// 阶段5: 清理工作
currentPhase.set(PHASE_CLEANUP);
notifyProgress("清理缓存...");
if (backupDir.exists() && !FileUtils.deleteRecursive(backupDir)) {
Log.w(TAG, "删除备份文件失败");
}
// 最终进度设为100%
notifyProgress("更新完成");
return SUCCESS;
} catch (InterruptedException e) {
lastErrorMessage = "更新任务被中断";
handleFailure(ERROR_USER_CANCELED);
return ERROR_USER_CANCELED;
} catch (Exception e) {
lastErrorMessage = "未知错误: " + e.getMessage();
Log.e(TAG, "更新失败", e);
return ERROR_UNEXPECTED;
}
}
@Override
protected void onCancelled() {
lastErrorMessage = "更新任务被中断";
handleFailure(ERROR_USER_CANCELED);
Log.d("MyTask", "任务被取消");
}
@Override
protected void onPostExecute(Integer resultCode) {
if (resultCode == SUCCESS) {
if (backupAlreadyDir != null && backupAlreadyDir.exists()) {
Log.w(TAG, "开始删除备份文件: " + backupAlreadyDir.getAbsolutePath());
if (!FileUtils.deleteRecursive(backupAlreadyDir)) {
Log.w(TAG, "删除备份文件失败: " + backupAlreadyDir.getAbsolutePath());
}
}
notifyListener(SUCCESS, "更新成功,请重启车机");
currentPhase.set(PHASE_IDLE);
currentTask = null;
}
else {
handleFailure(resultCode);//p4-1
}
}
}
务必保证rxjava和asynctask的流程注释文言完全一致,修复rxjava让它保持其优越性的基础上,在功能性上和asynctask一致。给出完整的rxjava实现
最新发布