8.0通知栏新增通知渠道

从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所示,在渠道详细界面可以设置渠道的提示音,震动,屏幕锁定时显示方式等。

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

图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);//取消注册广播
    }
}

源码下载

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页