推送這個功能之前接觸過,用的是極光推送,是給web網站推送。這次是要給app推送。用uni-push2.0這個推送。現在把開發流程記錄一下。
1 看文檔
這應該是所有開發必須有的流程,先了解功能是否滿足需求,熟悉對接流程。
文檔鏈接 https://uniapp.dcloud.net.cn/unipush-v2.html
1 簡介
uni-push
是DCloud推出的、全端的、雲端一體的統一推送服務。
- 客戶端方面,
uni-push2
支持App、web、小程序。
- App端,內置了蘋果、華爲、小米、OPPO、VIVO、魅族、谷歌FCM等手機廠商的系統推送和個推第三方推送
- 小程序端,內置了socket在線推送。如需模板消息/訂閱消息,另見uni-subscribemsg
- web端,內置了socket在線推送 (uni-push1僅支持app,且app必須包含個推原生sdk。uni-push2在app端如不需要廠商推送,只需在線推送,無需集成個推原生sdk)
-
服務端方面,
uni-push2
支持uniCloud雲端一體,無需再編寫複雜代碼輕鬆完成push。 (uni-push1.0僅支持使用傳統服務器開發語言如php,未和客戶端有效協同,流程比uni-push2.0繁瑣) -
uni-push還自帶一個web控制檯。不寫代碼也可以在web頁面發推送。uni-push1.0的web控制檯在dev.dcloud.net.cn。uni-push2.0的web控制檯是開源的,屬於uni-admin插件詳見。
2 流程圖
3 效果圖
4 開通
4.1 項目配置文件設置
4.2 開發者中心
相關配置
這裏有設置雲端證書
平臺信息設置就是從證書裏獲取
有離線需求的還需要在這裏設置
各種使用key ,祕鑰需要從手機廠家平臺註冊獲得。
對了,推送需要關聯雲空間,所以要先開通雲空間,這個需要實名制,且需要花錢購買,當然開發過程可以免費一個月。
5 開發
5.1 客戶端
就是在App.vue頁面裏設置
我這裏是這樣弄的,加了權限判斷
<script>
import permision from "@/js_sdk/wa-permission/permission.js"
export default {
//https://blog.csdn.net/qq_40745143/article/details/129282665
//https://blog.csdn.net/weixin_42998230/article/details/127842430
onLaunch: function() {
//h5可以跳轉 只能是普通頁面,不能跳轉tabBar頁面
// uni.getPushClientId({
// success: (res) => {
// console.log(res,"設備信息")
// let push_clientid = res.cid
// console.log('客戶端推送標識77:', push_clientid)
// uni.setStorageSync('push_clientid', push_clientid)//個推cid
// },
// fail(err) {
// console.log(err)
// }
// })
// uni.onPushMessage((res) => {
// console.log("收到消息:", res) //監聽推送消息
// uni.navigateTo({
// url: '/pages/delivery/orderCustomer?DoID=C2202%2F00248',
// success() {
// },
// fail(err) {
// console.log(err)
// }
// })
// })
//#ifdef APP-PLUS
var main = plus.android.runtimeMainActivity();
var pkName = main.getPackageName();
var uid = main.getApplicationInfo().plusGetAttribute("uid");
var NotificationManagerCompat = plus.android.importClass(
"android.support.v4.app.NotificationManagerCompat"
);
//android.support.v4升級爲androidx
if (NotificationManagerCompat == null) {
NotificationManagerCompat = plus.android.importClass(
"androidx.core.app.NotificationManagerCompat"
);
}
var areNotificationsEnabled = NotificationManagerCompat.from(main).areNotificationsEnabled();
// 未開通‘允許通知’權限,則彈窗提醒開通,並點擊確認後,跳轉到系統設置頁面進行設置
if (!areNotificationsEnabled) {
console.log('請開啓權限:通知管理-允許通知')
uni.showModal({
title: '權限提示',
content: '請前往 通知管理 開啓權限',
confirmColor: '#7287EA',
success: function(res) {
if (res.confirm) {
permision.gotoAppPermissionSetting() // 跳轉到APP設置,用戶手動開啓通知權限
} else if (res.cancel) {
console.log('用戶點擊取消');
}
}
});
}
uni.getPushClientId({
success: (res) => {
//console.log(res,"設備信息")
let push_clientid = res.cid
console.log('客戶77:', push_clientid)
uni.setStorageSync('push_clientid', push_clientid)//個推cid
},
fail(err) {
console.log(err)
}
})
uni.onPushMessage((res) => {
console.log("收到推送消息999999999:", res) //監聽推送消息
uni.switchTab({
url: '/pages/receives/receives',
success() {
},
fail(err) {
console.log(err)
}
})
})
//#endif
},
onShow: function() {
//console.log('App Show')
},
onHide: function() {
//console.log('App Hide')
}
}
</script>
<style lang="scss">
/* 注意要寫在第一行,同時給style標籤加入lang="scss"屬性 */
@import "@/uni_modules/uview-ui/index.scss";
</style>
裏面有我參考的文章鏈接
5.2 服務端
先關聯雲空間,然後添加雲函數或雲對象
代碼格式
'use strict';
const uniPush = uniCloud.getPushManager({appId:"__UNI__212B963"})
exports.main = async (event, context) => {
//event爲客戶端上傳的參數
console.log('event : ', event)
let body = event.body;
if (event.isBase64Encoded) {
body = Buffer.from(body);
}
if(!body) {
return { message: 'no body'};
}
const param = JSON.parse(body);
//返回數據給客戶端
const res = await uniPush.sendMessage({
"push_clientid": param.push_clientid,
"title": param.title,
"content": param.content,
"payload": param.payload,
"force_notification": true,
"request_id": param.request_id
})
return res
};
這裏要注意的 ,URL化:get方法和post方法參數值
這裏給大家說一下get和post請求雲函數url化的區別,使用post方式進行請求時你填寫的請求參數會放到event.body中,但是這個body是String格式的需要你自己進行一次轉換才能去調用sendMessage方法,而get請求時你的參數會放到event.queryStringParameters中,這個queryStringParameters是json格式的不需要再進行轉換就能調用sendMessage方法。
https://blog.csdn.net/weixin_42998230/article/details/127842430
在雲函數文件目錄右鍵(或按快捷鍵ctrl + r)-> 上傳並運行雲函數
添加三張表 擴展庫依賴3張opendb表:opendb-tempdata
,opendb-device
,uni-id-device
5.3 接口url化設置
找到對應的函數,然後點擊詳情
再點擊編輯,設置名稱
5.4 調用
代碼
[Route("send-pushmsg")]
[HttpPost]
public IHttpActionResult SendMsg([FromBody]PushMsgModel pushMsgModel)
{
startTime = System.DateTime.Now;//設置執行之前的時間
try
{
var respondMsg = "";
StringBuilder jsonRequestMsg = new StringBuilder("");
if (pushMsgModel==null)
{
return Error(HttpStatusCode.BadRequest, new ApiErrorModel(2004, "參數錯誤!"));
}
if ((string.IsNullOrEmpty(pushMsgModel.carId)) || string.IsNullOrEmpty(pushMsgModel.payload) || string.IsNullOrEmpty(pushMsgModel.title) || string.IsNullOrEmpty(pushMsgModel.content))
{
return Error(HttpStatusCode.BadRequest, new ApiErrorModel(2004, "發送信息參數不能爲空!"));
}
var userInfo = _userID_Push_ClientidService.GetListByCondition(x=>x.UserID==pushMsgModel.carId).FirstOrDefault();
if (userInfo==null)
{
return Error(HttpStatusCode.BadRequest, new ApiErrorModel(2004, "未找到用戶信息!"));
}
else
{
if (string.IsNullOrEmpty(userInfo.Push_Clientid)) //個推id沒有綁定好
{
return Error(HttpStatusCode.BadRequest, new ApiErrorModel(2004, "個推綁定錯誤!"));
}
jsonRequestMsg.Append("{");
if (string.IsNullOrEmpty(userInfo.Old_Push_Clientid) || userInfo.Old_Push_Clientid == userInfo.Push_Clientid)
{
jsonRequestMsg.AppendFormat("\"push_clientid\":[\"{0}\"],",userInfo.Push_Clientid);
}
else
{
jsonRequestMsg.AppendFormat("\"push_clientid\":[\"{0},{1}\"],", userInfo.Push_Clientid,userInfo.Old_Push_Clientid);
}
jsonRequestMsg.AppendFormat("\"title\":\"{0}\",",pushMsgModel.title);
jsonRequestMsg.AppendFormat("\"content\":\"{0}\",", pushMsgModel.content);
jsonRequestMsg.AppendFormat("\"payload\":{0},", pushMsgModel.payload);
jsonRequestMsg.AppendFormat("\"request_id\":\"{0}\"", Guid.NewGuid().ToString());
jsonRequestMsg.Append("}");
}
bool flag = true;
string url = "https://demoxxxxx.com/sendMsg";
string jsonString = Post(url, jsonRequestMsg.ToString(), "application/json");
// string jsonString = "{\"data\":{\"RASS_0317_17245befc8b5f7cb982cd7e11c441ce9\":{\"065dd58c97eef8e8723bcc43ab3ab5a8\":\"successed_online\"}},\"errCode\":0,\"errMsg\":\"success\"}";
if (string.IsNullOrEmpty(jsonString))
{
flag = false;
respondMsg = "";
}
else
{
ResponseModel model = JsonConvert.DeserializeObject<ResponseModel>(jsonString);
if (model==null)
{
flag = false;
return Ok(new { status = true, message = "消息格式不對!" });
}
if (model.errCode=="0")
{
respondMsg = model.data.ToString();
}
else
{
flag = false;
respondMsg = model.errCode + model.errMsg;
}
}
if (flag)
{
using (TransactionScope ts = new TransactionScope())
{
LG_Push_Msg push = new LG_Push_Msg();
push.CreateDate = DateTime.Now;
push.Prepared = User.Identity.Name;
push.UserID = pushMsgModel.carId;
push.RequestMsg = jsonRequestMsg.ToString();
push.RespondMsg = respondMsg;
push.ID = Guid.NewGuid();
_push_MsgService.Insert(push);
_userLogService.LogUserAction(startTime, User.Identity.Name, User.Identity.Name, clientIP, "MS", "發送消息", "添加", pushMsgModel.carId.ToString());
ts.Complete();
}
}
else
{
return Ok(new { status = true, message = "發送失敗!" });
}
return Ok(new { status = true, message = "發送成功!" });
}
catch (Exception ex)
{
return Ok(new { status = false, message = "發送失敗!" });
}
}
private static string Post(string url, string postData, string contentType)
{
try
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = contentType;
request.Method = "POST";
request.Timeout = 300000;
byte[] bytes = Encoding.UTF8.GetBytes(postData);
request.ContentLength = bytes.Length;
Stream writer = request.GetRequestStream();
writer.Write(bytes, 0, bytes.Length);
writer.Close();
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.UTF8);
string result = reader.ReadToEnd();
response.Close();
return result;
}
catch (Exception ex)
{
return "";
}
}
public class PushMsgModel
{
[Required]
//public string[] carIds { get; set; } //當前車輛ID集合
public string carId { get; set; } //當前登錄人員
public string title { get; set; }//標題
public string content { get; set; }//內容
public string payload { get; set; }
// public string request_id { get; set; }
}
postman 格式
{
"carId":"ABY6175",
"title":"這是必填項",
"content":"數據怎麼保存",
"payload":"{\"test\":\"9999aaaa\",\"pjjjwwwata\":\"77777\"}",
"request_id":"09763F6F-B1CA-462E-B30A-1321AA37p611a111"
}
6 app客戶端
6.1 打包
6.2 模擬器
模擬器 網易的MuMu模擬器X
去這裏下載模擬器 https://mumu.163.com/index.html
設置分辨率和root權限
安裝好,再安裝app
右擊安裝後的app,打開詳情,設置相關權限
推送的消息效果
設置可調試
設置教程 https://mumu.163.com/help/20220721/35047_730476.html
D:\Program Files\MuMu9\emulator\nemu9\vmonitor\bin
adb_server.exe connect 127.0.0.1:7555
adb_server shell
環境變量設置
重啓 HBuilderX
點擊運行 ---》運行到Android App基座
出現這個
向下滑動打開通知
就是可以跳到指定頁面了
6.3調試
調試頁面之類的功能可以不用真實手機,推送消息,拍照這之類的功能必須真實手機。
調試不能用localhost 需要用ip地址
config.baseUrl = 'http://192.168.1.16:29671';
可能出現的問題解決辦法
https://ask.dcloud.net.cn/question/110217
設置一個延遲展示時間
if (response.statusCode == 200) {
if (response.data.results.length > 0) {
setTimeout(() => {
that.tableList = that.tableList.concat(response.data.results);
that.total = response.data.itemCount; //總條數
that.pageCount = that.searchForm.pageIndex;
}, 500)
}
} else {
uni.showToast({
title: response.data.ErrorInfo,
icon: 'error'
})
return;
}