一文彻底玩转Android通知栏消息通知

Posted 我想月薪过万

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一文彻底玩转Android通知栏消息通知相关的知识,希望对你有一定的参考价值。

消息渠道

Google为什么要引入消息渠道这个,因为在之前版本的android通知管理中,通知消息要么全部接收,要么全部屏蔽,然而消息渠道改变了这一特点。

就是每条通知都要属于一个对应的渠道。每个App都可以自由地创建当前App拥有哪些通知渠道,但是这些通知渠道的控制权都是掌握在用户手上的。用户可以自由地选择这些通知渠道的重要程度,是否响铃、是否振动、或者是否要关闭这个渠道的通知。

以小米手机上的微信为例

API介绍

不带 channelId 已被废弃,慎用!!!

当然,Google也并没有完全做绝,即使方法标为了废弃,但还是可以正常使用的。可是如果你将项目中的targetSdkVersion指定到了26或者更高,那么Android系统就会认为你的App已经做好了8.0系统的适配工作,当然包括了通知栏的适配。这个时候如果还不使用通知渠道的话,那么你的App的通知将完全无法弹出。因此这里给大家的建议就是,一定要适配。

创建通知渠道

package com.wust.notifydemo;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationCompat;

import android.annotation.TargetApi;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.Build;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity 

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initNotificationChannel();
    

    /**
     * 初始化消息渠道
     */
    private void initNotificationChannel() 
        // 要确保的是当前手机的系统版本必须是Android 8.0系统或者更高,
        // 因为低版本的手机系统并没有通知渠道这个功能,
        // 不做系统版本检查的话会在低版本手机上造成崩溃。
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) 
            // 创建一个通知渠道至少需要渠道ID、渠道名称以及重要等级这三个参数
            // 渠道ID可以随便定义,只要保证全局唯一性就可以
            String channelId = "chat";
            // 渠道名称是给用户看的,需要能够表达清楚这个渠道的用途
            String channelName = "聊天消息";
            // 重要等级的不同则会决定通知的不同行为,重要等级还可以设置为IMPORTANCE_LOW、IMPORTANCE_MIN,分别对应了更低的通知重要程度。
            int importance = NotificationManager.IMPORTANCE_HIGH;
            createNotificationChannel(channelId, channelName, importance);

            channelId = "subscribe";
            channelName = "订阅消息";
            importance = NotificationManager.IMPORTANCE_DEFAULT;
            createNotificationChannel(channelId, channelName, importance);
        
    

    @TargetApi(Build.VERSION_CODES.O)
    private void createNotificationChannel(String channelId, String channelName, int importance) 
        // 创建 channel
        NotificationChannel channel = new NotificationChannel(channelId, channelName, importance);
        // 获取 notificationManager
        NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        // 注册 channel
        notificationManager.createNotificationChannel(channel);
    

运行代码,可以在 对应应用的 应用信息 =》 通知管理  =》 通知类别下看到我们创建的两个 channel ,效果如下:

刚才我们创建的两个通知渠道这里已经显示出来了。可以看到,由于这两个通知渠道的重要等级不同,通知的行为也是不同的,聊天消息可以发出提示音并在屏幕上弹出通知,而订阅消息只能发出提示音。

当然,用户还可以点击进去对该通知渠道进行任意的修改,比如降低聊天消息的重要等级,甚至是可以完全关闭该渠道的通知。

至于创建通知渠道的这部分代码,你可以写在MainActivity中,也可以写在Application中,实际上可以写在程序的任何位置,只需要保证在通知弹出之前调用就可以了。并且创建通知渠道的代码只在第一次执行的时候才会创建,以后每次执行创建代码系统会检测到该通知渠道已经存在了,因此不会重复创建,也并不会影响任何效率。

发送通知

触发通知的代码和之前版本基本是没有任何区别的,只是在构建通知对象的时候,需要多传入一个通知渠道ID,表示这条通知是属于哪个渠道的。

  • 布局文件
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btn_send_chat"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送聊天消息"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn_send_subscribe"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="发送订阅消息"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btn_send_chat" />

</androidx.constraintlayout.widget.ConstraintLayout>
  • 发送消息逻辑
btn_send_chat.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                //第一步:获取 NotificationManager
                NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                //第二步:创建
                Notification notification = new NotificationCompat.Builder(MainActivity.this, "chat")
                        .setContentTitle("收到一条聊天消息")
                        .setContentText("在干嘛呢?")
                        .setWhen(System.currentTimeMillis())
                        .setSmallIcon(R.drawable.bb)
                        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.bb))
                        .setAutoCancel(true)
                        .build();
                //第三步:发送
                notificationManager.notify(1, notification);
            
        );

        btn_send_subscribe.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                //第一步:获取 NotificationManager
                NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                //第二步:创建
                Notification notification = new NotificationCompat.Builder(MainActivity.this, "subscribe")
                        .setContentTitle("收到一条订阅消息")
                        .setContentText("你买的彩票中了2个亿?")
                        .setWhen(System.currentTimeMillis())
                        .setSmallIcon(R.drawable.bb)
                        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.bb))
                        .setAutoCancel(true)
                        .build();
                //第三步:发送
                notificationManager.notify(2, notification);
            
        );

管理通知渠道

btn_send_chat.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View view) 
                //第一步:获取 NotificationManager
                NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
                //第四步:检测 "chat" 这个通道的消息等级
                if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) 
                    NotificationChannel channel = notificationManager.getNotificationChannel("chat");
                    if (channel.getImportance() != NotificationManager.IMPORTANCE_HIGH) 
                        Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
                        intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
                        intent.putExtra(Settings.EXTRA_CHANNEL_ID, channel.getId());
                        startActivity(intent);
                        Toast.makeText(MainActivity.this, "请手动将通知打开", Toast.LENGTH_SHORT).show();
                    
                
                //第二步:创建
                Notification notification = new NotificationCompat.Builder(MainActivity.this, "chat")
                        .setContentTitle("收到一条聊天消息")
                        .setContentText("在干嘛呢?")
                        .setWhen(System.currentTimeMillis())
                        .setSmallIcon(R.drawable.bb)
                        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.bb))
                        .setAutoCancel(true)
                        .build();
                //第三步:发送
                notificationManager.notify(1, notification);
            
        );

测试条件:你将 聊天消息 重要程度 手动设置为 低,当你点击发送聊天消息的时候,代码会引导你设置聊天消息等级

显示未读角标

修改两个地方

第一是在创建通知渠道的时候,调用了NotificationChannel的setShowBadge(true)方法,表示允许这个渠道下的通知显示角标。第二是在创建通知的时候,调用了setNumber()方法,并传入未读消息的数量。

以上是关于一文彻底玩转Android通知栏消息通知的主要内容,如果未能解决你的问题,请参考以下文章

如何在通知选项卡中单击推送通知消息打开特定片段?

在android中按下通知时如何打开片段页面

当通知进入android时如何获取Bundle数据

有助于发送消息通知的 Android 的 Firebase 代码是啥? [复制]

Android 错误从通知转到片段

Android:单击片段中的按钮时如何通知活动? [复制]