Android 关于Notification 点击启动流程分析
最近在项目中做了一个关于推送消息,点击进入指定页面的一个功能,相信大家都遇到过这种情形。
比如在集成(极光/友盟/小米/华为)推送的时候,当收到消息的时候如何处理点击逻辑呢?看图:
上面是我简单画的一个分析流程以及注意事项,以后留用。
根据是否登录来做判断,为什么不根据进程是否存活来判断呢?因为在网上,很多都是根据进程是否alive来判断应用是否退出,但是进程死了,又如何能接收推送消息呢?因为接收推送消息需要一个常驻service。
所以我在项目中用是否登录来判断应用是否退出。
情况1:当应用没有退出时。
应当设置MainActivity启动模式为SingleTask,当MainActivity在堆栈中时,移除所有它上面的,将MainActivity至于栈顶,当Activity没启动,则在栈顶创建。 如此是为了保证MainActivity的唯一性。防止回退紊乱。在onNewIntent()方法中执行接收数据传递的方法。还需要执行setIntent(intent)方法来防止数据不会被刷新。
情况2:当应用退出时,
则应启动应用,在闪屏界面,登录界面,主界面一次传值。在onCreate()方法中去执行接收数据传递的方法。
onNewIntent的使用:
onNewIntent()使用场景,是当多次启动一个Activity时,只想保留一个Activity实例,需要用到onNewIntent()方法。故而只有SingleTask和SingleTop模式下,才可以用onNewIntent();第一次启动Activity时会走onCreate()->onStart()->onResume();并不会走onNewIntent(),多次启动同一Activity,会走onNewIntent()->onRestart()->onStart()->onResume().
当调用到onNewIntent(intent)的时候,需要在onNewIntent() 中使用setIntent(intent),否则,后续的getIntent()都是之前的Intent。赋值并不会被刷新。
以项目集成极光推送为例。
需要一个常驻service来接收推送的消息。
<!-- Required SDK 核心功能-->
<!-- 可配置android:process参数将PushService放在其他进程中 -->
<service
android:name="cn.jpush.android.service.PushService"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="cn.jpush.android.intent.REGISTER" />
<action android:name="cn.jpush.android.intent.REPORT" />
<action android:name="cn.jpush.android.intent.PushService" />
<action android:name="cn.jpush.android.intent.PUSH_TIME" />
</intent-filter>
</service>
需要一个Receiver来处理接收到的消息
<!-- Required SDK核心功能-->
<receiver
android:name="cn.jpush.android.service.PushReceiver"
android:enabled="true">
<intent-filter android:priority="1000">
<action android:name="cn.jpush.android.intent.NOTIFICATION_RECEIVED_PROXY" />
<category android:name="com.aixuetang.future" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.USER_PRESENT" />
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
<!-- Optional -->
<intent-filter>
<action android:name="android.intent.action.PACKAGE_ADDED" />
<action android:name="android.intent.action.PACKAGE_REMOVED" />
<data android:scheme="package" />
</intent-filter>
</receiver>
public class MyReceiver extends BroadcastReceiver {
private static final String TAG = "MyReceiver";
private NotificationManager nm;
@Override
public void onReceive(Context context, Intent intent) {
if (null == nm) {
nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
}
Bundle bundle = intent.getExtras();
Logger.d(TAG, "onReceive - " + intent.getAction() + ", extras: " + AndroidUtil.printBundle(bundle));
if (JPushInterface.ACTION_REGISTRATION_ID.equals(intent.getAction())) {
Logger.d(TAG, "JPush用户注册成功");
} else if (JPushInterface.ACTION_MESSAGE_RECEIVED.equals(intent.getAction())) {
Logger.d(TAG, "接受到推送下来的自定义消息");
} else if (JPushInterface.ACTION_NOTIFICATION_RECEIVED.equals(intent.getAction())) {
Logger.d(TAG, "接受到推送下来的通知");
receivingNotification(context,bundle);
} else if (JPushInterface.ACTION_NOTIFICATION_OPENED.equals(intent.getAction())) {
Logger.d(TAG, "用户点击打开了通知");
openNotification(context,bundle);
} else {
Logger.d(TAG, "Unhandled intent - " + intent.getAction());
}
}
private void receivingNotification(Context context, Bundle bundle){
String title = bundle.getString(JPushInterface.EXTRA_NOTIFICATION_TITLE);
Logger.d(TAG, " title : " + title);
String message = bundle.getString(JPushInterface.EXTRA_ALERT);
Logger.d(TAG, "message : " + message);
String extras = bundle.getString(JPushInterface.EXTRA_EXTRA);
Logger.d(TAG, "extras : " + extras);
}
private void openNotification(Context context, Bundle bundle){
String extras = bundle.getString(JPushInterface.EXTRA_EXTRA);
String myValue = "";
try {
JSONObject extrasJson = new JSONObject(extras);
myValue = extrasJson.optString("myKey");
} catch (Exception e) {
Logger.w(TAG, "Unexpected: extras is not a valid json", e);
return;
}
if (TYPE_THIS.equals(myValue)) {
Intent mIntent = new Intent(context, ThisActivity.class);
mIntent.putExtras(bundle);
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mIntent);
} else if (TYPE_ANOTHER.equals(myValue)){
Intent mIntent = new Intent(context, AnotherActivity.class);
mIntent.putExtras(bundle);
mIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(mIntent);
}
}
}
这里你可以启用自己的Notification,并处理点击事件
public void notify(PushCommandModel model,String message, Intent intent) {
String title=model.data.title;
String text=model.data.msg;
if(intent == null) {
intent = new Intent(StuApplication.getsAppContext(), MessageReceiver.class);
intent.putExtra("MSG_TYPE",message);
}
PendingIntent pendingIntent = PendingIntent.getBroadcast(StuApplication.getsAppContext(), 0, intent,PendingIntent.FLAG_UPDATE_CURRENT);
Notification notification = new NotificationCompat.Builder(StuApplication.getsAppContext())
.setContentTitle(title)
.setContentText(text)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.build();
notification.flags |= Notification.FLAG_AUTO_CANCEL;
notification.defaults |= Notification.DEFAULT_SOUND;
mNotificationManager.notify(sNotificationId++, notification);
LogUtils.e("sNotificationId---->"+sNotificationId);
}
处理点击用getBroadcast(),在MessageReceiver接收并处理,不处理点击用getActivity()。notify的id保证唯一,可以用当前系统时间。
在MessageReceiver中处理消息。
/**
* Created by Administrator on 2017/1/6.
*/
public class MessageReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
String message = intent.getStringExtra("MSG_TYPE");
if (MainActivity.isLogin) {
Log.i("isLogin", MainActivity.isLogin+"");
Intent mainIntent = new Intent(context, MainActivity.class);
mainIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mainIntent.putExtra(Constants.EXTRA_BUNDLE, message);
context.startActivity(mainIntent);
} else {
Log.i("isLogin", MainActivity.isLogin+"");
Intent launchIntent = context.getPackageManager().
getLaunchIntentForPackage("com.aixuetang.future");
launchIntent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
launchIntent.putExtra(Constants.EXTRA_BUNDLE, message);
context.startActivity(launchIntent);
}
} catch (Exception e) {
}
}
}
这里需要判断当前应用是否登录,判断方式不提,登录进入MainActivity,否则启动应用,当然各种参数需要传递
launchIntent.putExtra(Constants.EXTRA_BUNDLE, message);
在MainActivity中处理消息,跳转到指定页面
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// TODO: add setContentView(...) invocation
ButterKnife.bind(this);
receiveMessage();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
LogUtils.e("receiveMessage--onNewIntent-->");
receiveMessage();
}
private void receiveMessage(){
String message=getIntent().getStringExtra(Constants.EXTRA_BUNDLE);
LogUtils.e("receiveMessage---->"+message);
if(!TextUtils.isEmpty(message)){
LogUtils.e("receiveMessage--->");
PushDispatchUtils.dispatch(MainActivity.this,message);
}
}
在PushDispatchUtils中对消息进行集中处理,解析消息,分类型的处理消息。
对于未启动的情况,除了传值,别无其他,这里就不在讲述。
总结,需要常驻的service接收消息—->推到广播中接收—->弹出通知栏—->点击在广播中处理通知消息—->判断是否登录—–>>>>
推荐一款好用的通知栏库,代码也很简单。
https://github.com/wenmingvs/NotifyUtil
- 上一篇:没有了
- 下一篇:没有了