PendingIntent第四个参数flags在Notification中的不同作用

PendingIntent第四个参数为int类型的flags,首先看一下官方文档对它的描述:

flags May be FLAG_ONE_SHOT, FLAG_NO_CREATE, FLAG_CANCEL_CURRENT, FLAG_UPDATE_CURRENT, or any of the flags as supported by Intent.fillIn() to control which unspecified parts of the intent that can be supplied when the actual send happens.
可见flags可以有四个取值,分别是FLAG_ONE_SHOT, FLAG_NO_CREATE, FLAG_CANCEL_CURRENT, FLAG_UPDATE_CURRENT。这四种取值每一种都有特定的意义。当然,也可以不使用上述四种常量中的任意一种,即不为PendingIntent指定flags,此时只需要传入一个数字0即可。
例如:
PendingIntent.getActivity(context, requestCode, someIntent, 0);
传入0(第四个参数),就意味着你不打算使用任何一种flag来控制PendingIntent的创建。
 

接下来看一下四种flags的各自功能:

FLAG_CANCEL_CURRENT:如果要创建的PendingIntent已经存在了,那么在创建新的PendingIntent之前,原先已经存在的PendingIntent中的intent将不能使用

FLAG_NO_CREATE:如果要创建的PendingIntent尚未存在,则不创建新的PendingIntent,直接返回null

FLAG_ONE_SHOT:相同的PendingIntent只能使用一次,且遇到相同的PendingIntent时不会去更新PendingIntent中封装的Intent的extra部分的内容

FLAG_UPDATE_CURRENT:如果要创建的PendingIntent已经存在了,那么在保留原先PendingIntent的同时,将原先PendingIntent封装的Intent中的extra部分替换为现在新创建的PendingIntent的intent中extra的内容

PendingIntent重写了equals方法,判定两个PendingIntent是否相同的依据是它封装的Intent是否“相同”和requestCode是否一致。注意,“相同”上打了引号,这是因为在比较PendingIntent中封装的intent时是否相同时,使用的是Intent的filterEquals方法,该方法认为只要两个intent具有相同的action、data、categories、components、type和flags(这个flags是intent的flags)就认为它们两个是“相同”的,filterEquals是不会比较两个intent的extra部分和内存地址的。另外需要注意的是,Intent并没有重写equals方法,所以如果使用Intent的equals方法比较两个intent对象的话,比较的是两个对象的内存地址。看有如下代码示例:

int requestCode = 1;

Intent intentA = new Intent( );

intentA.putExtra("name","AAA");

Intent intentB = new Intent( );

intentB.putExtra("name","BBB");
PendingIntent p1 = PendingIntent.getActivity(context, requestCode, intentA, 0);
PendingIntent p2 = PendingIntent.getActivity(context, requestCode, intentB, 0);

Log.d("TAG","两个intent是否相等(equals)"+intentA.equals(intentB));//false

Log.d("TAG","两个intent是否相等(filterEquals)"+intentA.filterEquals(intentB));//true

Log.d("TAG","两个PendingIntent是否相等"+p1.equals(p2));//true

有了上面的知识铺垫,接下来,用不同的flags创建Notification中使用的PendingIntent,看看不同的flags所产生的不同效果:

 

 

 
  1. <span style="font-family:SimHei;font-size:18px;"><span style="color:#222222;">int requestCode = 1;

  2. Intent intentA = new Intent(this, SecondActivity.class);

  3. intentA.putExtra("name","AAA");

  4. Intent intentB = new Intent(this, SecondActivity.class);

  5. intentB.putExtra("name","BBB");

  6. PendingIntent p1 = PendingIntent.getActivity(this, requestCode, intentA, </span><span style="color:#ff0000;">0</span><span style="color:#222222;">);

  7. PendingIntent p2 = PendingIntent.getActivity(this, requestCode, intentB, </span><span style="color:#ff0000;">0</span><span style="color:#222222;">);

  8. NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

  9. Notification notification = new Notification.Builder(this).//

  10. setContentTitle("title").//

  11. setContentText("Content Text").//

  12. setSmallIcon(R.drawable.ic_launcher).//

  13. setAutoCancel(true).//

  14. setContentIntent(p1).//

  15. build();

  16. manager.notify(1, notification);

  17. Notification notification2 = new Notification.Builder(this).//

  18. setContentTitle("title2").//

  19. setContentText("Content Text2").//

  20. setSmallIcon(R.drawable.ic_launcher).//

  21. setAutoCancel(true).//

  22. setContentIntent(p2).//

  23. build();

  24. manager.notify(2, notification2);</span></span>

SecondAcitivity中有一个TextView,用来显示打开SecondActivity的Intent中的String Extra内容:

 

 
  1. TextView tv = (TextView) findViewById(R.id.test);

  2. tv.setText(getIntent().getStringExtra("name"));

