Android通知(Notification)中使用PendingIntent
如果你使用过Android手机,此时应该会下意识地认为这条通知是可以点击的。但是当你去点击它的时候,你会发现没有任何效果。不对啊,好像每条通知点击之后都应该会有反应的呀?其实要想实现通知的点击效果,我们还需要在代码中进行相应的设置,这就涉及了一个新的概念:PendingIntent。
PendingIntent从名字上看起来就和Intent有些类似,它们之间也确实存在着不少共同点。比如它们都可以去指明某一个“意图”,都可以用于启动活动、启动服务以及发送广播等。不同的是,Intent更加倾向于去立即执行某个动作,而PendingIntent更加倾向于在某个合适的时机去执行某个动作。所以,也可以把PendingIntent简单地理解为延迟执行的Intent。
PendingIntent的用法同样很简单,它主要提供了几个静态方法用于获取PendingIntent的实例,可以根据需求来选择是使用getActivity()方法、getBroadcast()方法,还是getService()方法。这几个方法所接收的参数都是相同的,第一个参数依旧是Context,不用多做解释。第二个参数一般用不到,通常都是传入0即可。第三个参数是一个Intent对象,我们可以通过这个对象构建出PendingIntent的“意图”。第四个参数用于确定PendingIntent的行为,有FLAG_ONE_SHOT、FLAG_NO_CREATE、FLAG_CANCEL_CURRENT和FLAG_UPDATE_CURRENT这4种值可选,每种值的具体含义你可以查看文档,通常情况下这个参数传入0就可以了。
对PendingIntent有了一定的了解后,我们再回过头来看一下NotificationCompat.Builder。这个构造器还可以再连缀一个setContentIntent()方法,接收的参数正是一个PendingIntent对象。因此,这里就可以通过PendingIntent构建出一个延迟执行的“意图”,当用户点击这条通知时就会执行相应的逻辑。
现在我们来优化一下NotificationTest项目,给刚才的通知加上点击功能,让用户点击它的时候可以启动另一个活动。
首先需要准备好另一个活动,右击com.example.notificationtest包→New→Activity→EmptyActivity,新建NotificationActivity,布局起名为notification_layout。然后修改notification_layout.xml中的代码,如下所示:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="24sp"
android:text="This is notification layout"
/>
</RelativeLayout>
这样就把NotificationActivity这个活动准备好了,下面我们修改MainActivity中的代码,给通知加入点击功能,如下所示:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
...
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.send_notice:
Intent intent = new Intent(this, NotificationActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
NotificationManager manager = (NotificationManager) getSystemService
(NOTIFICATION_SERVICE);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("This is content title")
.setContentText("This is content text")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher))
.setContentIntent(pi)
.build();
manager.notify(1, notification);
break;
default:
break;
}
}
}
可以看到,这里先是使用Intent表达出我们想要启动NotificationActivity的“意图”,然后将构建好的Intent对象传入到PendingIntent的getActivity()方法里,以得到PendingIntent的实例,接着在NotificationCompat.Builder中调用setContentIntent()方法,把它作为参数传入即可。
现在重新运行一下程序,并点击Send notice按钮,依旧会发出一条通知。然后下拉系统状态栏,点击一下该通知,就会看到NotificationActivity这个活动的界面了,如图所示:
咦?怎么系统状态上的通知图标还没有消失呢?是这样的,如果我们没有在代码中对该通知进行取消,它就会一直显示在系统的状态栏上。
**解决的方法有两种:**一种是在NotificationCompat.Builder中再连缀一个setAutoCancel()方法,一种是显式地调用NotificationManager的cancel()方法将它取消,两种方法我们都学习一下。
第一种方法写法如下:
Notification notification = new NotificationCompat.Builder(this)
...
.setAutoCancel(true)
.build();
可以看到,setAutoCancel()方法传入true,就表示当点击了这个通知的时候,通知会自动取消掉。
第二种方法写法如下:
public class NotificationActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.notification_layout);
NotificationManager manager = (NotificationManager) getSystemService
(NOTIFICATION_SERVICE);
manager.cancel(1);
}
}
这里我们在cancel()方法中传入了1,这个1是什么意思呢?还记得在创建通知的时候给每条通知指定的id吗?当时我们给这条通知设置的id就是1。因此,如果你想取消哪条通知,在cancel()方法中传入该通知的id就行了。
如果对你有帮助,就一键三连呗(关注+点赞+收藏),我会持续更新更多干货~~