Android学习笔记之PendingIntent

一、什么是PendingIntent

所谓的 PendingIntent 是区别于 Intent 而存在的。Intent(即意图)是立即发生的,而 PendingIntent 是在将来的某个时刻发生的。

二、获取PendingIntent的主要方法

PendingIntent 支持三种待定意图:启动Activity,启动Service,发送广播,对应着如下三种方法:

  1. PendingIntent.getActivity(Context context,int requestCode,Intent intent,int flags),该待定意图发生时,效果相当于Context.startActivity(Intent)
  2. PendingIntent.getService(Context context,int requestCode,Intent intent,int flags),该待定意图发生时,效果相当于Context.startService(Intent)
  3. PendingIntent.getBroadcast(Context context,int requestCode,Intent intent,int flags),该待定意图发生时,效果相当于Context.sendBroadcast(Intent)

三、获取PendingIntent实例的第四个参数解析

PendingIntent的第四个参数为int类型的flags,它可以有四个取值,分别是:

FLAG_ONE_SHOT,FLAG_NO_CREATE,FLAG_CANCEL_CURRENT,FLAG_UPDATE_CURRENT。

除此之外,我们还可以传入0,这意味着我们不使用任何一种flag去控制PendingIntent的创建。

3.1.什么叫相同的PendingIntent

PendingIntent重写了equals方法,如果我们说两个PendingIntent是相同的,那么也就是说,它们封装的Intent是相同的并且requestCode也是相同的。注意,这里我们说的Intent相同并不是说是相同的Intent对象,而是指两个intent具有相同的action、data、categories、components、type和flags(这个flags是intent的flags)。因为在比较PendingIntent中封装的intent时,调用的是Intent的filterEquals方法,而该方法认为只要两个intent具有相同的action、data、categories、components、type、flags就认为它们两个是相同的。

PS:Intent并没有重写equals方法,所以如果使用Intent的equals方法比较两个intent对象的话,比较的是两个对象的内存地址。

3.2.各个flag的功能

好了,在理解了什么是相同的PendingIntent之后,我们就可以来看看各个flag的说明到底是啥意思

FLAG_CANCEL_CURRENT:如果要创建的PendingIntent已经存在了,那么在创建新的PendingIntent之前,原先已经存在的PendingIntent中的intent将不能使用(换言之,在所有相同的PendingIntent中只有最新的那个可以使用)

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

FLAG_ONE_SHOT:相同的PendingIntent只能使用一次,且遇到相同的PendingIntent时不会去更新PendingIntent中封装的Intent的extra部分的内容(换言之,在所有相同的PendingIntent中只有第一个被使用的生效,其余不生效)

FLAG_UPDATE_CURRENT:如果要创建的PendingIntent已经存在了,那么在保留原先PendingIntent的同时,将原先PendingIntent封装的Intent中的extra部分替换为现在新创建的PendingIntent的intent中extra的内容(换言之,所有相同的PendingIntent 都会更新Extra的内容与最新的保持一致,并且都可以使用)

测试场景:有两个按钮(记为按钮A,按钮B)都可以发出一条通知,通知里面封装的Intent都是跳转到新的Activity(NotificationActivity),NotificationActivity会解析Intent中Extra的数据,并加以显示。代码如下:

Intent intentA = new Intent(this,NotificationActivity.class);
intentA.putExtra("name","AAA");
Intent intentB = new Intent(this,NotificationActivity.class);
intentB.putExtra("name","BBB");
PendingIntent piA = PendingIntent.getActivity(this,1,intentA,0);
PendingIntent piB = PendingIntent.getActivity(this,1,intentB,PendingIntent.FLAG_CANCEL_CURRENT);
case R.id.btn_send_a:
    notification = new NotificationCompat.Builder(this,"subscribe")
            .setContentTitle("订阅标题A")
            .setContentText("订阅内容A")
            .setWhen(System.currentTimeMillis())
            .setSmallIcon(R.drawable.ic_launcher_round)
            .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher_round))
            .setAutoCancel(true)
            .setContentIntent(piA)
            .build();
    notificationManager.notify(3,notification);
    break;
case R.id.btn_send_b:
    notification = new NotificationCompat.Builder(this,"subscribe")
            .setContentTitle("订阅标题B")
            .setContentText("订阅内容B")
            .setWhen(System.currentTimeMillis())
            .setSmallIcon(R.drawable.ic_launcher_round)
            .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher_round))
            .setAutoCancel(true)
            .setContentIntent(piB)
            .build();
    notificationManager.notify(4,notification);
    break;

NotificationActivity中的TextView用来展示Intent中Extra的内容:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.notification_layout);
    TextView textView = (TextView) findViewById(R.id.textView);
    String text = getIntent().getStringExtra("name");
    Log.d("NotificationActivity", "text: "+text);
    if(text!=null){
        textView.setText(text);
    }
}

1.当我们把PendingIntentA的flag设置为0,PendingIntentB的flag设置为FLAG_CANCEL_CURRENT时:

创建PendingIntentB的时候发现PendingIntentA与其相同,因此PendingIntentA中的Intent失效,运行结果为:按钮A发出的通知点击之后不发生跳转,直接回到MainActivity,通知消失;按钮B发出的通知点击之后跳转到NotificationActivity,显示文本为BBB,通知消失。

2.当我们把PendingIntentA的flag设置为FLAG_NO_CREATE,PendingIntentB的flag设置为0时:

创建PendingIntentA的时候发现PendingIntentA尚未创建,根据FLAG_NO_CREATE控制模式,不会创建PendingIntentA,直接返回null,运行结果为:按钮A发出的通知点击之后无任何现象,通知仍然存在。按钮B发出的通知点击之后跳转到NotificationActivity,显示文本为BBB,通知消失。

3.当我们把PendingIntentA和PendingIntentB的flag均设置为FLAG_ONE_SHOT时:

创建PendingIntentB的时候发现PendingIntentA与其相同,因此不会替换Intent中Extra的内容(保持为“AAA”),但仍会完成PendingIntentB的创建,并且二者只有第一个被点击的通知能使用Intent跳转,运行结果为:当通知A和通知B同时存在时(同时出现在状态栏),先点击通知A会跳转到NotificationActivity,显示文本为AAA,通知消失,然后点击通知B,不发生跳转,通知消失;如果先点击通知B仍会跳转到NotificationActivity,显示文本为AAA,通知消失,再点击通知A,不发生跳转,通知消失。

4.当我们把PendingIntentA的flag设置为0,PendingIntentB的flag设置为FLAG_UPDATE_CURRENT时:

创建PendingIntentB的时候发现PendingIntentA与其相同,保留PendingIntentA的同时替换掉Intent中Extra的内容(变为“BBB”),运行结果为:不论点哪一个按钮发出的通知,都会跳转到NotificationActivity,显示文本为BBB,通知消失。

你可能感兴趣的:(Android)