Skip to content

Commit 3101760

Browse files
committed
新增:一键克隆增加离线模式(导出备份json文件到Download目录,其他机器读取文件导入)
优化:一键克隆机制优化(替换db文件→操作现有db)
1 parent 60dde07 commit 3101760

21 files changed

+749
-505
lines changed
Lines changed: 108 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,32 @@
11
package com.idormy.sms.forwarder;
22

33
import android.annotation.SuppressLint;
4-
import android.app.ProgressDialog;
54
import android.content.Context;
65
import android.os.Bundle;
7-
import android.os.Handler;
8-
import android.os.Message;
6+
import android.os.Environment;
97
import android.text.TextUtils;
108
import android.util.Log;
9+
import android.view.View;
1110
import android.widget.Button;
11+
import android.widget.LinearLayout;
12+
import android.widget.RadioGroup;
1213
import android.widget.TextView;
1314

1415
import androidx.annotation.NonNull;
1516
import androidx.appcompat.app.AppCompatActivity;
1617

1718
import com.alibaba.fastjson.JSON;
19+
import com.hjq.permissions.OnPermissionCallback;
20+
import com.hjq.permissions.Permission;
21+
import com.hjq.permissions.XXPermissions;
1822
import com.hjq.toast.ToastUtils;
1923
import com.idormy.sms.forwarder.model.vo.CloneInfoVo;
2024
import com.idormy.sms.forwarder.receiver.BaseServlet;
2125
import com.idormy.sms.forwarder.receiver.RebootBroadcastReceiver;
2226
import com.idormy.sms.forwarder.sender.HttpServer;
23-
import com.idormy.sms.forwarder.utils.BackupDbTask;
27+
import com.idormy.sms.forwarder.utils.CloneUtils;
2428
import com.idormy.sms.forwarder.utils.Define;
25-
import com.idormy.sms.forwarder.utils.DownloadUtil;
29+
import com.idormy.sms.forwarder.utils.FileUtils;
2630
import com.idormy.sms.forwarder.utils.HttpUtil;
2731
import com.idormy.sms.forwarder.utils.NetUtil;
2832
import com.idormy.sms.forwarder.utils.SettingUtil;
@@ -31,6 +35,7 @@
3135
import java.io.File;
3236
import java.io.IOException;
3337
import java.util.HashMap;
38+
import java.util.List;
3439
import java.util.Map;
3540
import java.util.Objects;
3641
import java.util.concurrent.TimeUnit;
@@ -47,37 +52,19 @@ public class CloneActivity extends AppCompatActivity {
4752
private final String TAG = "CloneActivity";
4853
private Context context;
4954
private String serverIp;
50-
public static final String DATABASE_NAME = "sms_forwarder.db";
55+
private String backupPath;
56+
private final String backupFile = "SmsForwarder.json";
5157
private IPEditText textServerIp;
5258
private TextView sendTxt;
5359
private TextView receiveTxt;
60+
private TextView backupPathTxt;
5461
private Button sendBtn;
55-
public static final int TOAST = 0x9731994;
56-
public static final int DOWNLOAD = 0x9731995;
57-
58-
//消息处理者,创建一个Handler的子类对象,目的是重写Handler的处理消息的方法(handleMessage())
59-
@SuppressWarnings("deprecation")
60-
@SuppressLint("HandlerLeak")
61-
private final Handler handError = new Handler() {
62-
@Override
63-
public void handleMessage(Message msg) {
64-
if (msg.what == TOAST) {
65-
ToastUtils.delayedShow(msg.getData().getString("DATA"), 3000);
66-
} else if (msg.what == DOWNLOAD) {
67-
String savePath = context.getCacheDir().getPath() + File.separator + BackupDbTask.BACKUP_FILE;
68-
Log.d(TAG, savePath);
69-
downloadFile(msg.getData().getString("URL"), context.getCacheDir().getPath(), BackupDbTask.BACKUP_FILE, msg.getData().getString("INFO"));
70-
}
71-
}
72-
};
7362

7463
@Override
7564
public void onCreate(Bundle savedInstanceState) {
7665
Log.d(TAG, "onCreate");
7766
super.onCreate(savedInstanceState);
7867

79-
context = CloneActivity.this;
80-
8168
setContentView(R.layout.activity_clone);
8269
Log.d(TAG, "onCreate: " + RebootBroadcastReceiver.class.getName());
8370

@@ -92,6 +79,41 @@ protected void onStart() {
9279
super.onStart();
9380
Log.d(TAG, "onStart");
9481

82+
backupPathTxt = findViewById(R.id.backupPathTxt);
83+
// 申请储存权限
84+
XXPermissions.with(this).permission(Permission.Group.STORAGE).request(new OnPermissionCallback() {
85+
@Override
86+
public void onGranted(List<String> permissions, boolean all) {
87+
backupPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath();
88+
backupPathTxt.setText(backupPath + File.separator + backupFile);
89+
}
90+
91+
@Override
92+
public void onDenied(List<String> permissions, boolean never) {
93+
if (never) {
94+
ToastUtils.show(R.string.toast_denied_never);
95+
// 如果是被永久拒绝就跳转到应用权限系统设置页面
96+
XXPermissions.startPermissionActivity(CloneActivity.this, permissions);
97+
} else {
98+
ToastUtils.show(R.string.toast_denied);
99+
}
100+
backupPathTxt.setText("未授权储存权限,该功能无法使用!");
101+
}
102+
});
103+
104+
LinearLayout layoutNetwork = findViewById(R.id.layoutNetwork);
105+
LinearLayout layoutOffline = findViewById(R.id.layoutOffline);
106+
final RadioGroup radioGroupTypeCheck = findViewById(R.id.radioGroupTypeCheck);
107+
radioGroupTypeCheck.setOnCheckedChangeListener((group, checkedId) -> {
108+
if (checkedId == R.id.btnTypeOffline) {
109+
layoutNetwork.setVisibility(View.GONE);
110+
layoutOffline.setVisibility(View.VISIBLE);
111+
} else {
112+
layoutNetwork.setVisibility(View.VISIBLE);
113+
layoutOffline.setVisibility(View.GONE);
114+
}
115+
});
116+
95117
sendBtn = findViewById(R.id.sendBtn);
96118
sendTxt = findViewById(R.id.sendTxt);
97119
TextView ipText = findViewById(R.id.ipText);
@@ -110,18 +132,14 @@ protected void onStart() {
110132
sendBtn.setText(R.string.send);
111133
sendTxt.setText(R.string.server_has_stopped);
112134
}
113-
//noinspection CommentedOutCode
135+
136+
//发送
114137
sendBtn.setOnClickListener(v -> {
115138
if (!HttpServer.asRunning() && NetUtil.NETWORK_WIFI != NetUtil.getNetWorkStatus()) {
116-
Toast(handError, TAG, getString(R.string.no_wifi_network));
139+
ToastUtils.show(getString(R.string.no_wifi_network));
117140
return;
118141
}
119142

120-
//备份文件
121-
//BackupDbTask task = new BackupDbTask(this);
122-
//String backup_version = task.doInBackground(BackupDbTask.COMMAND_BACKUP);
123-
//Log.d(TAG, "backup_version = " + backup_version);
124-
125143
SettingUtil.switchEnableHttpServer(!SettingUtil.getSwitchEnableHttpServer());
126144
if (!HttpServer.update()) {
127145
SettingUtil.switchEnableHttpServer(!SettingUtil.getSwitchEnableHttpServer());
@@ -138,23 +156,24 @@ protected void onStart() {
138156
}
139157
});
140158

159+
//接收
141160
receiveBtn.setOnClickListener(v -> {
142161
if (HttpServer.asRunning()) {
143162
receiveTxt.setText(R.string.sender_cannot_receive);
144-
Toast(handError, TAG, getString(R.string.sender_cannot_receive));
163+
ToastUtils.show(getString(R.string.sender_cannot_receive));
145164
return;
146165
}
147166

148167
if (NetUtil.NETWORK_WIFI != NetUtil.getNetWorkStatus()) {
149168
receiveTxt.setText(R.string.no_wifi_network);
150-
Toast(handError, TAG, getString(R.string.no_wifi_network));
169+
ToastUtils.show(getString(R.string.no_wifi_network));
151170
return;
152171
}
153172

154173
serverIp = textServerIp.getIP();
155174
if (serverIp == null || serverIp.isEmpty()) {
156175
receiveTxt.setText(R.string.invalid_server_ip);
157-
Toast(handError, TAG, getString(R.string.invalid_server_ip));
176+
ToastUtils.show(getString(R.string.invalid_server_ip));
158177
return;
159178
}
160179

@@ -187,7 +206,7 @@ protected void onStart() {
187206
client.newCall(request).enqueue(new Callback() {
188207
@Override
189208
public void onFailure(@NonNull Call call, @NonNull final IOException e) {
190-
Toast(handError, TAG, getString(R.string.tips_get_info_failed));
209+
ToastUtils.show(getString(R.string.tips_get_info_failed));
191210
}
192211

193212
@Override
@@ -196,7 +215,7 @@ public void onResponse(@NonNull Call call, @NonNull Response response) throws IO
196215
Log.d(TAG, "Response:" + response.code() + "," + responseStr);
197216

198217
if (TextUtils.isEmpty(responseStr)) {
199-
Toast(handError, TAG, getString(R.string.tips_get_info_failed));
218+
ToastUtils.show(getString(R.string.tips_get_info_failed));
200219
return;
201220
}
202221

@@ -205,27 +224,68 @@ public void onResponse(@NonNull Call call, @NonNull Response response) throws IO
205224
Log.d(TAG, cloneInfoVo.toString());
206225

207226
if (!SettingUtil.getVersionName().equals(cloneInfoVo.getVersionName())) {
208-
Toast(handError, TAG, getString(R.string.tips_versions_inconsistent));
227+
ToastUtils.show(getString(R.string.tips_versions_inconsistent));
209228
return;
210229
}
211230

212-
//下载备份文件
213-
Message msg = new Message();
214-
msg.what = DOWNLOAD;
215-
Bundle bundle = new Bundle();
216-
bundle.putString("URL", requestUrl);
217-
bundle.putString("INFO", responseStr);
218-
msg.setData(bundle);
219-
handError.sendMessage(msg);
231+
if (CloneUtils.restoreSettings(cloneInfoVo)) {
232+
ToastUtils.show(getString(R.string.tips_clone_done));
233+
} else {
234+
ToastUtils.show(getString(R.string.tips_clone_failed));
235+
}
220236

221237
} catch (Exception e) {
222-
Toast(handError, TAG, getString(R.string.tips_clone_failed) + e.getMessage());
238+
ToastUtils.show(getString(R.string.tips_clone_failed) + e.getMessage());
223239
}
224240
}
225241
});
226242

227243
});
228244

245+
Button exportBtn = findViewById(R.id.exportBtn);
246+
TextView exportTxt = findViewById(R.id.exportTxt);
247+
Button importBtn = findViewById(R.id.importBtn);
248+
TextView importTxt = findViewById(R.id.importTxt);
249+
250+
//导出
251+
exportBtn.setOnClickListener(v -> {
252+
if (FileUtils.writeFileR(CloneUtils.exportSettings(), backupPath, backupFile, true)) {
253+
ToastUtils.show("导出配置成功!");
254+
} else {
255+
exportTxt.setText("导出失败,请检查写入权限!");
256+
ToastUtils.show("导出失败,请检查写入权限!");
257+
}
258+
});
259+
260+
//导入
261+
importBtn.setOnClickListener(v -> {
262+
try {
263+
String responseStr = FileUtils.readFileI(backupPath, backupFile);
264+
if (TextUtils.isEmpty(responseStr)) {
265+
ToastUtils.show(getString(R.string.tips_get_info_failed));
266+
return;
267+
}
268+
269+
CloneInfoVo cloneInfoVo = JSON.parseObject(responseStr, CloneInfoVo.class);
270+
Log.d(TAG, Objects.requireNonNull(cloneInfoVo).toString());
271+
272+
if (!SettingUtil.getVersionName().equals(cloneInfoVo.getVersionName())) {
273+
ToastUtils.show(getString(R.string.tips_versions_inconsistent));
274+
return;
275+
}
276+
277+
if (CloneUtils.restoreSettings(cloneInfoVo)) {
278+
ToastUtils.show(getString(R.string.tips_clone_done));
279+
} else {
280+
ToastUtils.show(getString(R.string.tips_clone_failed));
281+
}
282+
283+
} catch (Exception e) {
284+
e.printStackTrace();
285+
importTxt.setText("还原失败:" + e.getMessage());
286+
}
287+
});
288+
229289
}
230290

231291
@SuppressLint("SetTextI18n")
@@ -238,82 +298,4 @@ protected void onResume() {
238298
ipText.setText(getString(R.string.local_ip) + serverIp);
239299
}
240300

241-
/**
242-
* 文件下载
243-
*
244-
* @param url 下载链接
245-
*/
246-
public void downloadFile(String url, final String destFileDir, final String destFileName, final String cloneInfo) {
247-
ProgressDialog progressDialog = new ProgressDialog(context);
248-
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
249-
progressDialog.setTitle(getString(R.string.tips_downloading));
250-
progressDialog.setMessage(getString(R.string.tips_please_wait));
251-
progressDialog.setProgress(0);
252-
progressDialog.setMax(100);
253-
progressDialog.show();
254-
progressDialog.setCancelable(false);
255-
DownloadUtil.get().download(url, destFileDir, destFileName, new DownloadUtil.OnDownloadListener() {
256-
@Override
257-
public void onDownloadSuccess(File file) {
258-
if (progressDialog.isShowing()) {
259-
Toast(handError, TAG, getString(R.string.tips_download_done));
260-
progressDialog.dismiss();
261-
}
262-
//下载完成进行相关逻辑操作
263-
Log.d(TAG, file.getPath());
264-
265-
//还原数据库
266-
BackupDbTask task = new BackupDbTask(context);
267-
String backup_version = task.doInBackground(BackupDbTask.COMMAND_RESTORE);
268-
Log.d(TAG, "backup_version = " + backup_version);
269-
270-
//应用配置
271-
CloneInfoVo cloneInfoVo = JSON.parseObject(cloneInfo, CloneInfoVo.class);
272-
System.out.println(cloneInfoVo.toString());
273-
SettingUtil.init(context);
274-
SettingUtil.switchEnableSms(cloneInfoVo.isEnableSms());
275-
SettingUtil.switchEnablePhone(cloneInfoVo.isEnablePhone());
276-
SettingUtil.switchCallType1(cloneInfoVo.isCallType1());
277-
SettingUtil.switchCallType2(cloneInfoVo.isCallType2());
278-
SettingUtil.switchCallType3(cloneInfoVo.isCallType3());
279-
SettingUtil.switchEnableAppNotify(cloneInfoVo.isEnableAppNotify());
280-
SettingUtil.switchCancelAppNotify(cloneInfoVo.isCancelAppNotify());
281-
SettingUtil.smsHubApiUrl(cloneInfoVo.getSmsHubApiUrl());
282-
SettingUtil.setBatteryLevelAlarmMin(cloneInfoVo.getBatteryLevelAlarmMin());
283-
SettingUtil.setBatteryLevelAlarmMax(cloneInfoVo.getBatteryLevelAlarmMax());
284-
SettingUtil.switchBatteryLevelAlarmOnce(cloneInfoVo.isBatteryLevelAlarmOnce());
285-
SettingUtil.setRetryTimes(cloneInfoVo.getRetryTimes());
286-
SettingUtil.setDelayTime(cloneInfoVo.getDelayTime());
287-
SettingUtil.switchSmsTemplate(cloneInfoVo.isEnableSmsTemplate());
288-
SettingUtil.setSmsTemplate(cloneInfoVo.getSmsTemplate());
289-
290-
Toast(handError, TAG, getString(R.string.tips_clone_done));
291-
}
292-
293-
@Override
294-
public void onDownloading(int progress) {
295-
progressDialog.setProgress(progress);
296-
}
297-
298-
@SuppressLint("SetTextI18n")
299-
@Override
300-
public void onDownloadFailed(Exception e) {
301-
//下载异常进行相关提示操作
302-
Log.e(TAG, getString(R.string.tips_download_failed) + e.getMessage());
303-
Toast(handError, TAG, getString(R.string.tips_download_failed) + e.getMessage());
304-
}
305-
});
306-
}
307-
308-
public static void Toast(Handler handError, String Tag, String data) {
309-
Log.i(Tag, data);
310-
if (handError != null) {
311-
Message msg = new Message();
312-
msg.what = TOAST;
313-
Bundle bundle = new Bundle();
314-
bundle.putString("DATA", data);
315-
msg.setData(bundle);
316-
handError.sendMessage(msg);
317-
}
318-
}
319301
}

app/src/main/java/com/idormy/sms/forwarder/model/vo/CloneInfoVo.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22

33
import androidx.annotation.NonNull;
44

5+
import com.idormy.sms.forwarder.model.RuleModel;
6+
import com.idormy.sms.forwarder.model.SenderModel;
7+
58
import java.io.Serializable;
9+
import java.util.List;
610

711
import lombok.Getter;
812
import lombok.Setter;
@@ -28,7 +32,8 @@ public class CloneInfoVo implements Serializable {
2832
private int delayTime;
2933
private boolean enableSmsTemplate;
3034
private String smsTemplate;
31-
private String backupVersion;
35+
private List<SenderModel> senderList;
36+
private List<RuleModel> ruleList;
3237

3338
@NonNull
3439
@Override
@@ -51,7 +56,8 @@ public String toString() {
5156
", delayTime=" + delayTime +
5257
", enableSmsTemplate=" + enableSmsTemplate +
5358
", smsTemplate=" + smsTemplate +
54-
", backupVersion=" + backupVersion +
59+
", senderList=" + senderList.toString() +
60+
", ruleList=" + ruleList.toString() +
5561
'}';
5662
}
5763
}

0 commit comments

Comments
 (0)