欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

8.0通知栏新增通知渠道

程序员文章站 2024-03-17 14:31:22
...

从Android 8.0(API级别26)开始,所有通知必须要分配一个渠道,对于每个渠道,可以单独设置视觉和听觉行为。然后用户可以在设置中修改这些设置,根据应用程序来决定哪些通知可以显示或者隐藏。

创建通知渠道之后,程序无法修改通知行为,创建之后只有用户可以修改,程序只能修改渠道名称跟渠道描述。

我们可以为一个应用程序创建多个通知渠道,不同的通知类型用不同的渠道。例如重要通知用一个渠道,可以为这个渠道重要性设置成最高,不怎么重要的通知用一个渠道,这个渠道重要性设置成最低。

创建一个通知

要创建一个通知,有以下几个步骤:
1. 构造NotificationChannel对象,构造方法有三个参数:渠道id、渠道名称、渠道重要性级别。
2. 调用NotificationChannel.setDescription方法可以设置渠道描述。这个描述在系统设置中可以看到。
3. 调用NotificationManager.createNotificationChannel方法创建通知渠道。

以下是注册通知渠道的代码,记得先判断版本号是不是大于或者等于8.0,因为只有8.0以上才有通知渠道API。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    //创建通知渠道
    CharSequence name = "渠道名称1";
    String description = "渠道描述1";
    String channelId="channelId1";//渠道id     
    int importance = NotificationManager.IMPORTANCE_DEFAULT;//重要性级别
    NotificationChannel mChannel = new NotificationChannel(channelId, name, importance);
    mChannel.setDescription(description);//渠道描述
    mChannel.enableLights(true);//是否显示通知指示灯
    mChannel.enableVibration(true);//是否振动

    NotificationManager notificationManager = (NotificationManager) getSystemService(
            NOTIFICATION_SERVICE);
    notificationManager.createNotificationChannel(mChannel);//创建通知渠道
}

创建通知渠道不会执行任何操作,所以在启动应用程序时调用以上代码最好。

执行以上代码,就能在设置->应用和通知->选择当前app->应用通知,在应用通知界面就能看到创建的通知渠道,如图1-1所示,可以单独开关当前的通知类别,还可以点击当前渠道,进入渠道详细界面,如图1-2所示,在渠道详细界面可以设置渠道的提示音,震动,屏幕锁定时显示方式等。

8.0通知栏新增通知渠道

图1-1 单个app通知所有渠道列表

8.0通知栏新增通知渠道

图1-2 渠道详细界面

默认情况下,通知的震动还有声音提示都是由NotificationManagerCompat类中重要性级别决定的,例如常量IMPORTANCE_DEFAULT和IMPORTANCE_HIGH,后面我们会讲到这些常量的具体作用。

如果你想改变该渠道的默认通知,可以调用NotificationChannel对象的方法进行修改。以下介绍了几个常用的方法:
- enableLights() 是否显示通知指示灯
- setLightColor() 设置通知灯颜色
- setVibrationPattern() 设置振动模式

注意:一旦创建了渠道,调用以上方法就会无效,只有用户在设置中才能修改。

上面那段代码只告诉了我们创建渠道,下面这段代码让我们在之前创建的渠道上发送一个通知。

//第二个参数与channelId对应
Notification.Builder builder = new Notification.Builder(this,channelId);
//icon title text必须包含,不然影响桌面图标小红点的展示
builder.setSmallIcon(android.R.drawable.stat_notify_chat)
        .setContentTitle("通知渠道1->标题")
        .setContentText("通知渠道1->内容")
        .setNumber(3); //久按桌面图标时允许的此条通知的数量

Intent intent=new Intent(this,NotificationActivity.class);
PendingIntent ClickPending = PendingIntent.getActivity(this, 0, intent, 0);
builder.setContentIntent(ClickPending);

notificationManager.notify(id,builder.build());

用Notification.Builder构造通知对象时,传入第二个参数就是渠道id,用这个渠道id就能跟我们之前创建的渠道进行关联。设置内容跟发送系统通知代码跟之前类似。运行以上代码就能在8.0的手机上显示通知了。

设置渠道重要性级别

渠道重要性级别影响该渠道中所有通知的显示,在创建NotificationChannel对象的构造方法中必须要指定级别,一共有5个重要性界别,范围从 IMPORTANCE_NONE(0)至 IMPORTANCE_HIGH(4),如表1所示。

用户可见的重要性级别 重要性(Android 8.0及更高版本)
紧急(发出声音并显示为提醒通知) IMPORTANCE_HIGH
高(发出声音) IMPORTANCE_DEFAULT
中等(没有声音) IMPORTANCE_LOW
低(无声音并且不会出现在状态栏中) IMPORTANCE_MIN

表1-1 渠道重要级别

查看渠道设置

