Android 课程笔记-创建通知不显示等问题两则

本以为能快速解决的作业,照着书本码完果真出了问题,没能让我顺利在课上解决啊。

Android 课程笔记

NotificationCompat

看到NotificationCompat,我就有种本能的抗拒(因为第一次作业也是在Compat上翻了车),不过之后都是直接用的模板没翻过车,我也就渐渐淡忘了被Compat支配的恐惧。

果不其然,这次Notification又出现了DEPRECATED(不推荐使用)。课上老师说Notification每个版本几乎都会重写时,我就有感觉这里可能会有点麻烦。果然麻烦还不是一点点,这篇文章的所有问题都是关于API等级26以上才有的,那些低版本的安卓入门教程可以扔一旁了。

Android开发者手册上是这么写的:
NotificationCompat.Builder(Context context)
This constructor was deprecated in API level 26.1.0. use NotificationCompat.Builder(Context, String) instead. All posted Notifications must specify a NotificationChannel Id.

啊啊啊,必须指定一个通知渠道

至此,IDE给 Notification.Builder() 划的删除线终于消失,不过您不会认为问题解决了吧?若只是照抄老教程代码后只给Builer添了个渠道ID,运行后会发现通知怎么不显示?看看上一行加粗字体,您会发现不对劲的地方,还有通知渠道需要配置。

参考文献

  1. AndroidStudio3.0更新到API26.0之后的Notification.Builder()的方法改变
  2. NotificationCompat.Builder

通知不显示

进入下一个问题,通知不显示。问题的原因在上一部分已经指出——API等级26开始所有的通知都必须分配到相应的渠道。

找到原因,那么我们贴出我们要新增的代码,解决这个问题

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//来自Android开发者文档
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
CharSequence name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, name, importance);
channel.setDescription(description);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = getSystemService(NotificationManager.class);
notificationManager.createNotificationChannel(channel);
}
}

再贴一段工程代码,引用自帮我解决这个问题大佬的博客,这个代码我没有自己运行,只是摘了其中两句,在我看来这个并没有完全按照最新官方建议写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
String id = "my_channel_01";    //渠道ID
String name="渠道名字";
notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
Notification notification = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel mChannel = new NotificationChannel(id, name, NotificationManager.IMPORTANCE_LOW);
Toast.makeText(this, mChannel.toString(), Toast.LENGTH_SHORT).show();
Log.i(TAG, mChannel.toString());
notificationManager.createNotificationChannel(mChannel);
notification = new Notification.Builder(this)
.setChannelId(id)
.setContentTitle("Title")
.setContentText("Content")
.setSmallIcon(R.mipmap.ic_launcher).build();
} else {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
.setContentTitle("Title")
.setContentText("Content")
.setSmallIcon(R.mipmap.ic_launcher)
.setOngoing(true)
.setChannel(id);//无效
notification = notificationBuilder.build();
}
notificationManager.notify(114514, notification);

至此,通知正常在抽屉式通知栏显示。

参考文献

  1. 解决Android 8.0 的Notification不显示问题
  2. 创建渠道并设置重要性

通知音与Icon

到了这一部分,应该没什么大问题了(不过这得看你对大问题的定义了,对于我/课程老师要求😂来说没啥问题了),不过还有些代码的有些变动需要在这里提下。

啊啊,我想起来一个,虽然无关但还是忍不住想提一下:使用R.string引用中文时由于某种原因可能会显示成编码,这时在前面加上getResource()就能恢复正常。

通知音效

创建消息渠道时要求选择通知目标发布渠道的importance,不同的importance对通知的功能做出不同程度的限制:

  • Urgent: Makes a sound and appears as a heads-up notification.
  • High: Makes a sound.
  • Medium: No sound.
  • Low: No sound and does not appear in the status bar.

所以如果使通知的重要性为低的话,通知音、Heads-up notification什么的就无法实现了。现在,所有对通知的设置都变为对消息渠道的设置,至于老版教程里对通知设置通知音什么的在高版本API中似乎都已经失效。如要设置音效,我现在只发现手动通过Android系统设置来设置某个消息渠道的默认通知音。(搞不好我作业里通知重要性也是那里手动设置的,光通过代码实现我还没琢磨出来)

如果要Heads-Up notification,代码中importance设为High即可,文档里面High是Makes a sound,但上文又说The notification channel has high importance on devices running Android 8.0 (API level 26) and higher.[2],实验结果是High即可。

Icon

根据[3],Large icon: This is optional (usually used only for contact photos; do not use it for your app icon) and set with setLargeIcon().不要在Large icon里放app icon。事实上,照抄老师课上代码在Large icon显示mipmap结果是显示Large icon的区域啥都不显示。这个的原因我也没能想明白。我换了个PNG就正常显示了。

参考文献

  1. Notification importance
  2. Heads-up notification
  3. Notification anatomy