吉安感知网项目-前端
罗广辉
2026-02-06 89d9aa92065652753d7c54d3c4fc880744377c69
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
// index.uts - Android 应用保活插件
 
// 引用 Android API
import Context from "android.content.Context";
import Intent from "android.content.Intent";
import Build from "android.os.Build";
import NotificationChannel from "android.app.NotificationChannel";
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";
 
// 保活服务的通知渠道ID
const CHANNEL_ID = "keep_alive_channel";
const NOTIFICATION_ID: Int = 1001;
 
// 保活服务是否已启动的标志
let isKeepAliveRunning = false;
 
/**
 * 启动应用保活
 * 通过启动前台服务来保持应用在后台运行
 */
export function keepAliveStart(): void {
    const context = UTSAndroid.getAppContext();
    if (context == null) {
        console.error("keepAliveStart: 获取应用上下文失败");
        return;
    }
 
    if (isKeepAliveRunning) {
        console.log("keepAliveStart: 保活服务已在运行中");
        return;
    }
 
    try {
        // 创建通知渠道 (Android 8.0+)
        createNotificationChannel(context);
 
        // 创建并显示前台通知
        showForegroundNotification(context);
 
        isKeepAliveRunning = true;
        console.log("keepAliveStart: 保活服务启动成功");
    } catch (e) {
        console.error("keepAliveStart: 启动失败", e);
    }
}
 
/**
 * 停止应用保活
 */
export function keepAliveStop(): void {
    const context = UTSAndroid.getAppContext();
    if (context == null) {
        return;
    }
 
    try {
        // 取消通知
        const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
        notificationManager.cancel(NOTIFICATION_ID);
 
        isKeepAliveRunning = false;
        console.log("keepAliveStop: 保活服务已停止");
    } catch (e) {
        console.error("keepAliveStop: 停止失败", e);
    }
}
 
/**
 * 检查保活服务是否正在运行
 */
export function isKeepAliveActive(): boolean {
    return isKeepAliveRunning;
}
 
/**
 * 获取电池电量百分比
 */
export function getBatteryCapacity(): string {
    const context = UTSAndroid.getAppContext();
    if (context != null) {
        const manager = context.getSystemService(Context.BATTERY_SERVICE) as BatteryManager;
        const currentLevel: number = manager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY);
        return '' + currentLevel + '%';
    }
    return "0%";
}
 
/**
 * 请求忽略电池优化(需要用户手动确认)
 * 调用此方法会弹出系统设置页面
 */
export function requestIgnoreBatteryOptimization(): void {
    const context = UTSAndroid.getAppContext();
    if (context == null) {
        return;
    }
 
    if (Build.VERSION.SDK_INT >= 23) { // Android 6.0+
        const powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager;
        const packageName = context.getPackageName();
 
        if (!powerManager.isIgnoringBatteryOptimizations(packageName)) {
            try {
                const intent = new Intent();
                intent.setAction("android.settings.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS");
                intent.setData(android.net.Uri.parse("package:" + packageName));
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(intent);
            } catch (e) {
                console.error("requestIgnoreBatteryOptimization: 打开设置失败", e);
            }
        } else {
            console.log("requestIgnoreBatteryOptimization: 已在白名单中");
        }
    }
}
 
/**
 * 检查是否已忽略电池优化
 */
export function isIgnoringBatteryOptimizations(): boolean {
    const context = UTSAndroid.getAppContext();
    if (context == null) {
        return false;
    }
 
    if (Build.VERSION.SDK_INT >= 23) {
        const powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager;
        const packageName = context.getPackageName();
        return powerManager.isIgnoringBatteryOptimizations(packageName);
    }
 
    return true; // Android 6.0 以下默认返回 true
}
 
/**
 * 创建通知渠道 (Android 8.0+ 必需)
 */
function createNotificationChannel(context: Context): void {
    if (Build.VERSION.SDK_INT >= 26) { // Android 8.0+
        const channel = new NotificationChannel(
            CHANNEL_ID,
            "应用保活服务",
            NotificationManager.IMPORTANCE_LOW
        );
        channel.setDescription("保持应用在后台运行");
        channel.setShowBadge(false);
        channel.enableLights(false);
        channel.enableVibration(false);
 
        const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
        notificationManager.createNotificationChannel(channel);
    }
}
 
/**
 * 显示前台通知
 */
function showForegroundNotification(context: Context): void {
    // 获取应用的启动 Intent
    const packageManager = context.getPackageManager();
    const launchIntent = packageManager.getLaunchIntentForPackage(context.getPackageName());
 
    let pendingIntentFlags = PendingIntent.FLAG_UPDATE_CURRENT;
    if (Build.VERSION.SDK_INT >= 31) { // Android 12+
        pendingIntentFlags = pendingIntentFlags | PendingIntent.FLAG_IMMUTABLE;
    }
 
    const pendingIntent = PendingIntent.getActivity(
        context,
        0,
        launchIntent,
        pendingIntentFlags
    );
 
    // 构建通知
    let builder: Notification.Builder;
    if (Build.VERSION.SDK_INT >= 26) {
        builder = new Notification.Builder(context, CHANNEL_ID);
    } else {
        builder = new Notification.Builder(context);
    }
 
    // 获取应用图标
    const appInfo = context.getApplicationInfo();
    const appIcon = appInfo.icon;
    const appName = packageManager.getApplicationLabel(appInfo).toString();
 
    builder.setSmallIcon(appIcon)
        .setContentTitle(appName)
        .setContentText("服务运行中")
        .setContentIntent(pendingIntent)
        .setOngoing(true) // 常驻通知,不可被滑动删除
        .setPriority(Notification.PRIORITY_LOW);
 
    if (Build.VERSION.SDK_INT >= 21) {
        builder.setCategory(Notification.CATEGORY_SERVICE);
    }
 
    const notification = builder.build();
 
    // 显示通知
    const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
    notificationManager.notify(NOTIFICATION_ID, notification);
}