吉安感知网项目-前端
罗广辉
2026-02-06 dfc3ee25d81398711bf5076ec5def7b38481a6f0
feat: 保活
3 files modified
123 ■■■■ changed files
uniapps/work-app/src/App.vue 16 ●●●●● patch | view | raw | blame | history
uniapps/work-app/src/manifest.json 5 ●●●● patch | view | raw | blame | history
uniapps/work-app/src/uni_modules/keep-app/utssdk/app-android/index.uts 102 ●●●●● patch | view | raw | blame | history
uniapps/work-app/src/App.vue
@@ -3,7 +3,7 @@
import { useAppStore, useUserStore, useLocationStore } from '@/store'
import { useGlobalWS } from '@/hooks/useGlobalWS.js'
// #ifdef APP-PLUS
import { keepAliveStart } from '@/uni_modules/keep-app'
import { keepAliveStart, requestIgnoreBatteryOptimization } from '@/uni_modules/keep-app'
// #endif
const appStore = useAppStore()
@@ -11,8 +11,8 @@
const locationStore = useLocationStore()
// #ifdef APP-PLUS
import { getBatteryCapacity } from '@/uni_modules/lgh-getbatteryinfo'
console.log('电池电量:', getBatteryCapacity())
// import { getBatteryCapacity } from '@/uni_modules/lgh-getbatteryinfo'
// console.log('电池电量:', getBatteryCapacity())
// #endif
const valuetest = ref(1)
@@ -20,11 +20,10 @@
    setInterval(() => {
        valuetest.value = valuetest.value + 1
        console.log('valuetest.value:', valuetest.value)
        uni.showToast({title: valuetest.value, icon: 'none'});
        uni.showToast({ title: valuetest.value, icon: 'none' })
    }, 1000)
}
tests()
useGlobalWS()
onShow(async () => {
@@ -38,7 +37,6 @@
        }
    }
})
tests()
onHide(() => {
    console.log('App Hide')
@@ -53,6 +51,10 @@
    appStore.initSystemInfo()
    // #ifdef APP-PLUS
    keepAliveStart()
    // 请求用户允许忽略电池优化(重要:用于保活)
    setTimeout(() => {
        requestIgnoreBatteryOptimization()
    }, 2000)
    // #endif
    if (!userStore.userInfo) {
        //不存在则跳转至登录页
uniapps/work-app/src/manifest.json
@@ -53,7 +53,9 @@
                    "<uses-feature android:name=\"android.hardware.camera\"/>",
                    "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>",
                    "<uses-permission android:name=\"android.permission.RECORD_AUDIO\" />",
                    "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />"
                    "<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />",
                    "<uses-permission android:name=\"android.permission.FOREGROUND_SERVICE\" />",
                    "<uses-permission android:name=\"android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS\" />"
                ]
            },
            /* ios打包配置 */
@@ -110,3 +112,4 @@
        }
    }
}
uniapps/work-app/src/uni_modules/keep-app/utssdk/app-android/index.uts
@@ -8,8 +8,6 @@
import NotificationManager from "android.app.NotificationManager";
import Notification from "android.app.Notification";
import PendingIntent from "android.app.PendingIntent";
import Service from "android.app.Service";
import IBinder from "android.os.IBinder";
import PowerManager from "android.os.PowerManager";
import BatteryManager from "android.os.BatteryManager";
import { UTSAndroid } from "io.dcloud.uts";
@@ -21,9 +19,12 @@
// 保活服务是否已启动的标志
let isKeepAliveRunning = false;
// WakeLock 引用,用于保持 CPU 运行
let wakeLock: PowerManager.WakeLock | null = null;
/**
 * 启动应用保活
 * 通过启动前台服务来保持应用在后台运行
 * 通过 WakeLock + 通知来保持应用在后台运行
 */
