Apple 推播通知 及 Firebase 推播通知 FCM(二)
LearnIOS
上次說到 FCM ,用偷吃步的方式在 Iphone 上利用 URLRequest 來傳送通知到 Firebase 在傳送到使用者 Iphone 上面,這次就要來討論怎麼透過 Firebase 本身的服務來達成 推播通知(Remote notification) 。
Firebase Cloud Function
上面是文件說明,跟著步驟做先設定好 Node.js 還有 Firebase CLI,接下就很好上手了,在建立 firebase CLI 過程中記得選擇要使用的 project ,再來就開始來嘗試如何建立 function。
整個 function 的流程就是,如果更新 firestore 某個文件,cloud function 會去偵測,偵測到之後會做出接下來程式碼的改動。
使用的語法是 Node.js ,建議可以先下載 Atom 這個程式來編輯,雖然 Mac 內建的文字編輯器也可以用,但是 Atom 會比較方便看,會自動幫我們上色。
先打開 atom ,左上角 File — Open ,直接在 剛剛建立的 functions 點兩下開,主要是要編輯 index.js 這個文件
const admin = require(‘firebase-admin’);
const functions = require(‘firebase-functions’);admin.initializeApp(functions.config().firebase);let db = admin.firestore();
先在最上面寫上這些,要用到 firebase 自己的套件,再來就來試試看如何偵測囉
exports.sendPushMessage = functions.firestore
.document(‘matches_messages/{fromUserUid}/{toUserUid}/{messageUid}’)
.onCreate((snap, context) => {
const newValue = snap.data();
var newText = ‘’;
const toUid = newValue[‘toId’];
const fromUid = newValue[‘fromId’];
const id = context.params.fromUserUid;
const newType = newValue[‘MediaType’];
document 後面就是你要偵測的路徑,{}裡面的事當新增時可能是一個變數,例如 fromUserUid 就是傳送訊息的使用者的 uid,toUserUid 就是接受訊息的使用者的 uid, messageUid 是隨記亂碼的訊息 uid ,這樣是因為要一個 function 就適用所有的傳送。
onCreate 是當有數據新增時會觸發,所以當傳了一個新訊息,firestore 新增了一筆資料,就會觸發
/matches_messages/05YBcdtcb8TSHbWexZy0WQNl32J3/4VmJA76c9pPt24SAdy44KlZL1233/qvvHyCvJj8UfAVFWj45x
這是新增的文件的路徑
MediaType:”TEXT”fromId:”05YBcdtcb8TSHbWexZy0WQNl32J3"text:”Hello”timestamp:2020年2月20日 下午9:25:01 [UTC+8]toId:”4VmJA76c9pPt24SAdy44KlZLT1233"
上面傳送訊息後 firestore 會增加的文件,也就是 newValue 所拿到的東西。
之後就像 swift 的 dictionary 一樣 的去讀取想要拿到的東西,比較特別的是
const id = context.params.fromUserUid;
是因為 {fromUserUid} ,也就會拿到 05YBcdtcb8TSHbWexZy0WQNl32J3 這一串。
if (newType === ‘TEXT’){
newText = newValue[‘text’];
}else if (newType === ‘VIDEO’) {
newText = ‘You got a Video’;
}else if (newType === ‘PHOTO’) {
newText = ‘You got a Photo’;
}else if (newType === ‘RECORD’) {
newText = ‘You got a Record’;
}
因為我自己設定說訊息有分四種,要先辨別是哪一種才知道接下來要如何傳送,分辨完後就要來處理要做什麼反應
if (id === fromUid) {
return db.collection(‘users’).doc(String(fromUid)).get()
.then(doc => {
if (doc.exists === true) {
console.log(‘Document Data:’, doc.data().fullName);return db.collection(‘users’).doc(String(toUid)).get()
.then(otherDoc => {
if (otherDoc.exists === true) {
console.log(‘Document Data:’, otherDoc.data().fullName);var message = {
notification: {
title: doc.data().fullName,
body: newText
},
data: {
uid: String(doc.data().uid),
name: String(doc.data().fullName),
profileImageUrl: String(doc.data().imageUrl1),
fcmToken: String(doc.data().fcmToken)
},
token: otherDoc.data().fcmToken,
};
admin.messaging().send(message)
.then((response) => {
console.log(‘Successfully sent message:’, response);
return null;
})
.catch((error) => {
console.log(‘Error sending message:’, error);
});return otherDoc.data()
} else {
console.log(‘No such document!’);
throw new Error(“Profile doesn’t exist”)
}
})
.catch(err => {
console.log(‘Error getting document’, err);
});} else {
console.log(‘No such document!’);
throw new Error(“Profile doesn’t exist”)
}
})
.catch(err => {
console.log(‘Error getting document’, err);
});
} else {
return null;
}})
因為要一個 function 適用所有通知,所以要先辨別說只要當傳送的人跟新增資料的人是同一個才會繼續觸發,不然每傳一個訊息都會拿到兩次通知,至於 return 這個部分好像是 node.js 要求的,如果缺少這個 return 這個 function 很有可就會一直無限執行下去,但我還是無法完善,在 deploy 的時候會有黃色警告,還是可以使用。
/users/05YBcdtcb8TSHbWexZy0WQNl32J3
firestore 上的路徑
db.collection(‘users’).doc(String(fromUid)).get()
根據上面文件可以拿到傳送訊息的人的資料
db.collection(‘users’).doc(String(toUid)).get()
需要收到訊息的人的資料,主要是要拿到 fcmToken 才可以傳送通知
fcmToken:""fullName:""imageUrl1:""uid:""
拿到的資料模板
massage 的內容根據上面文件的說明就可以填寫,最後就是要傳送了
admin.messaging().send(message)
沒意外接收者的 iphone 就可以收到通知囉
FCM 透過 Cloud Function 來傳送大概就是這樣子囉
大家我們下次見