我们都知道渠道创建之后不能通过代码修改,但是可以先查看该渠道的振动和声音等行为,如果需要修改,可以根据返回的内容再提示用户手动去打开。
1. 调用NotificationManager.getNotificationChannel(String channelId)方法获取NotificationChannel对象,这个方法有个参数渠道id。
2. 有了NotificationChannel对象就能调用getVibrationPattern、getSound、getImportance等方法。

示例代码如下所示:

NotificationChannel notificationChannel=notificationManager.getNotificationChannel(channelId);
long[] vibrationPattern=notificationChannel.getVibrationPattern();//震动模式
if(vibrationPattern!=null){
    Log.i("ansen","震动模式:"+vibrationPattern.length);
}

Uri uri=notificationChannel.getSound();//通知声音
Log.i("ansen","通知声音:"+uri.toString());

int importance=notificationChannel.getImportance();//通知等级
Log.i("ansen","通知等级:"+importance);

打开通知渠道设置

创建渠道之后,代码无法去修改这个渠道的行为,只有用户去设置中进行修改,为了让用户更快的找到当前渠道,可以Intent使用ACTION_CHANNEL_NOTIFICATION_SETTINGS打开通知渠道的系统设置。

以下代码打开通知渠道的设置界面:

Intent channelIntent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
channelIntent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());
channelIntent.putExtra(Settings.EXTRA_CHANNEL_ID,channelId);//渠道id必须是我们之前注册的
startActivity(channelIntent);

需要传入两个参数,应用程序的包名跟渠道id。

删除通知渠道

调用deleteNotificationChannel(String channelId)方法删除渠道,代码如下所示:

NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.deleteNotificationChannel(channelId);

8.0通知栏点击通知发送广播

前面的案例我们点击通知栏都是跳转到指定Activity,但是PendingIntent除了getActivity方法之外,还有getBroadcast跟getService。可以点击通知发送广播,开启Service。

于是我们修改显示通知的代码:

String BROADCAST_ACTION="android.intent.action.BROADCAST_ACTION";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//第二个参数与channelId对应
Notification.Builder builder = new Notification.Builder(this,channelId);
//icon title text必须包含,不然影响桌面图标小红点的展示
builder.setSmallIcon(android.R.drawable.stat_notify_chat)
        .setContentTitle("通知渠道1->标题")
        .setContentText("通知渠道1->内容")
        .setNumber(3); //长按桌面图标时允许的此条通知的数量

Intent intent = new Intent(BROADCAST_ACTION);
intent.putExtra("data","12345");//带上参数
PendingIntent pendingIntent = PendingIntent.getBroadcast(this,id,intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pendingIntent);
builder.setAutoCancel(true);

mNotificationManager.notify(id,builder.build());
}

新建Intent对象的时候就传入了一个action,同时给Intent传入一个字符串参数,然后调用PendingIntent.getBroadcast构造PendingIntent对象,最后调用notify方法显示通知。

新建一个类DynamicBroadcast,继承BroadcastReceiver,用来接收通知栏点击时发送的广播。在onReceive方法中打印一下我们传入的参数。

public class DynamicBroadcast extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent){
        String data = intent.getStringExtra("data");
        Log.i("data",data);
    }
}

前面的内容我们讲了广播的两种注册方式,静态注册跟动态注册,这里我们使用静态注册,在AndroidManifest.xml文件中application标签中增加如下代码:

<receiver android:name=".DynamicBroadcast"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.BROADCAST_ACTION" />
    </intent-filter>
</receiver>

运行之后发现在Android8.0版本以下的手机正常,点击通知栏会打印广播的日志,但是在Android8.0版本或以上版本点击通知栏发现就没收到广播,我以为是8.0增加了通知渠道的问题,后面查看官网API,在Broadcasts类下面看到了这句话:

Beginning with Android 8.0 (API level 26), the
system imposes additional restrictions on
manifest-declared receivers. If your app targets
API level 26 or higher, you cannot use the manifest
to declare a receiver for most implicit broadcasts
(broadcasts that do not target your app
specifically).

大概意思是从Android8.0API级别26)开始,无法在AndroidManifest.xml文件中声明隐式广播,系统的隐式广播正常使用。

所以呢如果你的手机是Android8.0以上版本的,就需要动态注册广播,这样才能接收到通知栏点击时发送的广播。

注释掉AndroidManifest.xml文件中声明的广播,然后在MainActivity的onCreate方法中注册广播,代码如下:

//动态注册广播
dynamicBroadcast=new DynamicBroadcast();
IntentFilter intentFilter=new IntentFilter(BROADCAST_ACTION);
registerReceiver(dynamicBroadcast,intentFilter);

静态注册的广播一定要在onDestroy方法中进行反注册:

@Override
protected void onDestroy() {
    super.onDestroy();

    if(dynamicBroadcast!=null){
        unregisterReceiver(dynamicBroadcast);//取消注册广播
    }
}

源码下载