这里重点看创建PendingIntent时的第四个参数:

使用0时,意味着不使用flags进行创建PendingIntent时的控制,那么此时创建的两个PendingIntent对于安卓来说是一样的,并且不会去更新PendingIntent中封装的intent的extra内容。因此无论点击哪个通知都会跳转到SecondActivity的,并且都会在tv里面显示的是AAA。

现在改变一下创建PendingIntent时的flags:

设置两个PendingIntent的flags均为FLAG_CANCEL_CURRENT,此时随着p2的创建,p1里面的Intent内容会失效。因此,点击第一个Notification的时候,只会自动取消掉该通知(因为设置了AutoCancel为true)并且返回到MainActivity界面而不会发生跳转。当点击第二个Notification的时候,p2发挥作用,所以点击通知会进行跳转到SecondActivity,并在SecondActivity的tv中显示BBB。

设置两个PendingIntent的flags均为FLAG_NO_CREATE,此时无论点击哪个通知,都不会有任何效果,通知即不会自动消失也不会跳转到任何界面(即使MainActivity界面都无法跳转)。这是因为在之前没有“相同”的PendingIntent时,FLAG_NO_CREATE也根本不会创建新的PendingIntent而是直接返回null。这样在点击通知时,根本就没有PendingIntent,所以也不会跳转也不会取消通知。FLAG_CANCEL_CURRENT和FLAG_NO_CREATE最大的区别就是前者会保留PendingIntent,只是把里面的Intent取消掉。另外还可以知道很重要的一点,如果仅仅设置了通知的AutoCancel而没有设置PendingIntent的话,点击通知时,通知是不会消失的!

设置两个PendingIntent的flags均为FLAG_ONE_SHOT,相同的PendingIntent哪个先获得点击,哪个就会被执行。FLAG_ONE_SHOT不具备更新相同的PendingIntent中Intent的extra的能力。因此,如果先点击通知2,会跳转到SecondActivity,并在SecondActivity的tv中显示AAA,再点击通知1,仅仅会取消通知1并返回到MainActivity。如果先点击通知1,会跳转到SecondActivity,并在SecondActivity的tv中显示AAA,再点击通知2,仅仅会取消通知2并返回到MainActivity。

最后,设置两个PendingIntent的flags均为FLAG_UPDATE_CURRENT,使用该flags时,后创建的PendingIntent在遇到已经存在的相同的PendingIntent时,会去更新原先PendingIntent中封装的intent的extra内容为最新的PendingIntent封装的Intent中的extra内容。即,p2会把p1的intent的extra内容更新为自己的extra。此时,无论点击哪个通知,都会跳转到SecondActivity,并且在tv上显示最新一个PendingIntent中Intent中的extra内容,即都会显示BBB。

在Android应用,如果你想要创建一个即使当前Activity(活动)已经关闭但仍能显示的弹窗,通常的做法是在一个单独的服务(Service)或者通知(Notification)实现。以下是步骤概述: 1. **服务 (Service)**: 创建一个`Service`,它可以持续运行并在后台执行任务,例如维护一个定时器,每当到了某个条件(比如一定的时间间隔或特定事件发生)就显示一个自定义的通知。 ```java public class PersistentNotificationService extends Service { // 在这里添加显示弹窗的相关逻辑 @Override public void onStartCommand(Intent intent, int flags, int startId) { showPopup(); // 使用AlarmManager设置定时器或监听其他事件 AlarmManager alarm = getSystemService(AlarmManager.class); Intent i = new Intent(this, PersistentNotificationService.class); PendingIntent pi = PendingIntent.getService(this, 0, i, 0); alarm.setRepeating(RTC_WAKEUP, System.currentTimeMillis(), INTERVAL_IN_MILLIS, pi); } private void showPopup() { // 实现弹窗显示逻辑 } } ``` 2. **通知 (Notification)**: 使用`NotificationManager`创建一个持久化的通知。当需要显示弹窗时,更新这个通知的内容,而不是每次都启动一个新的Activity。 ```java public class NotificationHelper { public static void createPersistentNotification(Context context) { NotificationCompat.Builder builder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID) .setContentTitle("标题") .setContentText("内容"); // 设置通知为PERSISTENT,使其一直存在 builder.setSmallIcon(R.drawable.ic_notification) .setPriority(Notification.PRIORITY_DEFAULT) .setOngoing(true); // 获取通知管理器并发送通知 NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context); notificationManager.notify(NOTIFICATION_ID, builder.build()); } } ``` 请注意,保持弹窗的用户体验很重要,因此应提供一种机制让用户可以关闭这个弹窗,同时遵守Android的权限和设计指南。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值