From d81b425672a8b9c95f46f5712c3e001f97f4b8cb Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Tue, 10 Feb 2026 10:03:59 +0800
Subject: [PATCH] feat: 后台弹出界面

---
 uniapps/work-app/src/uni_modules/keep-app/utssdk/app-android/index.uts |  374 ++++++++++++++++++++++++++---------------------------
 1 files changed, 183 insertions(+), 191 deletions(-)

diff --git a/uniapps/work-app/src/uni_modules/keep-app/utssdk/app-android/index.uts b/uniapps/work-app/src/uni_modules/keep-app/utssdk/app-android/index.uts
index ec249a6..2ce95f2 100644
--- a/uniapps/work-app/src/uni_modules/keep-app/utssdk/app-android/index.uts
+++ b/uniapps/work-app/src/uni_modules/keep-app/utssdk/app-android/index.uts
@@ -1,105 +1,105 @@
 // 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 PowerManager from "android.os.PowerManager";
-import BatteryManager from "android.os.BatteryManager";
-import { UTSAndroid } from "io.dcloud.uts";
+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 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;
+const CHANNEL_ID = 'keep_alive_channel'
+const NOTIFICATION_ID: Int = 1001
 
 // 保活服务是否已启动的标志
-let isKeepAliveRunning = false;
+let isKeepAliveRunning = false
 
 // WakeLock 引用,用于保持 CPU 运行
-let wakeLock: PowerManager.WakeLock | null = null;
+let wakeLock: PowerManager.WakeLock | null = null
 
 /**
  * 启动应用保活
  * 通过 WakeLock + 通知来保持应用在后台运行
  */
 export function keepAliveStart(): void {
-    const context = UTSAndroid.getAppContext();
-    if (context == null) {
-        console.error("keepAliveStart: 获取应用上下文失败");
-        return;
-    }
+  const context = UTSAndroid.getAppContext()
+  if (context == null) {
+    console.error('keepAliveStart: 获取应用上下文失败')
+    return
+  }
 
-    if (isKeepAliveRunning) {
-        console.log("keepAliveStart: 保活服务已在运行中");
-        return;
-    }
+  if (isKeepAliveRunning) {
+    console.log('keepAliveStart: 保活服务已在运行中')
+    return
+  }
 
-    try {
-        // 1. 获取 WakeLock 唤醒锁,保持 CPU 运行
-        acquireWakeLock(context);
+  try {
+    // 1. 获取 WakeLock 唤醒锁,保持 CPU 运行
+    acquireWakeLock(context)
 
-        // 2. 创建通知渠道 (Android 8.0+)
-        createNotificationChannel(context);
+    // 2. 创建通知渠道 (Android 8.0+)
+    createNotificationChannel(context)
 
-        // 3. 创建并显示前台通知
-        showForegroundNotification(context);
+    // 3. 创建并显示前台通知
+    showForegroundNotification(context)
 
-        // 4. 注册应用生命周期监听
-        registerLifecycleCallbacks();
+    // 4. 注册应用生命周期监听
+    registerLifecycleCallbacks()
 
-        isKeepAliveRunning = true;
-        console.log("keepAliveStart: 保活服务启动成功(WakeLock已获取)");
-    } catch (e) {
-        console.error("keepAliveStart: 启动失败", e);
-    }
+    isKeepAliveRunning = true
+    console.log('keepAliveStart: 保活服务启动成功(WakeLock已获取)')
+  } catch (e) {
+    console.error('keepAliveStart: 启动失败', e)
+  }
 }
 
 /**
  * 停止应用保活
  */
 export function keepAliveStop(): void {
-    const context = UTSAndroid.getAppContext();
-    if (context == null) {
-        return;
-    }
+  const context = UTSAndroid.getAppContext()
+  if (context == null) {
+    return
+  }
 
-    try {
-        // 释放 WakeLock
-        releaseWakeLock();
+  try {
+    // 释放 WakeLock
+    releaseWakeLock()
 
-        // 取消通知
-        const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
-        notificationManager.cancel(NOTIFICATION_ID);
+    // 取消通知
+    const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+    notificationManager.cancel(NOTIFICATION_ID)
 
-        isKeepAliveRunning = false;
-        console.log("keepAliveStop: 保活服务已停止(WakeLock已释放)");
-    } catch (e) {
-        console.error("keepAliveStop: 停止失败", e);
-    }
+    isKeepAliveRunning = false
+    console.log('keepAliveStop: 保活服务已停止(WakeLock已释放)')
+  } catch (e) {
+    console.error('keepAliveStop: 停止失败', e)
+  }
 }
 
 /**
  * 检查保活服务是否正在运行
  */
 export function isKeepAliveActive(): boolean {
-    return isKeepAliveRunning;
+  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%";
+  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%'
 }
 
 /**
@@ -107,118 +107,113 @@
  * 调用此方法会弹出系统设置页面
  */
 export function requestIgnoreBatteryOptimization(): void {
-    const context = UTSAndroid.getAppContext();
-    if (context == null) {
-        return;
-    }
+  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 (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: 已在白名单中");
-        }
+    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;
-    }
+  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);
-    }
+  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
+  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);
+  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);
-    }
+    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());
+  // 获取应用的启动 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;
-    }
+  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
-    );
+  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);
-    }
+  // 构建通知
+  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();
+  // 获取应用图标
+  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);
+  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);
-    }
+  if (Build.VERSION.SDK_INT >= 21) {
+    builder.setCategory(Notification.CATEGORY_SERVICE)
+  }
 
-    const notification = builder.build();
+  const notification = builder.build()
 
-    // 显示通知
-    const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager;
-    notificationManager.notify(NOTIFICATION_ID, notification);
+  // 显示通知
+  const notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
+  notificationManager.notify(NOTIFICATION_ID, notification)
 }
 
 /**
@@ -226,44 +221,41 @@
  * PARTIAL_WAKE_LOCK: 保持 CPU 运行,屏幕和键盘背光可以关闭
  */
 function acquireWakeLock(context: Context): void {
-    if (wakeLock != null && wakeLock!.isHeld()) {
-        console.log("acquireWakeLock: WakeLock 已持有");
-        return;
-    }
+  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"
-        );
+  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);
+    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);
-        }
+  if (wakeLock != null && wakeLock!.isHeld()) {
+    try {
+      wakeLock!.release()
+      wakeLock = null
+      console.log('releaseWakeLock: WakeLock 已释放')
+    } catch (e) {
+      console.error('releaseWakeLock: WakeLock 释放失败', e)
     }
+  }
 }
 
 /**
@@ -271,30 +263,30 @@
  * 当应用进入后台时,确保 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.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.onAppActivityResume(() => {
+    console.log('onAppActivityResume: 应用返回前台')
+  })
 
-    // 应用被销毁时的回调
-    UTSAndroid.onAppActivityDestroy(() => {
-        console.log("onAppActivityDestroy: 应用被销毁");
-        // 释放资源
-        releaseWakeLock();
-        isKeepAliveRunning = false;
-    });
+  // 应用被销毁时的回调
+  UTSAndroid.onAppActivityDestroy(() => {
+    console.log('onAppActivityDestroy: 应用被销毁')
+    // 释放资源
+    releaseWakeLock()
+    isKeepAliveRunning = false
+  })
 
-    console.log("registerLifecycleCallbacks: 生命周期回调已注册");
+  console.log('registerLifecycleCallbacks: 生命周期回调已注册')
 }

--
Gitblit v1.9.3