From a42d6ceec696ee2864e6815f22f40ef6fed51afc Mon Sep 17 00:00:00 2001 From: BBIT-Kai <2911862937@qq.com> Date: Fri, 24 Jul 2026 18:17:06 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=97=A5=E5=BF=97=E9=80=BB?= =?UTF-8?q?=E8=BE=91=EF=BC=9B=E4=BF=AE=E6=94=B9=E9=99=A4=E6=B9=BF=E6=9C=BA?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E9=87=8D=E5=8F=91=E6=8C=87=E4=BB=A4=E7=9A=84?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E9=97=B4=E9=9A=94=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle | 4 +- .../receiver/FrpStartReceiver.java | 9 +- .../ui/activity/SplashActivityPresenter.java | 3 - .../example/iot_controlhost/utils/MyUtil.java | 41 ++++- .../utils/database/LogDBManager.java | 173 +++++++++++------- .../utils/global/RoomController.java | 2 +- .../utils/log/CrashHandlerUtil.java | 3 +- .../iot_controlhost/utils/log/MyLog.java | 18 +- .../iot_controlhost/utils/log/UserLog.java | 27 +-- 9 files changed, 162 insertions(+), 118 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d166a53..ba5e25e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -10,8 +10,8 @@ android { applicationId "com.example.iot_controlhost" minSdkVersion 25 targetSdkVersion 30 - versionCode 161 - versionName "3.5.0.161" + versionCode 163 + versionName "3.5.0.163" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" ndk { moduleName "mcu" diff --git a/app/src/main/java/com/example/iot_controlhost/receiver/FrpStartReceiver.java b/app/src/main/java/com/example/iot_controlhost/receiver/FrpStartReceiver.java index 651cfa5..60c7784 100644 --- a/app/src/main/java/com/example/iot_controlhost/receiver/FrpStartReceiver.java +++ b/app/src/main/java/com/example/iot_controlhost/receiver/FrpStartReceiver.java @@ -14,19 +14,20 @@ import com.xuexiang.rxutil2.rxbus.RxBusUtils; public class FrpStartReceiver extends BroadcastReceiver { @Override public void onReceive(Context mContext, Intent intent) { - if (intent.getAction().equals("receiver_frp_version")) { + String action = intent == null ? null : intent.getAction(); + if ("receiver_frp_version".equals(action)) { int frpVersion = intent.getIntExtra("version", 0); MyLog.frp("收到FRP版本:" + frpVersion); MMKVUtil.put(HardwareSetting.FRP_VERSION, frpVersion); - } else if (intent.getAction().equals("receiver_start_frp")) { + } else if ("receiver_start_frp".equals(action)) { if (intent.getBooleanExtra("start_frp", false)) { MyLog.frp("收到启动FRP指令"); MyUtil.relaunchFrp(); } - } else if (intent.getAction().equals("receiver_frp_info")) { + } else if ("receiver_frp_info".equals(action)) { String info = intent.getStringExtra("info"); MyLog.frp(info); RxBusUtils.get().post(RxTag.UPDATE_MAIN_MSG, info); } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/example/iot_controlhost/ui/activity/SplashActivityPresenter.java b/app/src/main/java/com/example/iot_controlhost/ui/activity/SplashActivityPresenter.java index 86130f1..d211ab7 100644 --- a/app/src/main/java/com/example/iot_controlhost/ui/activity/SplashActivityPresenter.java +++ b/app/src/main/java/com/example/iot_controlhost/ui/activity/SplashActivityPresenter.java @@ -25,7 +25,6 @@ import com.example.iot_controlhost.utils.database.dynamicSensor.IndoorAmmoniaSen import com.example.iot_controlhost.utils.database.dynamicSensor.IndoorCO2SensorUtil; import com.example.iot_controlhost.utils.database.dynamicSensor.IndoorFloorTSensorUtil; import com.example.iot_controlhost.utils.database.dynamicSensor.IndoorTHSensorUtil; -import com.example.iot_controlhost.utils.database.LogDBManager; import com.example.iot_controlhost.utils.global.AutoModelSet; import com.example.iot_controlhost.utils.global.HardwareSetting; import com.example.iot_controlhost.utils.global.RoomController; @@ -261,8 +260,6 @@ public class SplashActivityPresenter extends BasePresenter { public void onGranted(@NonNull List permissions, boolean allGranted) { if (allGranted) { processLiveData.postValue(new ProcessInfo(100, "系统启动成功")); - // 索引首次创建可能较慢,放在启动完成后后台执行,不阻塞启动页。 - LogDBManager.prepareAsync(); MyLog.app("系统启动成功"); } else { MyLog.appError("获取部分权限成功,但部分权限未正常授予"); diff --git a/app/src/main/java/com/example/iot_controlhost/utils/MyUtil.java b/app/src/main/java/com/example/iot_controlhost/utils/MyUtil.java index d368007..65867bb 100644 --- a/app/src/main/java/com/example/iot_controlhost/utils/MyUtil.java +++ b/app/src/main/java/com/example/iot_controlhost/utils/MyUtil.java @@ -466,17 +466,38 @@ public class MyUtil { } - public static void relaunchFrp(){ - Context mContext = ActivityUtils.getTopActivity(); - Intent intent = new Intent(); - intent.setAction("receiver_control"); - intent.putExtra("control", -1); - mContext.sendBroadcast(intent); - // 等待2sFRP关闭,然后重启 + public static void relaunchFrp() { + Context context = ActivityUtils.getTopActivity(); + if (context == null) { + context = MyApp.getAppContext(); + } + if (context == null) { + MyLog.frpError("启动FRP失败:无法获取应用上下文"); + return; + } + Context launchContext = context; + try { + Intent stopIntent = new Intent("receiver_control"); + stopIntent.putExtra("control", -1); + launchContext.sendBroadcast(stopIntent); + } catch (Exception e) { + MyLog.frpError("发送FRP停止指令失败:" + e.getMessage()); + } + // 等待2s让FRP释放资源,然后重新启动。 RxJavaUtils.delay(2, aLong -> { - Intent intent2 = mContext.getPackageManager().getLaunchIntentForPackage("com.bbitcn.bbit_frp2"); - intent2.putExtra("host_id", HardwareSetting.getHostId()); - mContext.startActivity(intent2); + try { + Intent launchIntent = launchContext.getPackageManager() + .getLaunchIntentForPackage("com.bbitcn.bbit_frp2"); + if (launchIntent == null) { + MyLog.frpError("启动FRP失败:未找到远程协助应用"); + return; + } + launchIntent.putExtra("host_id", HardwareSetting.getHostId()); + launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + launchContext.startActivity(launchIntent); + } catch (Exception e) { + MyLog.frpError("启动FRP失败:" + e.getMessage()); + } }); } } diff --git a/app/src/main/java/com/example/iot_controlhost/utils/database/LogDBManager.java b/app/src/main/java/com/example/iot_controlhost/utils/database/LogDBManager.java index 6dec73b..974186f 100644 --- a/app/src/main/java/com/example/iot_controlhost/utils/database/LogDBManager.java +++ b/app/src/main/java/com/example/iot_controlhost/utils/database/LogDBManager.java @@ -1,5 +1,7 @@ package com.example.iot_controlhost.utils.database; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; import android.util.Log; import com.example.iot_controlhost.MyApp; @@ -8,7 +10,6 @@ import com.example.iot_controlhost.utils.log.MyLog; import com.example.iot_controlhost.utils.log.UserLog; import org.greenrobot.greendao.query.QueryBuilder; -import org.greenrobot.greendao.query.WhereCondition; import java.util.Calendar; import java.util.Collections; @@ -16,8 +17,11 @@ import java.util.Date; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; -import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; /** * 日志数据库访问入口。 @@ -30,15 +34,14 @@ public final class LogDBManager { private static final String LOGCAT_TAG = "LogDBManager"; private static final int PAGE_SIZE = 20; private static final int RETENTION_DAYS = 15; - private static final String CREATE_DATETIME_INDEX = - "CREATE INDEX IF NOT EXISTS IDX_LOG_DATETIME_ID ON LOG (DATETIME DESC, _id DESC)"; - private static final String CREATE_TAG_DATETIME_INDEX = - "CREATE INDEX IF NOT EXISTS IDX_LOG_TAG_DATETIME_ID ON LOG (TAG, DATETIME DESC, _id DESC)"; + private static final int CLEANUP_BATCH_SIZE = 500; + private static final long CLEANUP_BATCH_DELAY_MS = 30L; + private static final long SYNC_WAIT_SECONDS = 10L; private static volatile Thread databaseThread; - private static volatile boolean indexesReady; + private static final AtomicBoolean CLEANUP_RUNNING = new AtomicBoolean(false); - private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor(runnable -> { + private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor(runnable -> { Thread thread = new Thread(() -> { databaseThread = Thread.currentThread(); runnable.run(); @@ -52,13 +55,6 @@ public final class LogDBManager { private LogDBManager() { } - /** - * 后台准备日志索引。首次升级可能需要一定时间,但不会阻塞应用启动流程。 - */ - public static void prepareAsync() { - EXECUTOR.execute(LogDBManager::ensureIndexes); - } - /** * 异步增加普通诊断日志。 */ @@ -67,10 +63,15 @@ public final class LogDBManager { } /** - * 同步落库,供需要确保“本地成功后再上传”的用户日志使用。 + * 异步落库并回调结果。回调在日志数据库线程执行,不允许执行耗时或UI操作。 */ - public static boolean insertLogSync(com.example.iot_controlhost.model.Log log) { - return executeSync(() -> insertInternal(log), false); + public static void insertLog(com.example.iot_controlhost.model.Log log, InsertCallback callback) { + EXECUTOR.execute(() -> { + boolean saved = insertInternal(log); + if (callback != null) { + callback.onComplete(saved); + } + }); } private static boolean insertInternal(com.example.iot_controlhost.model.Log log) { @@ -108,18 +109,13 @@ public final class LogDBManager { private static List queryPage( String filter, com.example.iot_controlhost.model.Log cursor) { return executeSync(() -> { - ensureIndexes(); QueryBuilder qb = LOG_DAO.queryBuilder(); List tags = UserLog.getStorageTagsForFilter(filter); qb.where(LogDao.Properties.Tag.in(tags)); - if (cursor != null) { - WhereCondition olderDate = LogDao.Properties.Datetime.lt(cursor.getDatetime()); - WhereCondition sameDateAndOlderId = qb.and( - LogDao.Properties.Datetime.eq(cursor.getDatetime()), - LogDao.Properties.Id.lt(cursor.getId())); - qb.where(qb.or(olderDate, sameDateAndOlderId)); + if (cursor != null && cursor.getId() != null) { + qb.where(LogDao.Properties.Id.lt(cursor.getId())); } - return qb.orderDesc(LogDao.Properties.Datetime, LogDao.Properties.Id) + return qb.orderDesc(LogDao.Properties.Id) .limit(PAGE_SIZE) .list(); }, Collections.emptyList()); @@ -130,10 +126,9 @@ public final class LogDBManager { */ public static List queryList(String filter, int currentPage) { return executeSync(() -> { - ensureIndexes(); return LOG_DAO.queryBuilder() .where(LogDao.Properties.Tag.in(UserLog.getStorageTagsForFilter(filter))) - .orderDesc(LogDao.Properties.Datetime, LogDao.Properties.Id) + .orderDesc(LogDao.Properties.Id) .offset(Math.max(0, currentPage - 1) * PAGE_SIZE) .limit(PAGE_SIZE) .list(); @@ -142,10 +137,9 @@ public final class LogDBManager { public static List queryDateRange(Date startDate, Date endDate) { return executeSync(() -> { - ensureIndexes(); return LOG_DAO.queryBuilder() .where(LogDao.Properties.Datetime.between(startDate, endDate)) - .orderDesc(LogDao.Properties.Datetime, LogDao.Properties.Id) + .orderDesc(LogDao.Properties.Id) .list(); }, Collections.emptyList()); } @@ -155,7 +149,6 @@ public final class LogDBManager { */ public static List queryAllList() { return executeSync(() -> { - ensureIndexes(); Calendar calendar = Calendar.getInstance(); Date currentDate = calendar.getTime(); calendar.add(Calendar.DAY_OF_YEAR, -7); @@ -167,7 +160,7 @@ public final class LogDBManager { MyLog.TAG_APP + MyLog.TAG_ERROR, MyLog.TAG_NETWORK, MyLog.TAG_NETWORK + MyLog.TAG_ERROR)) - .orderDesc(LogDao.Properties.Datetime, LogDao.Properties.Id) + .orderDesc(LogDao.Properties.Id) .list(); }, Collections.emptyList()); } @@ -198,48 +191,68 @@ public final class LogDBManager { } /** - * 每日后台清理十五天前的日志。 + * 每日后台分批清理十五天前的日志。每批之间主动让出数据库线程, + * 避免巨量历史数据形成大事务或长时间独占SQLite连接。 */ public static void clearExpiredLogsAsync() { - EXECUTOR.execute(() -> { - long start = System.currentTimeMillis(); - ensureIndexes(); - Calendar calendar = Calendar.getInstance(); - calendar.add(Calendar.DAY_OF_YEAR, -RETENTION_DAYS); - Date cutoff = calendar.getTime(); - try { - long count = LOG_DAO.queryBuilder() - .where(LogDao.Properties.Datetime.lt(cutoff)) - .count(); - if (count > 0) { - LOG_DAO.queryBuilder() - .where(LogDao.Properties.Datetime.lt(cutoff)) - .buildDelete() - .executeDeleteWithoutDetachingEntities(); - LOG_DAO.detachAll(); - } - long duration = System.currentTimeMillis() - start; - MyLog.app("日志维护完成:保留" + RETENTION_DAYS + "天,清理" + count - + "条,耗时" + duration + "ms"); - } catch (Exception e) { - Log.e(LOGCAT_TAG, "清理过期日志失败", e); - } - }); - } - - private static void ensureIndexes() { - if (indexesReady) { + if (!CLEANUP_RUNNING.compareAndSet(false, true)) { + Log.i(LOGCAT_TAG, "日志清理任务已在执行,本次跳过"); return; } + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DAY_OF_YEAR, -RETENTION_DAYS); + CleanupState state = new CleanupState(calendar.getTimeInMillis(), System.currentTimeMillis()); + EXECUTOR.execute(() -> clearNextBatch(state)); + } + + private static void clearNextBatch(CleanupState state) { try { - LOG_DAO.getDatabase().execSQL(CREATE_DATETIME_INDEX); - LOG_DAO.getDatabase().execSQL(CREATE_TAG_DATETIME_INDEX); - indexesReady = true; + SQLiteDatabase database = getRawDatabase(); + Batch batch = findExpiredBatch(database, state.lastId, state.cutoffMillis); + if (batch.count == 0) { + LOG_DAO.detachAll(); + CLEANUP_RUNNING.set(false); + long duration = System.currentTimeMillis() - state.startMillis; + MyLog.app("日志维护完成:保留" + RETENTION_DAYS + "天,分批清理" + + state.deletedCount + "条,耗时" + duration + "ms"); + return; + } + + database.execSQL( + "DELETE FROM LOG WHERE _id > ? AND _id <= ? AND DATETIME < ?", + new Object[]{state.lastId, batch.lastId, state.cutoffMillis}); + state.lastId = batch.lastId; + state.deletedCount += batch.count; + EXECUTOR.schedule(() -> clearNextBatch(state), CLEANUP_BATCH_DELAY_MS, TimeUnit.MILLISECONDS); } catch (Exception e) { - Log.e(LOGCAT_TAG, "创建日志索引失败", e); + CLEANUP_RUNNING.set(false); + Log.e(LOGCAT_TAG, "分批清理过期日志失败", e); } } + private static Batch findExpiredBatch(SQLiteDatabase database, long lastId, long cutoffMillis) { + long batchLastId = lastId; + int count = 0; + String sql = "SELECT _id FROM LOG WHERE _id > ? AND DATETIME < ? ORDER BY _id LIMIT " + + CLEANUP_BATCH_SIZE; + try (Cursor cursor = database.rawQuery(sql, + new String[]{String.valueOf(lastId), String.valueOf(cutoffMillis)})) { + while (cursor.moveToNext()) { + batchLastId = cursor.getLong(0); + count++; + } + } + return new Batch(batchLastId, count); + } + + private static SQLiteDatabase getRawDatabase() { + Object rawDatabase = LOG_DAO.getDatabase().getRawDatabase(); + if (!(rawDatabase instanceof SQLiteDatabase)) { + throw new IllegalStateException("日志数据库类型不受支持:" + rawDatabase); + } + return (SQLiteDatabase) rawDatabase; + } + private static T executeSync(Callable task, T fallback) { if (Thread.currentThread() == databaseThread) { try { @@ -250,13 +263,41 @@ public final class LogDBManager { } } try { - return EXECUTOR.submit(task).get(); + return EXECUTOR.submit(task).get(SYNC_WAIT_SECONDS, TimeUnit.SECONDS); } catch (InterruptedException e) { Thread.currentThread().interrupt(); Log.e(LOGCAT_TAG, "等待日志数据库操作时被中断", e); } catch (ExecutionException e) { Log.e(LOGCAT_TAG, "日志数据库操作失败", e.getCause()); + } catch (TimeoutException e) { + Log.e(LOGCAT_TAG, "等待日志数据库操作超时", e); } return fallback; } + + public interface InsertCallback { + void onComplete(boolean saved); + } + + private static final class CleanupState { + private final long cutoffMillis; + private final long startMillis; + private long lastId; + private long deletedCount; + + private CleanupState(long cutoffMillis, long startMillis) { + this.cutoffMillis = cutoffMillis; + this.startMillis = startMillis; + } + } + + private static final class Batch { + private final long lastId; + private final int count; + + private Batch(long lastId, int count) { + this.lastId = lastId; + this.count = count; + } + } } diff --git a/app/src/main/java/com/example/iot_controlhost/utils/global/RoomController.java b/app/src/main/java/com/example/iot_controlhost/utils/global/RoomController.java index ef7affa..0cd77d1 100644 --- a/app/src/main/java/com/example/iot_controlhost/utils/global/RoomController.java +++ b/app/src/main/java/com/example/iot_controlhost/utils/global/RoomController.java @@ -298,7 +298,7 @@ public class RoomController { // 检查除湿机功率是否与除湿机物理电源状态匹配,时刻监测当前除湿机功率状态,使之与软件开关匹配 // 防止出现软件界面中开启除湿器但实际上除湿器未开启(功率不足100W)的情况 if (RoomController.dehumidifier.isAvailable() || RoomController.dehumidifier485Relay.isAvailable()) { - PollingTask.getInstance().startPollingTaskOnIOThread(RxTag.TAG_DEHUMIDIFIER_STATUS, 60, () -> { + PollingTask.getInstance().startPollingTaskOnIOThread(RxTag.TAG_DEHUMIDIFIER_STATUS, 60 * 5, () -> { if (RoomController.dehumidifier.isAvailable() && RoomController.dehumidifier.isPowerSupply() && RoomController.dehumidifier.getPower() < 100) { MyLog.controllerError("除湿机电源已开启但功率不足100W,现尝试再次开启除湿机红外电源");//红外开关是一样的指令 所以这里等于是重新发送 MyQueue.getInstance(MyQueue.TYPE_CONTROLLER).addTask(new QueueIOTask(() -> RoomController.dehumidifier.setPowerSupply(true))); diff --git a/app/src/main/java/com/example/iot_controlhost/utils/log/CrashHandlerUtil.java b/app/src/main/java/com/example/iot_controlhost/utils/log/CrashHandlerUtil.java index 122d77b..f90ef5c 100644 --- a/app/src/main/java/com/example/iot_controlhost/utils/log/CrashHandlerUtil.java +++ b/app/src/main/java/com/example/iot_controlhost/utils/log/CrashHandlerUtil.java @@ -35,11 +35,12 @@ public class CrashHandlerUtil implements Thread.UncaughtExceptionHandler { public void uncaughtException(Thread thread, Throwable ex) { ex.printStackTrace(); MyLog.appError("软件已崩溃,重启应用:" + getFormattedException(ex)); - UserLog.systemErrorImmediately("程序运行异常,系统将自动重启"); + // 先启动重启保护,任何日志或数据库异常都不能阻断恢复流程。 new Thread(() -> { try { Thread.sleep(500); } catch (Exception ignored) { } ProcessPhoenix.triggerRebirth(mContext); }).start(); + UserLog.systemErrorImmediately("程序运行异常,系统将自动重启"); } diff --git a/app/src/main/java/com/example/iot_controlhost/utils/log/MyLog.java b/app/src/main/java/com/example/iot_controlhost/utils/log/MyLog.java index c4e398a..0d261a6 100644 --- a/app/src/main/java/com/example/iot_controlhost/utils/log/MyLog.java +++ b/app/src/main/java/com/example/iot_controlhost/utils/log/MyLog.java @@ -8,8 +8,6 @@ import static com.example.iot_controlhost.utils.log.UserLog.TAG_USER_TASK; import android.util.Log; import com.example.iot_controlhost.utils.database.LogDBManager; -import com.xuexiang.rxutil2.rxjava.RxJavaUtils; -import com.xuexiang.rxutil2.rxjava.task.RxIOTask; import java.util.ArrayList; import java.util.Collections; @@ -152,19 +150,13 @@ public class MyLog extends Timber.Tree { @Override protected void log(int priority, String tag, String message, Throwable t) { // 不处理UserLog日志 - if (tag.contains(TAG_USER_OPERATE) || tag.contains(TAG_USER_SENSOR) || tag.contains(TAG_USER_TASK) || tag.contains(TAG_USER_SYSTEM)) { + if (tag == null || tag.contains(TAG_USER_OPERATE) || tag.contains(TAG_USER_SENSOR) + || tag.contains(TAG_USER_TASK) || tag.contains(TAG_USER_SYSTEM)) { return; } - RxJavaUtils.doInIOThread(new RxIOTask<>(null) { - @Override - public Void doInIOThread(Object o) { - //输出日志到控制台 - Log.println(priority, tag, message); - //保存日志到数据库 - LogDBManager.insertLog(new com.example.iot_controlhost.model.Log(tag, priority, new Date(), message)); - return null; - } - }); + // 控制台立即输出,数据库写入由日志单线程异步处理,避免重复切换IO线程。 + Log.println(priority, tag, message); + LogDBManager.insertLog(new com.example.iot_controlhost.model.Log(tag, priority, new Date(), message)); } } diff --git a/app/src/main/java/com/example/iot_controlhost/utils/log/UserLog.java b/app/src/main/java/com/example/iot_controlhost/utils/log/UserLog.java index 1e95688..69ccb25 100644 --- a/app/src/main/java/com/example/iot_controlhost/utils/log/UserLog.java +++ b/app/src/main/java/com/example/iot_controlhost/utils/log/UserLog.java @@ -3,11 +3,7 @@ package com.example.iot_controlhost.utils.log; import android.util.Log; import com.example.iot_controlhost.utils.database.LogDBManager; -import com.example.iot_controlhost.utils.global.RxTag; import com.example.iot_controlhost.utils.network.TopicClass; -import com.xuexiang.rxutil2.rxbus.RxBusUtils; -import com.xuexiang.rxutil2.rxjava.RxJavaUtils; -import com.xuexiang.rxutil2.rxjava.task.RxIOTask; import java.util.ArrayList; import java.util.Arrays; @@ -142,7 +138,7 @@ public class UserLog extends Timber.Tree { } /** - * 崩溃场景使用同步入口,确保进程重启前日志已经落库。 + * 崩溃场景使用非阻塞入口,防止数据库繁忙时阻断进程重启。 */ public static void systemErrorImmediately(String msg) { persistAndUpload(TAG_USER_SYSTEM + MyLog.TAG_ERROR, Log.ERROR, msg, new Date()); @@ -158,13 +154,7 @@ public class UserLog extends Timber.Tree { if (tag == null || !isUserLogTag(tag)) { return; } - RxJavaUtils.doInIOThread(new RxIOTask<>(null) { - @Override - public Void doInIOThread(Object o) { - persistAndUpload(tag, priority, message, new Date()); - return null; - } - }); + persistAndUpload(tag, priority, message, new Date()); } private static boolean isUserLogTag(String tag) { @@ -177,13 +167,14 @@ public class UserLog extends Timber.Tree { private static void persistAndUpload(String tag, int priority, String message, Date datetime) { com.example.iot_controlhost.model.Log entry = new com.example.iot_controlhost.model.Log(tag, priority, datetime, message); - boolean saved = LogDBManager.insertLogSync(entry); Log.println(priority, tag, message); - if (!saved) { - Log.e(TAG_USER_SYSTEM, "用户日志本地落库失败,已取消上传以避免两端数据不一致"); - return; - } - TopicClass.uploadLog(toServerTag(tag), toServerPriority(tag), message, datetime); + LogDBManager.insertLog(entry, saved -> { + if (!saved) { + Log.e(TAG_USER_SYSTEM, "用户日志本地落库失败,已取消上传以避免两端数据不一致"); + return; + } + TopicClass.uploadLog(toServerTag(tag), toServerPriority(tag), message, datetime); + }); } private static int toServerTag(String tag) {