最近為了解決公司APP在一些手機出現的推送問題重新集成了最新版的友盟推送SDK,花費了幾天時間終於把集成和測試工作完成,最終在華為,Nexus,三星,小米,HTC,魅族等10多部手機上測試並達到了預想效果,這里把期間遇到的問題和集成注意事項記錄下來方便自己總結和迭代更新,也希望能給碰到相同問題的朋友帶去一點幫助,在此特別感謝友盟團隊的技術人員范亞傑(向睿)以及產品運營趙橫(沐惶)對我給予的幫助,話不多說,進入正題:
一、SDK集成
SDK版本:V3.1.0a
官網下載地址:http://dev.umeng.com/push/android/sdk-download
具體集成步驟參考官網:http://dev.umeng.com/push/android/integration
集成過程並不復雜,大體如下
1、在官網(http://push.umeng.com)上使用應用包名創建應用,獲取應用對應的AppKey和Umeng Message Secret。
2、下載SDK的壓縮文件並解壓縮(解壓后的文件路徑不能有中文),把解壓縮后得到的目錄下的PushSDK當做Module導入到自己的工程。
3、在官網PushSDK下載處,下載全平台so文件,添加缺少的so文件夾至 PushSDK下,使PushSDK的so文件夾與主工程的so文件夾保持一致。這里是否缺少so文件夾以及缺少那些文件夾可以通過解壓縮自己項目的release apk,看看lib下有哪些so文件夾來確定,保證每個文件夾都有推送SDK的so文件即可(參考后文注意事項第5點)。全平台so庫下載地址:http://dev.umeng.com/system/resources/W1siZiIsIjIwMTcvMDMvMTQvMTBfMzdfNDBfMjg5X3NvX2FsbF9wbGF0Zm9ybXMuemlwIl1d/so_all_platforms.zip
如圖所示,則需要添加arm64-v8a以及arm64-v7a兩個文件夾
4、配置Appkey和Secret,添加Channel ID
在工程的Application Module的AndroidManifest.xml中的<Application>標簽下添加:
<meta-data
android:name="UMENG_APPKEY"
android:value="xxxxxxxxxxxxxxxxxxxxxxxxxxxx">
</meta-data>
<meta-data
android:name="UMENG_MESSAGE_SECRET"
android:value="xxxxxxxxxxxxxxxxxxxxxxxxxxxx">
</meta-data>
<meta-data
android:name="UMENG_CHANNEL"
android:value="Channel ID" >
</meta-data>
把步驟1中的AppKey和Umeng Message Secret添加到UMENG_APPKEY和UMENG_MESSAGE_SECRET的相應value。你可以自定義Channel ID來標識App的推廣渠道,作為推送消息時給用戶分組的一個維度添加到UMENG_CHANNEL的value處。
5、配置build.gradle
在Application Module的build.gradle文件的dependencies下添加compile project(':PushSDK'),另外必須在defaultConfig中設置applicationId並保證和自己的包名一致,否則PushSDK依賴庫AndroidManifest中${applicationId}將不能正常替換成包名,例如:
6、注冊推送服務(是否開啟推送都要調用注冊方法)
如果項目中沒有用戶開啟關閉推送功能則只需要調用register方法,不用調用enable或者disable,否則按需調用enable和disable方法,例如我們項目有設置推送開關
7、統計應用啟動數據(在BaseActiivty調用)
8、添加混淆配置(拷貝官網配置即可)
9、打包測試
測試可按照官網說明,根據deviceToken定向推送。
二、測試
測試條件:WIFI條件
測試內容:測試模式下推送消息查看手機通知欄是否有消息送到,根據deviceToken查詢長連接Service在線狀態
測試機型:紅米note2,三星SM-E7009,華為Mate7,華為C199s,魅族M2 note,
ZTE N918St,三星Glaxy S6 edge+,海信 I639T,Coolpad8297-W01,HTC D816V,華為 TIT-CL00,HTC 2PQ93,Nexus 6P
測試系統版本范圍:4.X-6.X
測試步驟:APP首次安裝—>按home鍵,APP退至后台—>點擊系統返回,退出APP—>
從最近打開列表清除進程—>重新打開APP—>設置-應用程序-清除數據—>重新打開APP
結果如下:
測試結果總結如下:
(1)所有手機在“APP首次安裝”以及“按home鍵,APP退至后台”的操作都能正常獲取deviceToken並保證長連接Service處於在線狀態,並能及時收到推送消息。
(2)幾乎所有手機在“點擊系統返回鍵,退出APP”后長連接Service都能從離線狀態恢復成在線狀態,這個過程耗時10秒左右,並能收到離線時發送的歷史消息以及在線狀態的及時消息。一小部分特殊機型需要允許自啟動或者關聯啟動才能在線,特殊機型參考后文。
(3)超過半數的手機能在用戶“從最近打開列表清除進程”的操作后長連接Service能從離線狀態恢復成在線狀態,並接受到及時消息,原生系統手機基本都能正常工作,比如Nexsus,三星,HTC等等,不能正常工作的多為定制化廠商系統比如華為,小米等部分手機,因為這些手機系統底層做了限制,基本上無能為力。
(4)絕大多數手機在用戶進行“設置-應用程序-清除數據”操作后長連接Service都處於離線,推送都不能送達,一小部分手機(原生系統手機)能正常工作。
(5)所有手機都能重新打開APP的時候保證長連接Service在線並接收到離線或者及時消息(不管是點擊系統返回鍵退出后還是清除最近使用列表進程還是清除數據后都正常)。
(6)如果手機上有裝有其他集成了友盟推送SDK的應用,比如UC瀏覽器,暴風影音,魯大師等阿里系的應用基本都能一直保持長連接Service在線,從而正常工作,極大的提高推送成功率。因為友盟推送消息路由機制是復用長連接,能互相喚醒,只是宿主不同而已。
注:原生系統機器不會對推送做任何限制,長連接Service基本上不會被殺死,因為殺死還能自動起來,推送成功率很高(清除數據除外,因為這跟安裝完后沒打開差不多)。
三、注意事項匯總
1、 Android特殊機型整理&集成注意事項(不定期更新)
參考:http://bbs.umeng.com/thread-21334-1-1.html
2、 必須
在項目Application類的 onCreate()
方法中注冊推送服務,無論推送是否開啟都需要調用register方法
3、 device-token的生成規則及其變化條件
device token是【友盟+】生成的用於標識設備的id,長度為44位,不能定制和修改。同一台設備上不同應用對應的device token不一樣。
(1)device-token是SDK在初始化的時候向服務器端發起注冊請求,由服務器端生成之后頒發給客戶端的。 SDK向服務器端注冊的時候,要把設備的標識id(umid + utdid)和app的標識(appkey,包名)作為參數告知服務器,服務器以設備id和appkey為基礎,結合一定的算法生成device-token。所以device-token可以近似認為是“設備id + appkey”的結合。
(2)設備device-token變化有兩種最可能的情況:一種是設備卸載過,又重新安裝,token可能會變化;另一種是設備沒有SD卡,設備id變化導致的device-token變化。另外我發現清除數據再次打開APP,deviceToken也有概率性變化,應該也是屬於設備id變化導致,經過測試,Nexus 6P手機清除數據或者卸載APP后每次都會變化。而其他手機變化的幾率比較小。另外register方法的回調不一定每次都會返回deviceToken(有時候為null),只有進程被殺,重啟app,才會有返回值(這是友盟技術人員告訴我的),如果沒有被殺死則會返回null,所以不能在回調中存儲deviceToken,而應該是通過mPushAgent.getRegistrationId()來獲取。
參考: http://bbs.umeng.com/thread-11061-1-1.html 關於deviceToken的變化這個帖子說明的很詳細,必須知悉。
4、 So庫的引用導致的accs bindapp error以及獲取不到deviceToken問題
解壓縮我們的APK,發現APP主項目和依賴庫總共引入了4個平台so文件,SDK標准提供了兩個
所以得下載全平台的so庫,添加另外兩個文件夾到PushSDK,也能解決部分手機上獲取不到DeviceToken的bug,比如紅米note2(4個文件夾基本能滿足需求了,關於這點我也向友盟技術人員確認過了)。
參考:http://bbs.umeng.com/thread-23018-1-1.html
5、 官網集成文檔說明請勿在調用register方法時做進程判斷處理,主進程和channel進程均需要調用register方法才能保證長連接的正確建立,事實上是可以只在主進程和channel進程兩個中調用register方法即可(官方回復)。
6、 關閉推送方法disable調用后會同步到友盟SDK,如果沒有調用enable打開推送功能是不會再次開啟推送的,極端操作是我在設置中關閉推送,這個時候我清除APP數據功能,如果deviceToken沒變化的手機上打開APP時沒有調用enable則會出現推送不了的情況,因為會提示“用戶未注冊”,雖然在沒調用disable時,不用調用enable方法就能推送,那么這個時候就需要在初始化時候加上一定條件條件判斷,例如:
7、 Register方法必須放在Application中執行,如果滯后到MainActivity中則只能打開APP活着App處於前台才能收到推送消息,這個問題對於有特殊要求的應用有一定印象,比如說手機預裝應用,因為預裝應用中的聯網,讀取設備信息等操作都必須等待用戶同意之后才能進行,所以register方法可能需要滯后,當然另外一種解決辦法是第一次打開不進行register方法,直到用戶某次允許后才初始化,那么在這之前推送功能則無效,這個問題也需要具體分析對待。
8、 讀寫SD卡權限以及read phone state權限都是非必須權限,沒有也基本不影響推送功能,當然有最好,這是友盟技術人員告訴我的。
9、 清除數據后理論上進程會被殺死,但有的機子上也不一定,所以清除數據,一般都是要打開重新注冊推送才能正常工作的。
10、SDK默認在“23:00”到“7:00”之間收到通知消息時不響鈴,不振動,不閃燈。如果需要改變默認的靜音時間,可以使用以下接口:
public void setNoDisturbMode(int startHour, intstartMinute, int endHour, int endMinute)
11、 默認情況下,同一台設備在1分鍾內收到同一個應用的多條通知時,不會重復提醒,同時在通知欄里新的通知會替換掉舊的通知。可以通過如下方法來設置冷卻時間:
mPushAgent.setMuteDurationSeconds(int seconds);
12、 mPushAgent.enable(newIUmengCallback())回調失敗,返回300,bind Agoo service fail也不影響推送功能的使用。
13、集成測試可以PushAgent.setDebugMode(true)在logcat中過濾message標簽查看具體的日志,也可以過濾在channel進程中查看所有推送SDK的操作日志,包括網絡請求、響應的json以及心跳檢測,ping等操作,對於長連接的保活能有一定的指導作用。
14、 同一個設備deviceToken變化后可以檢測到在線,但是發送提示“設備號格式錯誤”。