吉安感知网项目-前端
罗广辉
2026-02-27 e00da17ae2adaecf1cdf2d5128e357a50607bc90
feat: 权限获取调整
4 files modified
255 ■■■■ changed files
uniapps/work-app/src/App.vue 51 ●●●●● patch | view | raw | blame | history
uniapps/work-app/src/hooks/useGlobalWS.js 15 ●●●● patch | view | raw | blame | history
uniapps/work-app/src/uni_modules/keep-app/utssdk/app-android/index.uts 65 ●●●●● patch | view | raw | blame | history
uniapps/work-app/src/uni_modules/lgh-dialog/utssdk/app-android/index.uts 124 ●●●●● patch | view | raw | blame | history
uniapps/work-app/src/App.vue
@@ -51,54 +51,13 @@
    keepAliveStart()
    //显示悬浮窗权限
    // setTimeout(allowFloat, 5000)
    setTimeout(allowFloat, 5000)
    // 请求用户允许忽略电池优化(重要:用于保活)
    setTimeout(() => {
        if (!isIgnoringBatteryOptimizations()) {
            uni.showModal({
                title: '权限提示',
                content: '为了在后台收到来电时能弹出通话界面,请将应用添加到电池优化白名单',
                confirmText: '去设置',
                cancelText: '暂不',
                success(res) {
                    if (res.confirm) {
                        requestIgnoreBatteryOptimization()
                    }
                }
            })
        }
    }, 10000)
    setTimeout(requestIgnoreBatteryOptimization, 10000)
    // 引导用户开启「后台弹出界面」权限
    // setTimeout(() => {
    //     uni.showModal({
    //         title: '权限提示',
    //         content: '为了在后台收到来电时能弹出通话界面,请开启“后台弹出界面”权限',
    //         confirmText: '去设置',
    //         cancelText: '暂不',
    //         success(res) {
    //             if (res.confirm) {
    //                 allowBackgroundPopup()
    //             }
    //         }
    //     })
    // }, 15000)
    //
    // // 引导用户开启「锁屏显示」权限
    // setTimeout(() => {
    //     uni.showModal({
    //         title: '权限提示',
    //         content: '为了在锁屏时能显示来电通知,请开启“锁屏显示通知”权限',
    //         confirmText: '去设置',
    //         cancelText: '暂不',
    //         success(res) {
    //             if (res.confirm) {
    //                 allowLockScreen()
    //             }
    //         }
    //     })
    // }, 20000)
    setTimeout(allowBackgroundPopup, 15000)
    //  引导用户开启「锁屏显示」权限
    setTimeout(allowLockScreen, 20000)
    // #endif
}
uniapps/work-app/src/hooks/useGlobalWS.js
@@ -2,7 +2,7 @@
import useAppStore from "../store/modules/app/index.js";
import websocketService from "@/utils/websocket.js";
// #ifdef APP-PLUS
import { openDialog, allowFloat, getBatteryCapacity } from '@/uni_modules/lgh-dialog'
import { openDialog, allowFloat, getBatteryCapacity, showIncomingCallNotification, cancelIncomingCallNotification } from '@/uni_modules/lgh-dialog'
// #endif
export function useGlobalWS() {
    const userStore = useUserStore();
@@ -27,8 +27,6 @@
    // 处理语音通话请求
    if (t === 'call') {
      console.log('📞 全局收到来电 call,来自', payload.from)
      // 播放铃声
      // playRingtone();
      // 触发震动
      triggerVibration();
      // 构建来电参数
@@ -37,7 +35,10 @@
        from: payload.from,
        type: 'incoming'
      };
// #ifdef APP-PLUS
      // #ifdef APP-PLUS
      // 发送来电通知(锁屏/后台都会弹出 + 亮屏)
      showIncomingCallNotification(payload.from || '未知来电')
      // 拉起应用到前台
            openDialog()
      // #endif
      // 转义参数以便在URL中传递
@@ -57,6 +58,12 @@
      }
      return
    }
    // 通话接听或结束时,取消来电通知
    if (t === 'accept' || t === 'reject' || t === 'hangup' || t === 'cancel') {
      // #ifdef APP-PLUS
      cancelIncomingCallNotification()
      // #endif
    }
  }
  // 播放来电铃声 - 定义在 messageHandler 外部
uniapps/work-app/src/uni_modules/keep-app/utssdk/app-android/index.uts
@@ -11,6 +11,8 @@
import PowerManager from 'android.os.PowerManager'
import BatteryManager from 'android.os.BatteryManager'
import { UTSAndroid } from 'io.dcloud.uts'
import AlertDialog from 'android.app.AlertDialog'
import DialogInterface from 'android.content.DialogInterface'
// 保活服务的通知渠道ID
const CHANNEL_ID = 'keep_alive_channel'
@@ -102,36 +104,7 @@
  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: 已在白名单中')
    }
  }
}
/**
 * 检查是否已忽略电池优化
@@ -152,6 +125,40 @@
}
/**
 * 请求忽略电池优化(需要用户手动确认)
 * 调用此方法会弹出系统设置页面
 */
