Arwii
mycodingjourney
Published in
8 min readDec 10, 2017

--

最近使用了一下firebase的push notification功能,想到以前串push notification的時候,簡單講起來,app team可能需要用c2dm,然後extends WakefulBroadcastReceiver,把GoogleCloudMessaging裡面的訊息parse出來,透過NotificationManager把需要的樣子打到使用者眼前.server team需要準備一台server跟GCM server溝通,如果使用者量大,server可能也需要考量到把要打的訊息分散到不同的時間,把訊息打到GCM server,再由GCM server轉發到應用程式上.這樣看起來至少需要兩個工程師的角色.一個app,一個server,如果你還需要友善的頁面讓你可以方便的填好有哪些訊息要送出(總不可能叫老闆自己用command line 打GCM的API),那這樣可能還需要一個前端做好這個友善的頁面.這段路的簡易圖大概如下

(Ref from https://developers.google.com/cloud-messaging/gcm)

以上這麼多功能,firebase已經可以覆蓋了大部分可能會使用的push notification的功能.這也就是最大的優點,(min)一個app的工程師就可以達到上述的效能了.

Google一下很容易搜尋到firebase怎麼設定,怎麼收到第一個push notification之類的文章,所以這部分就先pass,想要來分享一下一些push notification裡面的注意事項跟一些比較tricky的做法.

第一點:Push的時候app在foreground跟在background的差別

  1. 如果你的app沒有要客製化一些不太一樣的樣式的話,應該也不需要去改什麼.不過當你的app在background的時候只會出現公版的notification樣式,然後出現的訊息是firebase notification console裡面的message(如左圖),點下去notification據官方說法會把你的data帶到你的app去,然後需要用getIntent().getExtras();去把data拿出來

2. 如果notification需要有自己的樣子的話,或者是收到notification的時候需要做一些事情等等,這邊又分兩種情況,一是你的app在foreground,那麼最間單的你就只需要Override onMessageReceived,去對你要做的事情做處理,但這個onMessageReceived我自己測試的結果是當你的app在background的時候是不會跑到的.

所以google出了一個解法是去Override FirebaseMessagingService裡面的handleIntent,就可以當app在background的時候從這裡去發出你的notification or 去做你想做的事情.(ps. iOS不能這樣玩)

不過從這裡沒辦法拿到官方發出的notification的id,所以沒辦法針對該notification給cancel掉,為了避免有多個notification出現,我自己是會直接把我這個app的notification cancelAll就是了(算是一個work around)

第二點:Language的使用

  1. 在firebase的console裡面是可以選取push notification的語言,就是針對你所選的語言push到相對應語言的使用者device上,但這個語言的定義官方是說”device language”,但是我是有嘗試過把device改成不同的language,改完的當下push跟改完一天後的push都不會在預期的語言的機子上面收到相對應的push,不知道是因為我都用我自己的帳號去測試還是google判斷language的方式是跟著user的account去決定的,總之邏輯應該是在firebase那邊,這我自己是保持著保留意見.
  2. 所以就出現了Work around,

2.1 你可以在optional的data欄位裡面加上多組的key-value
代表key_language — valueXXX,例如說:

但這樣的work around感覺是有點髒,寫code的人都一直要知道這個邏輯,key firebase push的人也不能key錯

2.2 你也可以嘗試把你的message抽出變數,只push變數下去,然後把翻譯過的template放在app裡面,例如:

app裡面就可以放類似這樣的翻譯

<string name=”notification_discount_product_message”> %s 商品正在特價中</string>

<string name=”notification_discount_product_message”> %s discount! </string>

不過這也有缺點,你必須預先想好很多的可能會發出去的push,就不太適合太動態的notification了

2.3 第三個就是使用User properties!請參見下面這點

第三點:User properties的使用

1.先講重點!!目前只可以使用25組的properties!!目前不能delete!!感覺很重要可以說10遍.(對!你下面看到的test就是我已經浪費一個了…)

2. 要使用user properties之前需要在app裡面加上這段code

firebaseAnalytics.setUserProperty(key, value)

你才可以在你的console上面選到這個property,像上面第2點的問題就可以用這個很確切的設定好user的介面的語言了,例如:
firebaseAnalytics.setUserProperty(“language”, TW)
這樣在push的時候就可以選取language的property,然後設定通知條件,例如:

3. 不過個人猜測properties裡面value值可能可以帶某種資料結構,例如json object的形式之類的,收到再轉成自己要的樣子,不過應該也不適合太大量的資訊,如果真的需要很客製化,那還是建議自己弄個server可能會好些.

4. 額外一提,optional感覺可以用在檢查app有沒有最新版本,push一個你最新的版本下去,然後不要show出來,就可以跟現在版本比對然後去叫user更新了(這個之前也是需要server解決的,有看過有人的github上面是去parse google play的網頁,不過爬蟲嘛….就會是很苦功了.)

不過初步開始使用firebase的push notification,盡說些好處,怎麼可能一個東西只有好處沒有壞處,下面就提一下自己目前有遇到過的問題.

缺點:

  1. 收到user properties的update時間不確定,自己測試大概使用者要收到更新的狀態大概至少要30分鐘.
  2. 有些device收不到push就是收不到,對token的push可以,但對全部使用者的push就不收不到,直到factory reset機子後重裝app才可以收到.
  3. optional的key跟value設定需要人工設定,不小心就比較有可能key錯訊息,不然就是又要去implement一個web page然後打rest api到FCM上面去
  4. (這點有待確認) 目前好像沒有看到firebase有切分test env 跟production env,如果真的沒有可以設定的話應該也是可以用user properties解決,例如:
    firebaseAnalytics.setUserProperty(“env”, R.string.env)
    然後出app build的build script裡面再去針對R.string.env做更換.
    只是這樣也是要使用掉一個properties就是了,不過這樣可以考慮到上面提到的用json的解法把相關的系統設定綁在一個property?
    {
    language : “TW”,
    Env: “production”
    }

以上這些分享是個人目前使用

com.google.firebase:firebase-messaging:11.0.0

的一些小感想,之後一定會有不一樣的更新,搞不好到時候就不適用了.

現在就先拿出來跟有需要(看到)的人討論一下,有問題再請大家多多指教了.

--

--

Arwii
mycodingjourney

Try not to become a man of success, but rather try to become a man of value — A. Einstein