我们使用的每个应用都有通知的功能,最常看到的就是 QQ 和微信了。通知是我们可以在应用的常规 UI 外部向用户显示的消息。当我们告知系统发出通知时,它将先以图标的形式显示在通知区域中。用户可以打开抽屉式通知栏查看通知的详细信息。 通知区域和抽屉式通知栏均是由系统控制的区域,用户可以随时查看。
通知区域中的通知:
抽屉式通知栏中的通知:
相信大家对这个样式都很熟悉了。
通知的目的是告知用户 App 事件。在平时的使用中,通知主要有以下几个作用:
所以我们在设计通知的时候要注意与用户交互和实时的任务提醒。
现在都是使用建造者模式来构建 Notification 对象,可以使用的分别有 Notification.Builder 和 NotificationCompat.Builder。由于 Notification.Builder 仅支持 Android 4.1及之后的版本,为了解决兼容性问题, Google 在 Android Support v4 中加入了 NotificationCompat.Builder 类。
Notification 对象必须包含以下内容:
除了以上三项,其它均为可选项。虽然如此,但还是应该给 Notification 设置一个点击事件,这样就可以直接跳转到 App 的某个 Activity 、启动一个 Service 或者发送一个 Broadcast。否则,Notification 仅仅只能起到通知的效果,而不能与用户交互。
当系统接收到通知时,可以通过震动、响铃、呼吸灯等多种方式进行提醒。
Notification.Builder 的其它方法:
在上面出现了 setSmallIcon() 和 setLargeIcon() 两个设置图标的,它们的不同在于当 setSmallIcon() 与 setLargeIcon() 同时存在时, smallIcon 显示在largeIcon的右下角;当只设置 setSmallIcon() 时, smallIcon 显示在左侧。
在不同的设备上,可能效果不同,同时使用只会出现大图标。
上面介绍了很多通知的方法,我们现在先来做一个最简单的通知:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//获取NotificationManager实例
final NotificationManager notifyManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.t2);
//实例化NotificationCompat.Builde并设置相关属性
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Title")
.setContentText("content").setLargeIcon(bitmap);
Button button = (Button) findViewById(R.id.click);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
notifyManager.notify(1, builder.build());
}
});
}
}
构建一个简单的通知,主要分为三步:
NotificationManager: 是状态栏通知的管理类,负责发通知、清除通知等。NotificationManager 是一个系统Service,必须通过 getSystemService() 方法来获取。
大家都应该知道应用一般发的通知被点击就会跳转到一个应用程序里,这样说不是就跟 Intent 一样了吗?其实说是给 Notification 加点击事件,就是使用 Intent,然后我们的点击就能触发 Intent,可以说这是通知的核心,我们来看看用什么方法实现。
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final NotificationManager notifyManager = (NotificationManager)
getSystemService(Context.NOTIFICATION_SERVICE);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.t2);
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("Title")
.setContentText("content")
.setLargeIcon(bitmap);
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pIntent);
Button button = (Button) findViewById(R.id.click);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
notifyManager.notify(1, builder.build());
}
});
}
}
在上面我们介绍方法的时候说到 setContentIntent(),这里就使用了,这个方法就是用来设置通知的 Intent 的,不过这里不能使用 Intent,而是使用 PendingIntent。
PendingIntent 是一种特殊的 Intent ,字面意思可以解释为延迟的 Intent,用于在某个事件结束后执行特定的 Action,这里就是当用户点击通知时,才会执行 Intent。
PendingIntent 是 Android 系统管理并持有的用于描述和获取原始数据的对象的标志(引用)。也就是说,即便创建该 PendingIntent 对象的进程被杀死了,这个 PendingItent 对象在其他进程中还是可用的。
日常使用中的短信、闹钟等都用到了 PendingIntent。
PendingIntent 主要可以通过以下三种方式获取:
//获取一个用于启动 Activity 的 PendingIntent 对象
public static PendingIntent getActivity(Context context, int requestCode, Intent intent, int flags);
//获取一个用于启动 Service 的 PendingIntent 对象
public static PendingIntent getService(Context context, int requestCode, Intent intent, int flags);
//获取一个用于向 BroadcastReceiver 广播的 PendingIntent 对象
public static PendingIntent getBroadcast(Context context, int requestCode, Intent intent, int flags)
pendingIntent 执行的操作实质上是参数传进来的 Intent 的操作,但是使用 pendingIntent 的目的在于它所包含的 Intent 的操作的执行需要满足某些条件。
PendingIntent 具有以下几种 flag:
我们刚刚只是跳转到本应用的 Activity 下,如果我们想要跳转到其它应用应该怎么做呢。
我们要启动另一个应用,最重要的是知道应用的包名,对于这个是比较容易获得的:
PackageManager pm = getPackageManager();
Intent intent = pm.getLaunchIntentForPackage("com.android.calculator2");
这是跳转到系统带的一个计算器上,使用这个还需要判断这个包的程序是否存在,这里就不做了。
上面跳转的例子中我们虽然点击了通知,但它并没有消失,根据平时我们使用其它软件的经验,这个通知已经取到了通知的作用,在点击后就应该让它消失,那该怎么取消呢。
要消除通知有几种方法:
如果你是通过 NotificationManager.notify(String tag, int id, Notification notify) 方法创建的通知,那么只能通过 cancel(String tag, int id) 方法才能清除对应的通知,调用 cancel(int id) 无效。
前面提到过 setAutoCancel() 必须是通知中被设置了 Intent 才会有效,我们在刚刚的例子中加上调用这个方法:
builder.setAutoCancel(true);
将 Notification 的 flags 变为 FLAG_AUTO_CANCEL,我们可以这么做:
Notification notification = builder.build();
notification.flags = Notification.FLAG_AUTO_CANCEL;
这里需要创建 Notification 实例,不能用 builder.build().flags 来设置。notify() 方法中的 Notification 也要设置为这个才能起到作用。
结束语:本文仅用来学习记录,参考查阅。