export function requestIgnoreBatteryOptimization(): void {
  if (isIgnoringBatteryOptimizations()) return
  const activity = UTSAndroid.getUniActivity()
  if (activity == null) return
  AlertDialog.Builder(activity)
    .setTitle('权限提示')
    .setMessage('为了在后台收到来电时能弹出通话界面,请将应用添加到电池优化白名单')
    .setPositiveButton('去设置', (_dialog : DialogInterface, _which : Int) => {
      const context = UTSAndroid.getAppContext()
      if (context == null) return
      if (Build.VERSION.SDK_INT >= 23) {
        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)
          }
        }
      }
    })
    .setNegativeButton('暂不', null)
    .show()
}
/**
 * 创建通知渠道 (Android 8.0+ 必需)
 */
function createNotificationChannel(context: Context): void {
uniapps/work-app/src/uni_modules/lgh-dialog/utssdk/app-android/index.uts
@@ -10,6 +10,8 @@
import PendingIntent from 'android.app.PendingIntent'
import PowerManager from 'android.os.PowerManager'
import KeyguardManager from 'android.app.KeyguardManager'
import AlertDialog from 'android.app.AlertDialog'
import DialogInterface from 'android.content.DialogInterface'
// 来电通知相关常量
const CALL_CHANNEL_ID = 'incoming_call_channel'
@@ -37,64 +39,86 @@
    if (context == null) return
    // 1. 检查悬浮窗权限 (Android 6.0+)
    const noneFloat = Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(context)
    if (noneFloat) {
        uni.showModal({
            title: '权限提示',
            content: '为了在后台收到来电时能弹出通话界面,请开启“悬浮”权限',
            confirmText: '去设置',
            cancelText: '暂不',
            success(res) {
                if (res.confirm) {
            try {
              // 无权限,跳转到权限设置页面
              const intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
              intent.setData(android.net.Uri.parse('package:' + context.getPackageName()))
              intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
              context.startActivity(intent)
            } catch (e) {
              console.error(e)
            }
                }
            }
        })
    }
    if (!noneFloat) return
    const activity = UTSAndroid.getUniActivity()
    if (activity == null) return
    AlertDialog.Builder(activity)
        .setTitle('权限提示')
        .setMessage('为了在后台收到来电时能弹出通话界面,请开启"悬浮窗"权限')
        .setPositiveButton('去设置', (_dialog : DialogInterface, _which : Int) => {
            try {
                const intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION)
                intent.setData(android.net.Uri.parse('package:' + context.getPackageName()))
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                context.startActivity(intent)
            } catch (e) {
                console.error(e)
            }
        })
        .setNegativeButton('暂不', null)
        .show()
}
// 跳到后台弹出界面权限页面(应用详情设置)
export function allowBackgroundPopup() {
    const context = UTSAndroid.getAppContext()
    if (context == null) return
    try {
        const intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
        intent.setData(android.net.Uri.parse('package:' + context.getPackageName()))
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        context.startActivity(intent)
    } catch (e) {
        console.error(e)
    }
  const context = UTSAndroid.getAppContext()
  if (context == null) return
  // 后台弹出界面无标准API,用悬浮窗权限作为代理判断(有悬浮窗权限通常也允许后台弹出)
  const nonePermission = Build.VERSION.SDK_INT >= 23 && !Settings.canDrawOverlays(context)
  if (!nonePermission) return
  const activity = UTSAndroid.getUniActivity()
  if (activity == null) return
  AlertDialog.Builder(activity)
    .setTitle('权限提示')
    .setMessage('为了在后台收到来电时能弹出通话界面,请开启"后台弹出界面"权限')
    .setPositiveButton('去设置', (_dialog : DialogInterface, _which : Int) => {
      try {
        const intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
        intent.setData(android.net.Uri.parse('package:' + context.getPackageName()))
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        context.startActivity(intent)
      } catch (e) {
        console.error(e)
      }
    })
    .setNegativeButton('暂不', null)
    .show()
}
// 跳到锁屏显示权限页面(通知设置)
export function allowLockScreen() {
    const context = UTSAndroid.getAppContext()
    if (context == null) return
    try {
        if (Build.VERSION.SDK_INT >= 26) {
            // Android 8.0+ 跳转到应用通知设置
            const intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
            intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName())
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            context.startActivity(intent)
        } else {
            // 低版本跳转到应用详情
            const intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
            intent.setData(android.net.Uri.parse('package:' + context.getPackageName()))
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            context.startActivity(intent)
        }
    } catch (e) {
        console.error(e)
    }
  const context = UTSAndroid.getAppContext()
  if (context == null) return
  // 锁屏显示依赖通知权限,检查通知是否开启
  const nm = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
  const nonePermission = !nm.areNotificationsEnabled()
  if (!nonePermission) return
  const activity = UTSAndroid.getUniActivity()
  if (activity == null) return
  AlertDialog.Builder(activity)
    .setTitle('权限提示')
    .setMessage('为了在锁屏时能显示来电通知,请开启"锁屏显示通知"权限')
    .setPositiveButton('去设置', (_dialog : DialogInterface, _which : Int) => {
      try {
        if (Build.VERSION.SDK_INT >= 26) {
          // Android 8.0+ 跳转到应用通知设置
          const intent = new Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
          intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName())
          intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
          context.startActivity(intent)
        } else {
          // 低版本跳转到应用详情
          const intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
          intent.setData(android.net.Uri.parse('package:' + context.getPackageName()))
          intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
          context.startActivity(intent)
        }
      } catch (e) {
        console.error(e)
      }
    })
    .setNegativeButton('暂不', null)
    .show()
}
/**