Android 关于Notification 点击启动流程分析
来源:互联网 发布:数控火焰切割手动编程 编辑:程序博客网 时间:2024/06/04 19:56
最近在项目中做了一个关于推送消息,点击进入指定页面的一个功能,相信大家都遇到过这种情形。
比如在集成(极光/友盟/小米/华为)推送的时候,当收到消息的时候如何处理点击逻辑呢?看图:
上面是我简单画的一个分析流程以及注意事项,以后留用。
根据是否登录来做判断,为什么不根据进程是否存活来判断呢?因为在网上,很多都是根据进程是否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
- Android 关于Notification 点击启动流程分析
- android 点击notification只启动一个activity
- android启动流程分析
- Android 启动流程分析
- Android Framework启动流程分析
- Android 开机启动流程分析
- Android 4.0启动流程分析
- Android Framework启动流程分析
- Android PackageManagerService启动流程分析
- Android Framework启动流程分析
- Android Framework启动流程分析
- Android -- Wifi启动流程分析
- Android Framework启动流程分析
- Android应用启动流程分析
- android PakageManagerService启动流程分析
- Android service启动流程分析.
- Android Application启动流程分析
- Android -- Wifi启动流程分析
- 安卓自定义相册的选择器
- 【Redis学习】:NoSQL概述
- 浮点数表示
- 集群维护
- 理解RemoteViews(Android开发艺术探索读书笔记)
- Android 关于Notification 点击启动流程分析
- string.format()
- Android 搜索框:SearchView 的属性和用法详解
- Android之---Activity与Fragment之间的传值问题
- C++中的类和对象(二)
- vector对象的初始化
- 数据结构实验之链表二:逆序建立链表(附带链表的释放)
- android 64k方法数限制的解决方案
- git学习笔记3—工作区与暂存区