mirror of
https://gitea.winboll.cc/Studio/OriginMaster.git
synced 2026-02-04 10:31:31 +08:00
添加FTP备份目标保存路径设置。
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sat Jan 31 12:06:15 GMT 2026
|
||||
#Sat Jan 31 13:02:06 GMT 2026
|
||||
stageCount=12
|
||||
libraryProject=libappbase
|
||||
baseVersion=15.15
|
||||
publishVersion=15.15.11
|
||||
buildCount=27
|
||||
buildCount=29
|
||||
baseBetaVersion=15.15.12
|
||||
|
||||
@@ -168,18 +168,18 @@ public class MainActivity extends Activity {
|
||||
public void onFTPBackupsActivity(View view) {
|
||||
LogUtils.d(TAG, "onFTPBackupsActivity() 调用");
|
||||
SFTPBackupsSettingsDialog dlg = new SFTPBackupsSettingsDialog(this);
|
||||
SFTPAuthModel authModel = dlg.getSFTPAuthModelFromSP(this);
|
||||
SFTPAuthModel authModel = SFTPBackupsSettingsDialog.getSFTPAuthModelFromSP(this);
|
||||
if (authModel == null) {
|
||||
dlg.show();
|
||||
} else {
|
||||
// 1. 构建应用Data目录待备份文件Map
|
||||
HashMap<String, String> dataFileMap = new HashMap<>();
|
||||
// 存入文件:key=唯一标识,value=应用外部文件目录下的相对路径(与原addSdcardFile参数一致)
|
||||
// 存入文件:key=唯一标识,value=应用Data目录下的相对路径
|
||||
dataFileMap.put(TestBean.class.getName() + ".json",
|
||||
getTestBeanRelativePath());
|
||||
// 1. 构建SDCard目录待备份文件Map(与BackupUtils的SdcardMap泛型一致:String-String)
|
||||
// 构建SDCard目录待备份文件Map(与BackupUtils的SdcardMap泛型一致:String-String)
|
||||
HashMap<String, String> sdcardFileMap = new HashMap<>();
|
||||
// 存入文件:key=唯一标识,value=应用外部文件目录下的相对路径(与原addSdcardFile参数一致)
|
||||
// 存入文件:key=唯一标识,value=应用专属外部文件目录下的相对路径
|
||||
sdcardFileMap.put(TestBean.class.getName() + ".json",
|
||||
getTestBeanRelativePath());
|
||||
|
||||
@@ -188,7 +188,8 @@ public class MainActivity extends Activity {
|
||||
// 3. 序列化传递Map参数(使用FTPBackupsActivity中定义的常量,避免硬编码)
|
||||
ftpBackupsIntent.putExtra(FTPBackupsActivity.EXTRA_DATA_DIR_FILE_MAP, dataFileMap);
|
||||
ftpBackupsIntent.putExtra(FTPBackupsActivity.EXTRA_SDCARD_DIR_FILE_MAP, sdcardFileMap);
|
||||
// 若需要传Data目录的Map,同理:ftpBackupsIntent.putExtra(FTPBackupsActivity.EXTRA_DATA_DIR_FILE_MAP, dataFileMap);
|
||||
// 传递FTP上传目标目录参数,路径为/WinBoLLStudio/APPBackups/WinBoLL
|
||||
ftpBackupsIntent.putExtra(FTPBackupsActivity.EXTRA_FTP_TARGET_DIR, "/WinBoLLStudio/APPBackups/WinBoLL");
|
||||
|
||||
// 4. 启动Activity,参数自动透传
|
||||
startActivity(ftpBackupsIntent);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#Created by .winboll/winboll_app_build.gradle
|
||||
#Sat Jan 31 12:06:15 GMT 2026
|
||||
#Sat Jan 31 13:02:06 GMT 2026
|
||||
stageCount=12
|
||||
libraryProject=libappbase
|
||||
baseVersion=15.15
|
||||
publishVersion=15.15.11
|
||||
buildCount=27
|
||||
buildCount=29
|
||||
baseBetaVersion=15.15.12
|
||||
|
||||
@@ -21,18 +21,19 @@ import cc.winboll.studio.libappbase.dialogs.SFTPBackupsSettingsDialog;
|
||||
|
||||
/**
|
||||
* BackupUtils 调用实例
|
||||
* 支持Intent传入双Map参数,初始化BackupUtils的待备份文件列表
|
||||
* 支持Intent传入双Map参数+FTP上传目标目录,初始化BackupUtils的待备份文件列表和上传路径
|
||||
* 强制校验FTP上传目录参数,未传参时直接提示不执行备份
|
||||
* @Author 豆包&ZhanGSKen<zhangsken@qq.com>
|
||||
* @Date 2026/01/30 20:55
|
||||
* @LastEditTime 2026/02/01 04:00
|
||||
* @LastEditTime 2026/02/01 11:00
|
||||
*/
|
||||
public class FTPBackupsActivity extends Activity {
|
||||
|
||||
public static final String TAG = "FTPBackupsActivity";
|
||||
// 主线程Handler:子线程更新UI专用
|
||||
private Handler mMainHandler;
|
||||
// FTP服务器上传目标目录(可根据业务自定义)
|
||||
private static final String FTP_TARGET_DIR = "/WinBoLLStudio/APPBackups/WinBoLL/";
|
||||
// FTP服务器上传目标目录-默认值(移除,改为强制传参,无默认值)
|
||||
private static final String DEFAULT_FTP_TARGET_DIR = null;
|
||||
|
||||
// ==================== Intent传参常量(规范外部调用)====================
|
||||
/**
|
||||
@@ -45,10 +46,16 @@ public class FTPBackupsActivity extends Activity {
|
||||
* 类型:HashMap<String,String> 实现Serializable接口
|
||||
*/
|
||||
public static final String EXTRA_SDCARD_DIR_FILE_MAP = "extra_sdcard_dir_file_map";
|
||||
/**
|
||||
* Intent传入参数-FTP/SFTP服务器上传目标目录【强制传参】
|
||||
* 类型:String 示例:/backup/app/ ,必须传参否则不执行备份
|
||||
*/
|
||||
public static final String EXTRA_FTP_TARGET_DIR = "extra_ftp_target_dir";
|
||||
|
||||
// 解析后的双Map参数(用于初始化BackupUtils)
|
||||
// 解析后的参数(用于初始化BackupUtils)
|
||||
private Map<String, String> mDataDirFileMap;
|
||||
private Map<String, String> mSdcardDirFileMap;
|
||||
private String mFtpTargetDir; // 解析后的FTP上传目标目录(强制非空)
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@@ -56,38 +63,60 @@ public class FTPBackupsActivity extends Activity {
|
||||
setContentView(R.layout.activity_ftp_backups);
|
||||
// 初始化主线程Handler,避免子线程更新UI崩溃
|
||||
mMainHandler = new Handler(Looper.getMainLooper());
|
||||
// 解析Intent中的双Map参数
|
||||
// 解析Intent中的所有参数(双Map+FTP上传目录)
|
||||
parseIntentParams();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析Intent传入的序列化Map参数
|
||||
* 兜底处理:参数为空/类型错误时,赋值为null(兼容BackupUtils初始化逻辑)
|
||||
* 解析Intent传入的所有序列化参数
|
||||
* 兜底处理:双Map解析失败初始化空Map,FTP目录**未传/空则直接赋值null,不兜底默认值**
|
||||
*/
|
||||
private void parseIntentParams() {
|
||||
Intent intent = getIntent();
|
||||
if (intent != null) {
|
||||
// 解析Data目录Map:强转为HashMap(实现Serializable,可序列化传递)
|
||||
Serializable dataMapSer = intent.getSerializableExtra(EXTRA_DATA_DIR_FILE_MAP);
|
||||
if (dataMapSer instanceof HashMap) {
|
||||
mDataDirFileMap = (HashMap<String, String>) dataMapSer;
|
||||
LogUtils.d(TAG, "Intent解析Data目录Map成功,共" + mDataDirFileMap.size() + "个文件");
|
||||
} else {
|
||||
mDataDirFileMap = null;
|
||||
LogUtils.d(TAG, "Intent未解析到有效Data目录Map");
|
||||
}
|
||||
|
||||
// 解析SDCard目录Map:强转为HashMap(实现Serializable,可序列化传递)
|
||||
Serializable sdcardMapSer = intent.getSerializableExtra(EXTRA_SDCARD_DIR_FILE_MAP);
|
||||
if (sdcardMapSer instanceof HashMap) {
|
||||
mSdcardDirFileMap = (HashMap<String, String>) sdcardMapSer;
|
||||
LogUtils.d(TAG, "Intent解析SDCard目录Map成功,共" + mSdcardDirFileMap.size() + "个文件");
|
||||
} else {
|
||||
mSdcardDirFileMap = null;
|
||||
LogUtils.d(TAG, "Intent未解析到有效SDCard目录Map");
|
||||
}
|
||||
if (intent == null) {
|
||||
LogUtils.w(TAG, "parseIntentParams:Intent为null,参数解析失败");
|
||||
initEmptyParams();
|
||||
return;
|
||||
}
|
||||
// 未解析到参数时,保持null即可,BackupUtils内部会默认初始化空Map
|
||||
|
||||
// 1. 解析Data目录Map:强转为HashMap,失败则初始化空Map
|
||||
Serializable dataMapSer = intent.getSerializableExtra(EXTRA_DATA_DIR_FILE_MAP);
|
||||
if (dataMapSer instanceof HashMap) {
|
||||
mDataDirFileMap = (HashMap<String, String>) dataMapSer;
|
||||
LogUtils.d(TAG, "Intent解析Data目录Map成功,共" + mDataDirFileMap.size() + "个文件");
|
||||
} else {
|
||||
mDataDirFileMap = new HashMap<>();
|
||||
LogUtils.d(TAG, "Intent未解析到有效Data目录Map,初始化空Map");
|
||||
}
|
||||
|
||||
// 2. 解析SDCard目录Map:强转为HashMap,失败则初始化空Map
|
||||
Serializable sdcardMapSer = intent.getSerializableExtra(EXTRA_SDCARD_DIR_FILE_MAP);
|
||||
if (sdcardMapSer instanceof HashMap) {
|
||||
mSdcardDirFileMap = (HashMap<String, String>) sdcardMapSer;
|
||||
LogUtils.d(TAG, "Intent解析SDCard目录Map成功,共" + mSdcardDirFileMap.size() + "个文件");
|
||||
} else {
|
||||
mSdcardDirFileMap = new HashMap<>();
|
||||
LogUtils.d(TAG, "Intent未解析到有效SDCard目录Map,初始化空Map");
|
||||
}
|
||||
|
||||
// 3. 解析FTP上传目标目录:**强制校验,未传/空/空格则直接赋值null,不兜底**
|
||||
String inputFtpDir = intent.getStringExtra(EXTRA_FTP_TARGET_DIR);
|
||||
if (inputFtpDir != null && !inputFtpDir.trim().isEmpty()) {
|
||||
mFtpTargetDir = inputFtpDir.trim().endsWith("/") ? inputFtpDir.trim() : inputFtpDir.trim() + "/";
|
||||
LogUtils.d(TAG, "Intent解析FTP上传目录成功:" + mFtpTargetDir);
|
||||
} else {
|
||||
mFtpTargetDir = null;
|
||||
LogUtils.w(TAG, "Intent未传递/传递空的FTP上传目录参数,禁止执行备份");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化空参数:Intent为null时使用,FTP目录直接赋值null
|
||||
*/
|
||||
private void initEmptyParams() {
|
||||
mDataDirFileMap = new HashMap<>();
|
||||
mSdcardDirFileMap = new HashMap<>();
|
||||
mFtpTargetDir = null;
|
||||
}
|
||||
|
||||
public void onSFTPSettings(View view) {
|
||||
@@ -97,57 +126,68 @@ public class FTPBackupsActivity extends Activity {
|
||||
|
||||
/**
|
||||
* 点击事件:执行FTP备份(核心调用方法)
|
||||
* 主线程仅做UI触发,所有核心逻辑在子线程执行
|
||||
* 每次点击都重新解析Intent参数,保证获取最新的文件列表
|
||||
* 【强制校验】未传递FTP_TARGET_DIR参数时,仅吐司提示,不执行任何操作
|
||||
* 每次点击都重新解析Intent参数,保证参数最新
|
||||
*/
|
||||
public void onBackups(View view) {
|
||||
ToastUtils.show("开始执行FTP备份,请勿退出页面...");
|
||||
LogUtils.d(TAG, "触发FTP备份操作,开启子线程执行核心逻辑");
|
||||
// 每次点击都重新解析Intent参数,避免Activity复用导致参数失效
|
||||
// 1. 重新解析参数,保证最新
|
||||
parseIntentParams();
|
||||
SFTPBackupsSettingsDialog dlg = new SFTPBackupsSettingsDialog(this);
|
||||
SFTPAuthModel authModel = dlg.getSFTPAuthModelFromSP(this);
|
||||
if (authModel == null) {
|
||||
dlg.show();
|
||||
} else {
|
||||
// 传入解析后的双Map参数
|
||||
doBackups(authModel, mDataDirFileMap, mSdcardDirFileMap);
|
||||
// 2. 强制核心校验:FTP上传目录未传参,直接吐司提示,不执行后续操作
|
||||
if (mFtpTargetDir == null) {
|
||||
ToastUtils.show("备份失败:未设置FTP上传目标目录参数");
|
||||
LogUtils.e(TAG, "触发备份操作失败:Intent未传递EXTRA_FTP_TARGET_DIR参数");
|
||||
return;
|
||||
}
|
||||
// 3. 校验SFTP配置,未配置则弹框
|
||||
SFTPAuthModel authModel = SFTPBackupsSettingsDialog.getSFTPAuthModelFromSP(this);
|
||||
if (authModel == null) {
|
||||
ToastUtils.show("备份失败:请先配置SFTP服务器信息");
|
||||
new SFTPBackupsSettingsDialog(this).show();
|
||||
LogUtils.w(TAG, "触发备份操作失败:未配置SFTP服务器信息");
|
||||
return;
|
||||
}
|
||||
// 4. 所有校验通过,提示并执行备份
|
||||
ToastUtils.show("开始执行FTP备份,请勿退出页面...");
|
||||
LogUtils.d(TAG, "所有校验通过,开启子线程执行备份核心逻辑");
|
||||
doBackups(authModel, mDataDirFileMap, mSdcardDirFileMap, mFtpTargetDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心备份逻辑:子线程执行
|
||||
* 核心备份逻辑:子线程执行(仅在校验通过后调用)
|
||||
* @param authModel SFTP认证模型
|
||||
* @param dataDirFileMap Intent解析的Data目录文件Map
|
||||
* @param sdcardDirFileMap Intent解析的SDCard目录文件Map
|
||||
* @param ftpTargetDir Intent解析的FTP上传目标目录(已标准化、非空)
|
||||
*/
|
||||
void doBackups(final SFTPAuthModel authModel, final Map<String, String> dataDirFileMap, final Map<String, String> sdcardDirFileMap) {
|
||||
void doBackups(final SFTPAuthModel authModel, final Map<String, String> dataDirFileMap,
|
||||
final Map<String, String> sdcardDirFileMap, final String ftpTargetDir) {
|
||||
// 所有BackupUtils操作放入子线程,规避网络/IO主线程异常
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// 初始化BackupUtils单例,透传解析后的双Map参数
|
||||
// 初始化BackupUtils单例,透传动态解析的FTP上传目录
|
||||
BackupUtils backupUtils = BackupUtils.getInstance(
|
||||
getApplicationContext(),
|
||||
authModel,
|
||||
FTP_TARGET_DIR,
|
||||
dataDirFileMap,
|
||||
sdcardDirFileMap
|
||||
ftpTargetDir
|
||||
);
|
||||
|
||||
LogUtils.d(TAG, "待备份文件初始化完成 → Data目录:" + backupUtils.getAllDataDirFiles().size() + "个 | SDCard目录:" + backupUtils.getAllSdcardFiles().size() + "个");
|
||||
// 向BackupUtils添加解析后的待备份文件(双Map)
|
||||
addBackupFilesToUtils(backupUtils, dataDirFileMap, sdcardDirFileMap);
|
||||
|
||||
LogUtils.d(TAG, "待备份文件初始化完成 → Data目录:" + backupUtils.getAllDataDirFiles().size() + "个 | SDCard目录:" + backupUtils.getAllSdcardFiles().size() + "个 | 上传目录:" + ftpTargetDir);
|
||||
|
||||
// 核心执行:打包为ZIP + SFTP上传(内部已实现登录→打包→上传→登出)
|
||||
boolean isSuccess = backupUtils.packAndUploadByFtp();
|
||||
|
||||
// 主线程反馈执行结果
|
||||
if (isSuccess) {
|
||||
updateUi("FTP备份成功!文件已打包为ZIP上传至服务器:" + FTP_TARGET_DIR);
|
||||
LogUtils.i(TAG, "FTP备份全流程执行成功");
|
||||
updateUi("FTP备份成功!文件已打包为ZIP上传至服务器:" + ftpTargetDir);
|
||||
LogUtils.i(TAG, "FTP备份全流程执行成功,上传目录:" + ftpTargetDir);
|
||||
} else {
|
||||
updateUi("FTP备份失败!请检查服务器配置或文件路径");
|
||||
LogUtils.e(TAG, "FTP备份全流程执行失败");
|
||||
LogUtils.e(TAG, "FTP备份全流程执行失败,上传目录:" + ftpTargetDir);
|
||||
}
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
@@ -168,6 +208,26 @@ public class FTPBackupsActivity extends Activity {
|
||||
}).start();
|
||||
}
|
||||
|
||||
/**
|
||||
* 向BackupUtils添加待备份文件:遍历双Map,调用add方法逐个添加
|
||||
* 先清空原有文件,避免Activity复用导致文件重复
|
||||
* @param backupUtils BackupUtils实例
|
||||
* @param dataMap Data目录待备份文件Map
|
||||
* @param sdcardMap SDCard目录待备份文件Map
|
||||
*/
|
||||
private void addBackupFilesToUtils(BackupUtils backupUtils, Map<String, String> dataMap, Map<String, String> sdcardMap) {
|
||||
backupUtils.clearDataDirFiles();
|
||||
backupUtils.clearSdcardFiles();
|
||||
// 添加Data目录文件
|
||||
for (Map.Entry<String, String> entry : dataMap.entrySet()) {
|
||||
backupUtils.addDataDirFile(entry.getKey(), entry.getValue());
|
||||
}
|
||||
// 添加SDCard目录文件
|
||||
for (Map.Entry<String, String> entry : sdcardMap.entrySet()) {
|
||||
backupUtils.addSdcardFile(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 子线程更新UI工具方法(Toast提示)
|
||||
* @param msg 提示信息
|
||||
@@ -192,9 +252,10 @@ public class FTPBackupsActivity extends Activity {
|
||||
if (mMainHandler != null) {
|
||||
mMainHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
// 清空本地Map引用,协助GC(不影响BackupUtils内部逻辑)
|
||||
// 清空本地引用,协助GC
|
||||
mDataDirFileMap = null;
|
||||
mSdcardDirFileMap = null;
|
||||
mFtpTargetDir = null;
|
||||
LogUtils.d(TAG, "FTPBackupsActivity销毁:已释放本地资源,不影响二次备份初始化");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user