实现Android推送功能,选择了接入华为推送和小米推送,结果步入了华为推送的一个神坑😂,需求其实很简单,就是服务器发个消息,客户端收到后显示,用户点击跳转到对应界面,应用未启动则启动应用跳转到对应界面
需求有了,开始实现吧,因为普通消息后台是调用的华为和小米平台的普通应用,所有通知栏的弹框华为和小米的SDK已经集成好,会根据后台给的字段弹出,需要处理的只是通知的点击事件,这部分其实很简单,点击通知后先跳转到首页,再根据传递过去的数据跳转到详情页,因为用户可能当前停留在首页,所有首页activity的lauchModel要设置成为singletask,不了解singletask的可以去看看activity的四种启动方式,singletask启动为如果栈内有activity实例,则不重新创建而走onNewIntent方法,并把栈中activity之上的其他activity全部清退(划重点),跳转代码:
Intent intent = new Intent();
intent.setClass(context,MainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP|Intent.FLAG_ACTIVITY_NEW_TASK);//创建新的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">
这样,点击推送会挑战到主页,然后再在mainactivity的 oncreate和onnewintent中根据传递的是数据是否未空来判断是否需要跳转到下一个页面
protected voidonCreate(@NullableBundlesavedInstanceState) {
super.onCreate(savedInstanceState);
if(getIntent().getExtras()!=null){
model= (NewsDetailsModel)getIntent().getExtras().getSerializable(NEWS_MODEL);
NotificationUtil.notifyToNewsDetails(model,mContext);//跳转到对应Activity
}
}
@Override
protected voidonNewIntent(Intentintent) {
super.onNewIntent(intent);
if(intent.getExtras()!=null){
model= (NewsDetailsModel)intent.getExtras().getSerializable(NEWS_MODEL);
NotificationUtil.notifyToNewsDetails(model,mContext);//跳转到对应Activity
}
}
如果应用处于未启动则走onCreate,处于启动则走onNewIntent,这样就实现了推送点击跳转到对应页面。
写好了,开始测试,小米没问题,按照流程跳转,然后开始测试华为,点击通知,跳转到首页,跳转到对应界面,木有问题,哎,等等,怎么 对应的页面自己关闭了?什么情况?为毛对应的界面会关闭?发生了什么?what ?
为什么小米可以华为会自己关闭页面?哪里错了?检查代码,没问题啊然后再测试一遍,发现华为推送跳转到了启动页,而小米没有,怎么办呢,看官方文档,发现华为推送有三种推送模式:富媒体,打开网页,打开应用,而后台发的普通通知的点击事件是打开应用,而小米的点击事件是交给应用去操作
然后我们打印华为推送点击后各个activity的生命周期(启动页SplashActivity,主页MainActivity,目标页TestActivity),华为推送的日志为
MainActivity:onNewIntent
TestActivity:onCreate
SplashActivity:onCreate
SplashActivity:onDestroy
MainActivity:onCreate
TestActivity:onDestroy
what?TestActivity为什么会走到onDestroy?why?
为什么小米没问题呢?检查代码,我们看到了MainActivity的lauchMode是singleTask,这样就说的通了,华为通知点击后activity的启动顺序是 MainActivity →SplashActivity→TestActivity→MainActivity
而小米的是MainActivity→TestActivity
为什么会不一样呢?因为华为的推送点击自带了启动应用🤣,而不带启动应用只能走透传,而小米可以交给客户端自己去处理,看文档,华为只提供3中推送方式,普通通知并不能让客户端自己处理点击事件,必须启动应用🤣,想不通为什么华为要这么干
而我们之前说了,singelTask的Activity会把activity栈中在它之上的所有activity清栈,所以我们的目标Activity就走到了onDestroy,原因找到,怎么解决呢?本着自己解决不去改后台的原因,我们来自己解决
我们看到,因为华为多启动了一次应用,所有栈内的activitiy变成了这样
而在SplashActivity中,因为会延迟跳转MainActivity,所以当MainActivity再次加入栈中时,会把MainActivity之上的Activity全部清退,这样就造成了TestActivity自动销毁,如何解决呢?
我们可以把SplashActivity也设置为SingleTask,并且在从SplashActivity跳转到首页的时候不去销毁它,在MainActivity的onDestroy中去销毁栈内所有Activity,这样点击华为推送后启动顺序为:启动MainActiviy,启动SplahsActivity,因为SplashActivity已经在栈内,所有要清退在它上面的所有Activity,然后MainActivity呗销毁,之后重新创建MainActivity,跳转到TestActivity
日志为这样:
MainActivity:onNewIntent
SplashActivity:onNewIntent
MainActivity:onDestroy
MainActivity:onCreate
TestActivity:onCreate
这个时候的Activity栈:
而在SplashActivity中,如果MainActivity被启动而SplashActivity中的延迟加载未加载完,则要去掉SplashActivity中的延迟加载,这样就解决了华为推送启动应用后跳转到指定页面的问题,当然最简单的还是直接使用透传而不用华为提供的推送