吉安感知网项目-前端
罗广辉
2026-02-06 dfc3ee25d81398711bf5076ec5def7b38481a6f0
feat: 保活
3 files modified
341 ■■■■■ changed files
uniapps/work-app/src/App.vue 16 ●●●●● patch | view | raw | blame | history
uniapps/work-app/src/manifest.json 223 ●●●● 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
@@ -1,112 +1,115 @@
{
    "name" : "吉安低空",
    "appid" : "__UNI__FFA6B4D",
    "description" : "",
    "versionName" : "1.0.1",
    "versionCode" : 101,
    "transformPx" : false,
    /* 5+App特有相关 */
    "app-plus" : {
        "orientation" : [
            //竖屏正方向
            "portrait-primary",
            //竖屏反方向
            "portrait-secondary",
            //横屏正方向
            "landscape-primary",
            //横屏反方向
            "landscape-secondary",
            //自然方向
            "default"
        ],
        "usingComponents" : true,
        "nvueStyleCompiler" : "uni-app",
        "compilerVersion" : 3,
        "splashscreen" : {
            "alwaysShowBeforeRender" : true,
            "waiting" : true,
            "autoclose" : true,
            "delay" : 0
        },
        /* 模块配置 */
        "modules" : {
            "Share" : {}
        },
        /* 应用发布信息 */
        "distribute" : {
            /* android打包配置 */
            "android" : {
                "permissions" : [
                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
                    "<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\" />"
                ]
            },
            /* ios打包配置 */
            "ios" : {
                "dSYMs" : false
            },
            /* SDK配置 */
            "sdkConfigs" : {
                "share" : {
                    "weixin" : {
                        "appid" : "gh_f2fbbd1d5d2a",
                        "UniversalLinks" : ""
                    }
                }
            },
            "icons" : {
                "android" : {
                    "hdpi" : "src/static/images/app-logo.png",
                    "xhdpi" : "src/static/images/app-logo.png",
                    "xxhdpi" : "src/static/images/app-logo.png",
                    "xxxhdpi" : "src/static/images/app-logo.png"
                }
            }
        },
        "nativePlugins" : {}
    },
    /* 快应用特有相关 */
    "quickapp" : {},
    /* 小程序特有相关 */
    "mp-weixin" : {
        "appid" : "wx05742eafb412a57a",
        "setting" : {
            "urlCheck" : false
        },
        "usingComponents" : true
    },
    "mp-alipay" : {
        "usingComponents" : true
    },
    "mp-baidu" : {
        "usingComponents" : true
    },
    "mp-toutiao" : {
        "usingComponents" : true
    },
    "uniStatistics" : {
        "enable" : false
    },
    "vueVersion" : "3",
    "h5" : {
        "router" : {
            "mode" : "hash",
            "base" : "/work-app/"
        }
    }
    "name": "吉安低空",
    "appid": "__UNI__FFA6B4D",
    "description": "",
    "versionName": "1.0.1",
    "versionCode": 101,
    "transformPx": false,
    /* 5+App特有相关 */
    "app-plus": {
        "orientation": [
            //竖屏正方向
            "portrait-primary",
            //竖屏反方向
            "portrait-secondary",
            //横屏正方向
            "landscape-primary",
            //横屏反方向
            "landscape-secondary",
            //自然方向
            "default"
        ],
        "usingComponents": true,
        "nvueStyleCompiler": "uni-app",
        "compilerVersion": 3,
        "splashscreen": {
            "alwaysShowBeforeRender": true,
            "waiting": true,
            "autoclose": true,
            "delay": 0
        },
        /* 模块配置 */
        "modules": {
            "Share": {}
        },
        /* 应用发布信息 */
        "distribute": {
            /* android打包配置 */
            "android": {
                "permissions": [
                    "<uses-permission android:name=\"android.permission.CHANGE_NETWORK_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
                    "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
                    "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
                    "<uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\"/>",
                    "<uses-feature android:name=\"android.hardware.camera.autofocus\"/>",
                    "<uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.CAMERA\"/>",
                    "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
                    "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
                    "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
                    "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
                    "<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.FOREGROUND_SERVICE\" />",
                    "<uses-permission android:name=\"android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS\" />"
                ]
            },
            /* ios打包配置 */
            "ios": {
                "dSYMs": false
            },
            /* SDK配置 */
            "sdkConfigs": {
                "share": {
                    "weixin": {
                        "appid": "gh_f2fbbd1d5d2a",
                        "UniversalLinks": ""
                    }
                }
            },
            "icons": {
                "android": {
                    "hdpi": "src/static/images/app-logo.png",
                    "xhdpi": "src/static/images/app-logo.png",
                    "xxhdpi": "src/static/images/app-logo.png",
                    "xxxhdpi": "src/static/images/app-logo.png"
                }
            }
        },
        "nativePlugins": {}
    },
    /* 快应用特有相关 */
    "quickapp": {},
    /* 小程序特有相关 */
    "mp-weixin": {
        "appid": "wx05742eafb412a57a",
        "setting": {
            "urlCheck": false
        },
        "usingComponents": true
    },
    "mp-alipay": {
        "usingComponents": true
    },
    "mp-baidu": {
        "usingComponents": true
    },
    "mp-toutiao": {
        "usingComponents": true
    },
    "uniStatistics": {
        "enable": false
    },
    "vueVersion": "3",
    "h5": {
        "router": {
            "mode": "hash",
            "base": "/work-app/"
        }
    }
}
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: 生命周期回调已注册");
}