????實(shí)現(xiàn)Android推送功能,選擇了接入華為推送和小米推送班挖,結(jié)果步入了華為推送的一個神坑??鲁捏,需求其實(shí)很簡單,就是服務(wù)器發(fā)個消息萧芙,客戶端收到后顯示给梅,用戶點(diǎn)擊跳轉(zhuǎn)到對應(yīng)界面,應(yīng)用未啟動則啟動應(yīng)用跳轉(zhuǎn)到對應(yīng)界面
需求有了双揪,開始實(shí)現(xiàn)吧动羽,因?yàn)槠胀ㄏ⒑笈_是調(diào)用的華為和小米平臺的普通應(yīng)用,所有通知欄的彈框華為和小米的SDK已經(jīng)集成好渔期,會根據(jù)后臺給的字段彈出运吓,需要處理的只是通知的點(diǎn)擊事件渴邦,這部分其實(shí)很簡單,點(diǎn)擊通知后先跳轉(zhuǎn)到首頁拘哨,再根據(jù)傳遞過去的數(shù)據(jù)跳轉(zhuǎn)到詳情頁谋梭,因?yàn)橛脩艨赡墚?dāng)前停留在首頁,所有首頁activity的lauchModel要設(shè)置成為singletask,不了解singletask的可以去看看activity的四種啟動方式倦青,singletask啟動為如果棧內(nèi)有activity實(shí)例瓮床,則不重新創(chuàng)建而走onNewIntent方法,并把棧中activity之上的其他activity全部清退(劃重點(diǎn))姨夹,跳轉(zhuǎn)代碼:
Intent intent = new Intent();
intent.setClass(context,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);//創(chuàng)建新的activity并清除棧頂activity
Bundle bundle = new Bundle();
bundle.putSerializable(NEWS_MODEL, data);
intent.putExtras(bundle);
context.startActivity(intent);
AndroidMainfest
<android:name=".ui.activity.MainActivity"
android:configChanges="keyboardHidden|orientation|screenSize|locale"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden"
android:screenOrientation="portrait"
android:launchMode="singleTask"
android:theme="@style/AppTheme">
這樣纤垂,點(diǎn)擊推送會挑戰(zhàn)到主頁,然后再在mainactivity的 oncreate和onnewintent中根據(jù)傳遞的是數(shù)據(jù)是否未空來判斷是否需要跳轉(zhuǎn)到下一個頁面
protected voidonCreate(@NullableBundlesavedInstanceState) {
????super.onCreate(savedInstanceState);
????????if(getIntent().getExtras()!=null){
????????????????model= (NewsDetailsModel)getIntent().getExtras().getSerializable(NEWS_MODEL);
????????????????NotificationUtil.notifyToNewsDetails(model,mContext);//跳轉(zhuǎn)到對應(yīng)Activity
????????}
}
@Override
protected voidonNewIntent(Intentintent) {
????super.onNewIntent(intent);
????if(intent.getExtras()!=null){
????????model= (NewsDetailsModel)intent.getExtras().getSerializable(NEWS_MODEL);
????????NotificationUtil.notifyToNewsDetails(model,mContext);//跳轉(zhuǎn)到對應(yīng)Activity
????}
}
如果應(yīng)用處于未啟動則走onCreate磷账,處于啟動則走onNewIntent,這樣就實(shí)現(xiàn)了推送點(diǎn)擊跳轉(zhuǎn)到對應(yīng)頁面峭沦。
寫好了,開始測試逃糟,小米沒問題吼鱼,按照流程跳轉(zhuǎn),然后開始測試華為绰咽,點(diǎn)擊通知菇肃,跳轉(zhuǎn)到首頁,跳轉(zhuǎn)到對應(yīng)界面取募,木有問題琐谤,哎,等等玩敏,怎么 對應(yīng)的頁面自己關(guān)閉了斗忌?什么情況?為毛對應(yīng)的界面會關(guān)閉旺聚?發(fā)生了什么织阳?what ?
為什么小米可以華為會自己關(guān)閉頁面?哪里錯了砰粹?檢查代碼唧躲,沒問題啊然后再測試一遍,發(fā)現(xiàn)華為推送跳轉(zhuǎn)到了啟動頁碱璃,而小米沒有弄痹,怎么辦呢,看官方文檔嵌器,發(fā)現(xiàn)華為推送有三種推送模式:富媒體界酒,打開網(wǎng)頁,打開應(yīng)用嘴秸,而后臺發(fā)的普通通知的點(diǎn)擊事件是打開應(yīng)用毁欣,而小米的點(diǎn)擊事件是交給應(yīng)用去操作
然后我們打印華為推送點(diǎn)擊后各個activity的生命周期(啟動頁SplashActivity,主頁MainActivity,目標(biāo)頁TestActivity),華為推送的日志為
MainActivity:onNewIntent
TestActivity:onCreate
SplashActivity:onCreate
SplashActivity:onDestroy
MainActivity:onCreate
TestActivity:onDestroy
what?TestActivity為什么會走到onDestroy?why?
為什么小米沒問題呢庇谆?檢查代碼,我們看到了MainActivity的lauchMode是singleTask凭疮,這樣就說的通了饭耳,華為通知點(diǎn)擊后activity的啟動順序是 MainActivity →SplashActivity→TestActivity→MainActivity
而小米的是MainActivity→TestActivity
為什么會不一樣呢?因?yàn)槿A為的推送點(diǎn)擊自帶了啟動應(yīng)用??执解,而不帶啟動應(yīng)用只能走透傳寞肖,而小米可以交給客戶端自己去處理,看文檔衰腌,華為只提供3中推送方式新蟆,普通通知并不能讓客戶端自己處理點(diǎn)擊事件,必須啟動應(yīng)用??右蕊,想不通為什么華為要這么干
而我們之前說了琼稻,singelTask的Activity會把a(bǔ)ctivity棧中在它之上的所有activity清棧,所以我們的目標(biāo)Activity就走到了onDestroy,原因找到,怎么解決呢饶囚?本著自己解決不去改后臺的原因帕翻,我們來自己解決
我們看到,因?yàn)槿A為多啟動了一次應(yīng)用萝风,所有棧內(nèi)的activitiy變成了這樣
而在SplashActivity中嘀掸,因?yàn)闀舆t跳轉(zhuǎn)MainActivity,所以當(dāng)MainActivity再次加入棧中時,會把MainActivity之上的Activity全部清退规惰,這樣就造成了TestActivity自動銷毀睬塌,如何解決呢?
我們可以把SplashActivity也設(shè)置為SingleTask歇万,并且在從SplashActivity跳轉(zhuǎn)到首頁的時候不去銷毀它衫仑,在MainActivity的onDestroy中去銷毀棧內(nèi)所有Activity,這樣點(diǎn)擊華為推送后啟動順序?yàn)椋簡覯ainActiviy,啟動SplahsActivity,因?yàn)镾plashActivity已經(jīng)在棧內(nèi)堕花,所有要清退在它上面的所有Activity,然后MainActivity唄銷毀,之后重新創(chuàng)建MainActivity,跳轉(zhuǎn)到TestActivity
日志為這樣:
MainActivity:onNewIntent
SplashActivity:onNewIntent
MainActivity:onDestroy
MainActivity:onCreate
TestActivity:onCreate
這個時候的Activity棧:
而在SplashActivity中粥鞋,如果MainActivity被啟動而SplashActivity中的延遲加載未加載完缘挽,則要去掉SplashActivity中的延遲加載,這樣就解決了華為推送啟動應(yīng)用后跳轉(zhuǎn)到指定頁面的問題呻粹,當(dāng)然最簡單的還是直接使用透傳而不用華為提供的推送