# app后台保活,支持Android/iOS - ios通过后台定位或着无限播放音乐来达到后台保活的目的 - ios商店审核时注意说明有后台播放音乐或后台定位功能 - 支持息屏 ## 要唤醒未启动的app可以使用插件[https://ext.dcloud.net.cn/plugin?id=20180](https://ext.dcloud.net.cn/plugin?id=20180) ## 集成步骤 1. 拷贝demo里的nativeResources、Info.plist文件到项目根目录 2. 集成插件,集成插件步骤请参考 [https://www.cnblogs.com/wenrisheng/p/18323027](https://www.cnblogs.com/wenrisheng/p/18323027) ## 保活方式 ### Android采用多种方式一起使用来增加保活的概率 ### iOS系统支持两种保活方式(后台定位、无限循环播放无声音乐),采用其中一种即可 ## 接口文档 ```javascript import { UTSKeepalive } from "@/uni_modules/wrs-uts-keepalive" let keepalive = new UTSKeepalive() ``` ```javascript // 设置回调 UTSKeepalive.setCallback((resp)=>{ this.showMsg(JSON.stringify(resp)) let opt = resp.opt switch (opt){ // 定位改变 case "onLocationChanged": if(this.isAndroid) { let location = resp.location let latitude = location.latitude let longitude = location.longitude let speed = location.speed } else { let locations = resp.locations } break; default: break; } }) ``` ### android保活 ```javascript 多种方式一起使用: let params = this.getAndroidNotification() // 1. 开启前台服务 UTSKeepalive.startForegroundService(params) // 2. 开启定时服务结合双进程互相唤醒方式 UTSKeepalive.startJobService(params) UTSKeepalive.startLocalService(params) UTSKeepalive.startRemoteService(params) // 3. 开启锁屏监听 UTSKeepalive.startScreenLockReceiver() // 后台定位功能,用不到后台定位可以不需要调用 let locationParams = {} locationParams.notification = params locationParams.location = { provider: "gps", // 支持gps、fused、network、passive minTimeMs: 500, // 间隔时间,这里为了测试效果,设置为500毫秒,实际情况根据自己业务设置 minDistanceM: 0.5 // 间隔距离,这里为了测试效果,设置为0.5米,实际情况根据自己业务设置 } UTSKeepalive.startLocstionService(locationParams) provider: (1)GPS_PROVIDER:通过 GPS 来获取地理位置的经纬度信息; 优点:获取地理位置信息精确度高; 缺点:只能在户外使用,获取经纬度信息耗时,耗电; (2)NETWORK_PROVIDER:通过移动网络的基站或者 Wi-Fi 来获取地理位置; 优点:只要有网络,就可以快速定位,室内室外都可; 缺点:精确度不高; (3)PASSIVE_PROVIDER:被动接收更新地理位置信息,而不用自己请求地理位置信息。 PASSIVE_PROVIDER 返回的位置是通过其他 providers 产生的,可以查询 getProvider() 方法决定位置更新的由来,需要 ACCESS_FINE_LOCATION 权限,但是如果未启用 GPS,则此 provider 可能只返回粗略位置匹配; (4)FUSED_PROVIDER:这个本来已经被废弃了,但是目前在Android12(即android api 31)上又重新使用了起来,但是它依赖GMS,所以国内暂时无法使用。 我们通常使用gps和network这两种方式。 ``` ```javascript getAndroidNotification() { let channelId = 10 let params = {} params.identifier = "123" // 通知ID,尽量所有的通知都用同一个identifier,不同identifier会产生多条通知 params.channel = { // 如果已经channelId的channel则不创建,如果没有则会自动创建 channelId: channelId, channelName: "保活channel", importance: 5, // 3: default 4: high 2: low 5: max 1: min 0: none lockscreenVisibility: 1, //1: public 0: private -1: secret description: "保活channel" } params.notification = { channelId: channelId, // 此消息通知是属于哪个channel的 contentTitle: "保活通知", contentText: "保活", visibility: 1, // 1: public 0: private -1: secret smallIcon: { // 小图标,必传 type: "resource", // 固定 defType: "drawable", // 固定 name: "not" // 文件名,不要带文件后缀,对应nativeResources/android/res/drawable文件夹下的图片 }, autoCancel: false } return params } ``` - Android白名单 一些android手机需要开启白名单来达到保活,需要用户手动开启,白名单主要指: 1. 电池后台耗电管理 从 Android 6.0 开始,系统为了省电增加了休眠模式,系统待机一段时间后,会杀死后台正在运行的进程。 但系统会有一个后台运行白名单,白名单里的应用将不会受到影响 开启路径(不通机型有所不一样):「设置」 - 「电池」 - 「电池优化」 - 「未优化应用」 - 允许后台高耗电 - 允许自启动 - 允许后台活动 2. 开机自启动 开启路径(不通机型有所不一样):「应用权限设置页」 - 「所有权限」 - 自启动(开机自动 后台启动) - 开机启动 3. 锁屏清理 开启路径(不通机型有所不一样):「应用权限设置页」 - 「锁屏清理」 - 「开启」 4. 神隐模式(小米) 开启路径(不通机型有所不一样):「应用权限设置页」 - 「神隐模式」 - 「无限制」 - 「开启定位」 5. 还有一些其它机型有类似「绿色后台」、「应用保护」这样的设置,都需要开启 - 跳到app设置页面,仅支持Android ```javascript UTSKeepalive.goToAppSettings() ``` - 请求定位权限,仅支持iOS ```javascript // 0:kCLAuthorizationStatusNotDetermined // 1: kCLAuthorizationStatusRestricted // 2: kCLAuthorizationStatusDenied // 3: kCLAuthorizationStatusAuthorizedAlways // 4: kCLAuthorizationStatusAuthorizedWhenInUse // 5: kCLAuthorizationStatusAuthorized var authorizationStatus = UTSKeepalive.getAuthorizationStatus(); if (authorizationStatus == 0) {// 没有授权过定位时,请求定位权限 keepalive.requestLocationAuthorization() } ``` ## ios保活 ```javascript // 监听app前后台状态 UTSKeepalive.listenerApp((resp) => { let opt = resp.opt switch (opt) { // app进入后台 case "enterBackground": { var authorizationStatus = UTSKeepalive.getAuthorizationStatus(); // app进入后台,此时采用定位保活还是采用播放音乐保活可以根据自己业务决定 if (authorizationStatus == 3) { // 当定位权限是总是一直定位时采用定位来保活 console.log("定位保活") keepalive.startLocation({ desiredAccuracy: "NearestTenMeters", allowsBackgroundLocationUpdates: true, // 允许后台更新位置 pausesLocationUpdatesAutomatically: false // 不允许自动暂停更新位置 }) } else { // 采用播放音乐保活 console.log("播放音乐保活") UTSKeepalive.setCategory("playback") var url = plus.io.convertLocalFileSystemURL('_www/static/bgmusic.mp3'); keepalive.playMusic({ url: url, numberOfLoops: -1, // 循环此时,-1表示无限循环 volume: 0 // 音量,0 }); } // 通知系统开始后台任务 UTSKeepalive.beginBackgroundTask() } break; // app回到前台 case "enterForeground": { // 停止播放音乐 keepalive.stopMusic() // 停止定位 keepalive.stopLocation() // 通知系统结束后台任务 UTSKeepalive.endBackgroundTask() } break; default: break; } }) ``` - 保活验证代码 ```javascript onHide() { //页面消失的时候开启定时器实时刷新当前时间,app退到后台后启动定时器,实时刷新当前时间,观察控制台输出的定时输出日志,如果控制台一直有打印数据说明app后台运行时还是保活的 // app回到前台时,如果显示的是当前时间,说明后台保活有效,定时器在后台运行时一直有效 if (this.timer) { clearInterval(this.timer); } this.timer = setInterval(() => { this.curTime = this.getCurrentTime() this.count = this.count + 1 this.showMsg("定时任务 count: " + this.count) }, 1000); }, onShow() { if (this.timer) { clearInterval(this.timer); } }, ```