通知(Notification)是Android系统中一个特色功能,当某个应用程序希望向用户发出一些提示信息,而该应用程序又不在前台运行时,就可以借助通知来实现。发出一条通知后,手机最上方的状态中会显示一个通知的图标,下拉状态栏可以看到详细的内容。
通知的基本用法
通知既可以在活动中创建,也可以在广播接收器中创建,也可以在服务中创建。相比于在广播接收器和服务,在活动中创建通知的场景还是比较少的,因为一般只有当程序进入后台的时候我们才需要使用通知;
创建通知的详细步骤:
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.support.v4.app.NotificationCompat;
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder ;
int channelId = 1 ;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ //Android 8.0以上适配
NotificationChannel channel = new NotificationChannel(String.valueOf(channelId),"channel_name",
NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(channel);
builder = new NotificationCompat.Builder(this,String.valueOf(channelId));
}else{
builder = new NotificationCompat.Builder(this);
}
builder.setContentTitle("this is content title") //指定通知栏的标题内容
.setContentText("this is content text") //通知的正文内容
.setWhen(System.currentTimeMillis()) //通知创建的时间
.setSmallIcon(R.drawable.ic_launcher_background) //通知显示的小图标,只能用alpha图层的图片进行设置
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher_background));
Notification notification = builder.build() ;
manager.notify(channelId,notification);
现在将这段代码在Activity中进行运行,看看效果:
package com.sl.demo;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Handler;
import android.support.v4.app.NotificationCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
createNofication();
}
},2000);
}
private void createNofication(){
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder ;
int channelId = 1 ;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){ //Android 8.0适配
NotificationChannel channel = new NotificationChannel(String.valueOf(channelId),
"channel_name",
NotificationManager.IMPORTANCE_HIGH);
manager.createNotificationChannel(channel);
builder = new NotificationCompat.Builder(this,String.valueOf(channelId));
}else{
builder = new NotificationCompat.Builder(this);
}
builder.setContentTitle("this is content title") //指定通知栏的标题内容
.setContentText("this is content text") //通知的正文内容
.setWhen(System.currentTimeMillis()) //通知创建的时间
.setSmallIcon(R.drawable.ic_launcher_background) //通知显示的小图标,只能用alpha图层的图片进行设置
.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher_background));
Notification notification = builder.build() ;
//channelId为本条通知的id
manager.notify(channelId,notification);
}
}
运行效果为:
我们在使用Android手机时,当通知栏出现通知时,基本上都可以点击的,而现在如果点击我们创建的这条通知,是没有任何效果的,而要让其有点击效果,我们就需要对代码进行设置,现在就涉及了一个新概念:PendingIntent
PendingIntent和Intent从名字上看有些类似,他们这件确实存在着不少共同点。如,它们都可以去指明某一个“意图”,都可以用于启动活动、启动服务以及发送广播等。不同的是,Intent更加倾向于去立即执行某个动作,而PendingIntent更加倾向于在某个合适的时机去执行某个动作。所以,也可以把PendingIntent理解为延迟执行的Intent;
PendingIntent的用法,它主要提供了几个静态方法用户获取PendingIntent的实例
- getActivity(Context context,int requestCode,Intent intent,int flag):跳转到一个Activity组件
- getBroadcast(Context context,int requestCode,Intent intent,int flag):打开一个广播组件
- getService(Context context,int requestCode,Intent intent,int flag):打开一个服务组件
这几个方法的参数解释
- Context就不做解释
- 第二个参数requestCode一般用不到,通常传入0即可
- 第三个参数是一个Intent对象,我们可以通过这个对象构建出PendingIntent的“意图”
- 第四个参数int flag,用于确定PendingIntent的行为,有FLAG_ONE_SHOT,FLAG_NO_CREATE,FLAG_CANCEL_CURRENT和FLAG_UPDATE_CURRENT这4中值可选。
先看看flag的几个主要常量
- FLAG_CANCEL_CURRENT:如果当前系统中已经存在一个PendingIntent对象,那么先将已有的PendingIntent取消,然后重新生成一个PendingIntent对象。(测试发现,多个通知的channelId不同,PendingIntent内容相同时,只有最后发送的通知的PendingIntent有效,即点击事件有效)
- FLAG_NO_CREATE:如果当前系统中不存在相同的PendingIntent对象,系统将不会创建该PendingIntent而是直接返回null。
- FLAG_ONE_SHOT:该PendingIntent只作用一次(测试发现两个id不同但PendingIntent内容相同的通知,只要点击了其中一个,当再次点击时发现两个通知的点击事件都已经无效)
- FLAG_UPDATE_CURRENT:①requestCode相同时:如果系统中有一个和你描述的PendingIntent对等的PendingIntent,那么系统将使用该PendingIntent对象,但是会使用新的Intent来更新之前PendingIntent中的Intent对象数据,例如Intent中的Extras ; ②requestCode不同时:PendingIntent为设置的内容,不会进行改变
现在在程序中新建一个Actitvity为NotificationActivity,修改刚才的代码,创建PendingIntent并添加点击事件
Intent intent = new Intent(this,NotificationActivity.class);
PendingIntent pi = PendingIntent.getActivity(this,0,intent,0);
builder...
.setContentIntent(pi);
现在再点击通知栏时,则程序会跳转到NotificationActivity的界面中;但是,发现点击后通知栏还是存在,并没有取消,其实取消通知栏显示有两种方法;
第一种为在NotificationCompat.Builder中再连缀一个方法,setAutoCancel(true),就是当通知栏被点击时取消该条通知,如:
builder....
.setAutoCancel(true); //点击通知后,自动取消
第二种为手动取消通知,我们可以在通知对应的点击后操作的步骤中手动取消通知,如:
public class NotificationActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notification);
//手动调用取消通知,其中cancel(1)中的1表示想取消通知的id
((NotificationManager)getSystemService(NOTIFICATION_SERVICE)).cancel(1);
}
}
通知的进阶技巧
好了,现在已经知道通知的创建、点击事件、取消通知,但是我们平常发现收到同志时会有震动、声音、Led灯闪烁,下面在看看如何进行设置;
- setSound():设置通知接收到时播放音频,我现在用的模拟器运行,在模拟器中有该文件存在
Notification notification = new Notification.Builder(this)....
.setSound(Uri.fromFile(new File("/system/media/audio/ringtones/Lyra.ogg")))
.build();
- setVibarate():设置震动,其参数为一个长整型数组,用于设置手机静止和震动的时长,以毫秒为单位。赋值规律为:静止时长、振动时长、静止时长、振动时长....,以此类推
Notification notification = new Notification.Builder(this)....
.setVibrate(new long[]{0,1000,1000,1000})
.build();
实现手机振动,还需要声明振动权限:
- setLights():设置LED灯,第一个参数设置LED灯颜色,第二个参数亮灯时长,第三个参数暗灯时长,如
Notification notification = new Notification.Builder(this)....
.setLights(Color.GREEN,1000,1000)
.build();
其实,如果不想进行这么多复杂的设置,也可以使用通知的默认效果,它会根据当前手机环境来决定播放什么铃声,以及如何振动,写法如下:
Notification notification = new Notification.Builder(this)....
.setDefaults(NotificationCompat.DEFAULT_ALL) //设置全部默认
.build();
Notification notification = new Notification.Builder(this)...
//设置默认声音和振动
.setDefaults(NotificationCompat.DEFAULT_SOUND|NotificationCompat.DEFAULT_VIBRATE)
.build();
通知的高级功能
NotificationCompat.Builder类有很多Api是我们没有用过的,现在我们看看setStyle()方法,这个方法允许我们构建出富文本的通知内容,也就是说通知中不管可以有文字和图标,还可以包含更多的东西。
- 在通知中显示一段长文字
Notification notification = new Notification.Builder(this)....
.setStyle(new NotificationCompat.BigTextStyle().bigText("setStyle()方法,
这个方法允许我们构建出富文本的通知内容"))
.build();
在模拟器测试时是直接显示为完全了,但在我的小米5显示时是没有显示完全的,只有当长按通知时才显示出来;
- 在通知中显示一张大图片
Notification notification = new Notification.Builder(this)....
.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(
BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher)))
.build();
在测试时发现setStyle只能设置一个,如果设置多个,最后一个会覆盖之前的。
- setPriority()方法,用于设置通知的重要程度,一共有五个值可选
- PRIORITY_DEFAULT:表示默认的重要程度,和不设置效果是一样的
- PRIORITY_MIN:表示最低的重要程度,系统只会在特定的场景才会显示这条通知,比如用户下拉状态栏时
- PRIORITY_LOW:表示较低的重要程度,系统可能将这类通知缩小,或改变其显示顺序,将其排在更重要的通知之后
- PRIORITY_HIGH:表示较高的重要程度,系统可能将这类通知放大,或改变其显示的顺序,将其排在比计较靠前的位置
- PRIORITY_MAX:表示最高的重要程度,这类通知消息必须要让用户立即看到,甚至需要用户做出响应操作
具体写法如下:
Notification notification = new Notification.Builder(this)....
.setPriority(NotificationCompat.PRIORITY_MAX)
.build();