Android 通知

通知(Notification)

通知是Android系统中比较有特色的一个功能,当某个应用程序希望向用户发出一些提示信息,而该应用程序又不在前台运行时,就可以借助通知来实现。发出一条通知后,手机最上方的状态栏中会显示一个通知的图标,下拉状态栏可以看到通知的详细内容。

基本用法
  • 1.用Context.getSystemService(Context.NOTIFICATION_SERVICE)获取到NotificationManager对通知管理

    1
    NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)
  • 2.大于android8.0版本的适配问题

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     // 大于Android 8.0的版本适配
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
    NotificationChannel notificationChannel = null;

    //注意,这里创建了渠道,三个参数分别为 渠道ID、渠道名称和重要等级,这里的渠道ID就是我们下面
    //创建builder对象时要对应一致的ID。
    notificationChannel = new NotificationChannel("unique", "TEST", NotificationManager.IMPORTANCE_HIGH);
    notificationChannel.enableLights(true); //LED灯
    notificationChannel.setLightColor(Color.YELLOW);
    manager.createNotificationChannel(notificationChannel);
    }
  • 3.用Builder构造器创建Notification对象,channelId用来表示消息通道的ID,需要和上面创建的渠道ID相同,如果传入了一个不存在的渠道ID,通知是无法显示出来的。

    1
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "unique");
  • 4.基本设置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    builder.setContentTitle("这是标题")
    .setAutoCancel(true)
    .setContentText("这是文本")
    .setContentInfo("这是内容")
    .setSubText("这是小字")
    .setTicker("滚动消息......")
    .setWhen(System.currentTimeMillis()) // 出现时间
    .setSmallIcon(R.mipmap.ic_launcher) //小图标
    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher)); // 大图标
  • 5.显示通知,第一个参数是自定义id(要保证每个通知的id都不同),第二个参数是notification对象

    1
    2
    Notification notification = builder.build();
    manager.notify(1, notification);
通知的响应
  • 通知的相应依赖于PendingIntent, 在某个合适的时机去执行某个动作(Intent更倾向于立刻执行某个动作)

  • PendingIntent提供了几个静态方法用于获取PendingIntent的实例,可以根据需求来选择是使用getActivity()方法、getBroadcast()方法还是getService()方法

    1
    PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
  • PendingIntent的4个参数:

    • 第一个参数:Context
    • 第二个参数:一般用不到,传入0即可
    • 第三个参数: Intent对象
    • 第四个参数:用于确定PendingIntent的行为,有FLAG_ONE_SHOT,FLAG_NO_CREATE,FLAG_CANCEL_CURRENT,FLAG_UPDATE_CURRENT 4个值可以选。但通常写0
  • 因此前面的NotificationCompat.Builder对象还有个方法:setContentIntent()方法,接收的参数正是一个PendingIntent对象

简单Demo
  • activity_main.xml:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <Button
    android:id="@+id/send_notice"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="发起通知"/>

    </LinearLayout>
  • MainActivity.java:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private Button button_sendNotice;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    button_sendNotice=findViewById(R.id.send_notice);
    button_sendNotice.setOnClickListener(this);
    }

    @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);
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this,"unique");
    builder.setContentTitle("这是标题")
    .setAutoCancel(true)
    .setContentText("这是文本")
    .setContentInfo("这是内容")
    .setSubText("这是小字")
    .setTicker("滚动消息......")
    .setWhen(System.currentTimeMillis()) //出现时间
    .setSmallIcon(R.mipmap.ic_launcher) //小图标
    .setContentIntent(pi)
    .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));//大图标
    // 大于Android 8.0的版本适配
    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
    NotificationChannel notificationChannel = null;
    notificationChannel = new NotificationChannel("unique", "TEST", NotificationManager.IMPORTANCE_HIGH);
    notificationChannel.enableLights(true); //LED灯
    notificationChannel.setLightColor(Color.YELLOW);
    manager.createNotificationChannel(notificationChannel);
    }
    Notification notification = builder.build();
    manager.notify(1,notification);
    break;
    }
    }
    }
  • activity_notification.xml:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".NotificationActivity">

    <TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="这是一个通知页面"/>
    </LinearLayout>
  • NotificationActivity.java

    1
    2
    3
    4
    5
    6
    7
    8
    public class NotificationActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_notification);
    }
    }
  • 运行结果:

让通知消失的两种方法
  • 1.在NotificationCompat.Builder中连缀一个setAutoCancel(true)方法,通知被点击后就会自动清除

    1
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "001").setAutoCancel(true);
  • 显式调用NotificationMangercancel()将它取消,cancel()接收一个参数是通知的id

    1
    2
    NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
    manager.cancel(1); //这个1是我们前面介绍通知时设的id
通知的进阶技巧
设置通知的音效:
1
builder.setSound(Uri.fromFile(new File("铃声路径")));
设置震动:(数组下标为偶数表示振动的毫秒数,奇数表示接着静止的毫秒数)
  • 需先添加权限:
1
<uses-permission android:name="android.permission.VIBRATE"/>
1
2
3
builder.setVibrate(new long[]{0, 1000, 1000, 1000});
// 8.0 以上:
channel.setVibrationPattern(new long[]{0});//通道来控制震动
显式长文字
1
2
3
4
5
6
7
builder.setStyle(new NotificationCompat.BigTextStyle().bigText("唧唧复唧唧,木兰当户织。不闻机杼声,惟闻女叹息。\n" +
"问女何所思,问女何所忆。女亦无所思,女亦无所忆。昨夜见军帖,可汗大点兵,军书十二卷,卷卷有爷名。阿爷无大儿,木兰无长兄,愿为市鞍马,从此替爷征。\n" +
"东市买骏马,西市买鞍鞯,南市买辔头,北市买长鞭。旦辞爷娘去,暮宿黄河边,不闻爷娘唤女声,但闻黄河流水鸣溅溅。旦辞黄河去,暮至黑山头,不闻爷娘唤女声,但闻燕山胡骑鸣啾啾。\n" +
"万里赴戎机,关山度若飞。朔气传金柝,寒光照铁衣。将军百战死,壮士十年归。\n" +
"归来见天子,天子坐明堂。策勋十二转,赏赐百千强。可汗问所欲,木兰不用尚书郎,愿驰千里足,送儿还故乡。\n" +
"爷娘闻女来,出郭相扶将;阿姊闻妹来,当户理红妆;小弟闻姊来,磨刀霍霍向猪羊。开我东阁门,坐我西阁床,脱我战时袍,著我旧时裳。当窗理云鬓,对镜帖花黄。出门看火伴,火伴皆惊忙:同行十二年,不知木兰是女郎。\n" +
"雄兔脚扑朔,雌兔眼迷离;双兔傍地走,安能辨我是雄雌?"))

显示图片
1
builder.setStyle(new NotificationCompat.BigPictureStyle().bigPicture(BitmapFactory.decodeResource(getResources(), R.drawable.cat)))

设置重要程度:
1
builder.setPriority(NotificationCompat.PRIORITY_MAX)
0%