使用 UniApp Push 2.0 服务需要在手机厂商开发者获取相应的推送密钥,但是申请密钥的过程极其繁琐,甚至需要各种证、备案等,有些厂商甚至仅开放企业用户开发者注册。
在安卓系统中,当应用进入后台或者被用户关闭后,通常会被系统回收资源以达到系统性能优化的目的。但是,有些应用程序需要在后台长时间运行,比如音乐播放器、即时通讯等,这时就需要使用一些技术手段来保持应用程序的运行状态,以确保应用程序能够正常运行。
本文主要使用后台播放音频和定时激活的方式解决无法实时推送,缺点是一段时间后还是会被系统杀后台,而且 APP 不能关闭,同时系统其他声音会被暂停。
<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.INTERNET" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_ADDED" />
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_CHANGED" />
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_INSTALL" />
<uses-permission android:name="android.permission.BROADCAST_PACKAGE_REPLACED" />
<uses-permission android:name="android.permission.RESTART_PACKAGES" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
Geolocation 定位
Push 2.0 - 离线推送✅
let interval = null
const pushAlert = {
title: '油油',
content: '正在后台运行中',
}
const music = uni.createInnerAudioContext() // 创建播放器对象
music.src = '/static/sound/noSound.m4a' // 这里是无声音频文件地址,网上很多
music.loop = true // 循环
// 这个推送仅作为后台运行提示
music.onPlay(() => {
uni.createPushMessage({
...pushAlert,
cover: true,
})
})
/**
* 推送消息
*
* 通过播放无声音频和定位来实现 APP 常驻后台,防止 APP 被系统杀死
*
* **onShowApp** 显示时关闭声音和定位,在 `onShow` 中调用
*
* **onHideApp** 隐藏时播放声音和定位,在 `onHide` 中调用
*
* @author Yoniu // xu_jingzhi@200011.net
*
*/
export default {
setPushAlert(title = '油油', content = '正在后台运行中') {
pushAlert.title = title
pushAlert.content = content
},
pushEventListener() {
// #ifdef APP-PLUS
// 接收推送消息
uni.onPushMessage((res) => {
switch (res.type) {
case 'click':
/// 这里是点击消息后执行的方法
break
default:
uni.createPushMessage({
title: res.data.title,
content: res.data.content,
payload: res.data.payload,
sound: 'system',
})
break
}
})
// #endif
},
onShowApp() {
// 关闭定时获取定位
if (interval != null) {
clearInterval(interval)
interval = null
}
},
onHideApp() {
if (interval != null) {
clearInterval(interval)
interval = null
}
// 开始播放无声音频
music.play()
// 定时获取定位
interval = setInterval(() => {
uni.getLocation({
type: 'wgs84',
success() {
},
})
}, 5 * 1000)
},
}
<script>
import push from './methods/push.js'
export default {
onLaunch() {
push.pushEventListener()
},
onShow() {
push.onShowApp()
},
onHide() {
push.onHideApp()
}
};
</script>
'use strict';
const uniPush = uniCloud.getPushManager({ appId:"" }) //注意这里需要传入你的应用appId,用于指定接收消息的客户端
exports.main = async (event, context) => {
try {
if (!event.body) {
throw new Error("请求必填参数为空")
}
const obj = JSON.parse(event.body)
const sendObj = await uniPush.sendMessage({
"push_clientid": obj.cids, // 设备id,支持多个以数组的形式指定多个设备,如["cid-1","cid-2"]
"title": obj.title, // 标题
"content": obj.content, // 内容
"payload": obj.payload, // 数据
"request_id": obj.request_id // 请求唯一标识号,10-32位之间;如果request_id重复,会导致消息丢失
})
return {
code: "200",
message: "推送成功",
data: sendObj,
}
} catch(error) {
return {
code: "400",
message: error.message || "系统在执行相关操作时出现错误",
data: null,
}
}
};
后端只需要执行云函数就可以实现推送。
另外后端需要处理用户设备 id,通过 UniApp 获取设备 id:
uni.getPushClientId({
success: (res) => {
const push_clientid = res.cid // 设备 id
},
fail(err) {},
})