export function keepAliveStart(): void {
    const context = UTSAndroid.getAppContext();
@@ -38,14 +39,20 @@
    }
    try {
        // 创建通知渠道 (Android 8.0+)
        // 1. 获取 WakeLock 唤醒锁,保持 CPU 运行
        acquireWakeLock(context);
        // 2. 创建通知渠道 (Android 8.0+)
        createNotificationChannel(context);
        // 创建并显示前台通知
        // 3. 创建并显示前台通知
        showForegroundNotification(context);
        // 4. 注册应用生命周期监听
        registerLifecycleCallbacks();
        isKeepAliveRunning = true;
        console.log("keepAliveStart: 保活服务启动成功");
        console.log("keepAliveStart: 保活服务启动成功(WakeLock已获取)");
    } catch (e) {
        console.error("keepAliveStart: 启动失败", e);
    }
@@ -61,12 +68,15 @@
    }
    try {
        // 释放 WakeLock
        releaseWakeLock();
        // 取消通知
        const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
        notificationManager.cancel(NOTIFICATION_ID);
        isKeepAliveRunning = false;
        console.log("keepAliveStop: 保活服务已停止");
        console.log("keepAliveStop: 保活服务已停止(WakeLock已释放)");
    } catch (e) {
        console.error("keepAliveStop: 停止失败", e);
    }
@@ -210,3 +220,81 @@
    const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
    notificationManager.notify(NOTIFICATION_ID, notification);
}
/**
 * 获取 WakeLock 唤醒锁
 * PARTIAL_WAKE_LOCK: 保持 CPU 运行,屏幕和键盘背光可以关闭
 */
function acquireWakeLock(context: Context): void {
    if (wakeLock != null && wakeLock!.isHeld()) {
        console.log("acquireWakeLock: WakeLock 已持有");
        return;
    }
    try {
        const powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager;
        // PARTIAL_WAKE_LOCK 保持 CPU 运行
        wakeLock = powerManager.newWakeLock(
            PowerManager.PARTIAL_WAKE_LOCK,
            "KeepAlive::WakeLock"
        );
        if (wakeLock != null) {
            // 设置超时时间为无限(传 0 或负数表示无限)
            // 使用 acquire() 无参版本
            wakeLock!.setReferenceCounted(false);
            wakeLock!.acquire();
            console.log("acquireWakeLock: WakeLock 获取成功");
        }
    } catch (e) {
        console.error("acquireWakeLock: WakeLock 获取失败", e);
    }
}
/**
 * 释放 WakeLock 唤醒锁
 */
function releaseWakeLock(): void {
    if (wakeLock != null && wakeLock!.isHeld()) {
        try {
            wakeLock!.release();
            wakeLock = null;
            console.log("releaseWakeLock: WakeLock 已释放");
        } catch (e) {
            console.error("releaseWakeLock: WakeLock 释放失败", e);
        }
    }
}
/**
 * 注册应用生命周期回调
 * 当应用进入后台时,确保 WakeLock 保持持有
 */
function registerLifecycleCallbacks(): void {
    // 应用进入后台时的回调
    UTSAndroid.onAppActivityPause(() => {
        console.log("onAppActivityPause: 应用进入后台");
        // 确保 WakeLock 仍然持有
        const context = UTSAndroid.getAppContext();
        if (context != null && isKeepAliveRunning) {
            if (wakeLock == null || !wakeLock!.isHeld()) {
                acquireWakeLock(context);
            }
        }
    });
    // 应用返回前台时的回调
    UTSAndroid.onAppActivityResume(() => {
        console.log("onAppActivityResume: 应用返回前台");
    });
    // 应用被销毁时的回调
    UTSAndroid.onAppActivityDestroy(() => {
        console.log("onAppActivityDestroy: 应用被销毁");
        // 释放资源
        releaseWakeLock();
        isKeepAliveRunning = false;
    });
    console.log("registerLifecycleCallbacks: 生命周期回调已注册");
}