当前位置:   article > 正文

Android弹出通知_安卓开发通知弹窗怎么实现

安卓开发通知弹窗怎么实现

发现把Android通知渠道的重要性设置为最高时,当发送通知时,通知能直接弹出来显示,以前一直搞不明白为什么别的app的通知可以弹出来,我的不行,搞了半天原来是这个属性在作怪,示例如下:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            registerForActivityResult(ActivityResultContracts.RequestPermission()) {
            }.launch(Manifest.permission.POST_NOTIFICATIONS)
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val importance = NotificationManager.IMPORTANCE_HIGH
            val channel = NotificationChannel("channel_id", "MyChannel", importance)
            channel.description = "This is my notification channel"
            NotificationManagerCompat.from(this).createNotificationChannel(channel)
        }

        val builder = NotificationCompat.Builder(this, "channel_id")
            .setSmallIcon(R.drawable.icon)
            .setContentTitle("这是通知标题")
            .setContentText("这是通知内容")

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
            NotificationManagerCompat.from(this).notify(1, builder.build())
        }
    }

}
  • 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

主要的是使用了NotificationManager.IMPORTANCE_HIGH常量,其它的随便怎么设置都不重要。运行效果如下:

在这里插入图片描述
如果手机有这个设置需要打开,如下:
在这里插入图片描述
这个选项默认是打开的。如果是关的话通知就不会弹出来。点击通知渠道名称还有一个 “允许打扰” 的选项,如下:
在这里插入图片描述
这个开关默认是关的,但是通知还是能弹出来,而且也有通知声音,振动没试过。在一台不知名的手机上,我试了设置免打扰模式,通知还是能弹出来,只是通知的声音没有了,打开 “允许打扰” 就可以听到通知声音了,这台手机是Android 11版本,可能做的不太规范。

在我的小米手机11pro(Android 13)上,通知设置的主页是这样的:

在这里插入图片描述
这个开关默认也是开的,点击通道名称(MyChannel)之后也有一个一样的权限,默认也是开的,如下:
在这里插入图片描述
当我把主页上的 “悬浮通知权限” 关闭后,通道里的这个开关就不见了,所以,通知主页上的所有开关都是app通知的总开关,对所有频道都生效,所以如果有多个通道频道的话可以针对不同的频道单独设置是否可以弹出通知,比如有一个Linphone应用,我查看它的通知是创建了4个频道的,如下:
在这里插入图片描述

  • Linphone 来电通知:用于显示来电。通过自定义通知的UI,可以在通知上显示接收听电话按钮。如果是平时我们自己做的话估计会使用Dialog来弹窗显示,原来用通知也能实现啊!那如何保持通知弹出来一直显示呢?直到用户点击接听或者挂断按钮。
  • Linphone 即时通讯通知:用于显示消息通知
  • Linphone 未接来电通知:用于显示未接来电
  • Linphone 服务通知:用于在保持应用长期在后台,所以这个服务是以前台服务开启的,这样就必须显示一个常驻消息栏的通知,通知的消息内容为:“若要在后台可接听电话这是必要的”。这个理由很不错,学习了,充分的理由让用户知道这个前台服务的功能,要不然用户可能会关闭掉这个服务(不知道是不是把通知一关服务就关掉了呢?待实验)。

为不同的使用场景创建不同的频道是个比较好的做法,以方便用户有更细的选择,比如,我觉得电话比较重要,我就可以打开 “Linphone 来电通知” 这个渠道中的悬浮窗权限,其它频道的全都关闭。

再来看看微信app的通知渠道:
在这里插入图片描述
可以看到,微信app创建了3个通知频道,一个用于接收新消息,一个用于下载,一个用于音视频通话,在微信app中,我们可以设置消息免打扰,如果我想把所有的微信群都设置为免打扰,无需在app内部设置,最快捷的办法就是在 “新消息通知” 这个通知频道中设置就可以了,比如把这个频道中的所有开关全部关掉,如下:
在这里插入图片描述
“允许通知” 是一个总开关,关掉这个,下面的所有功能都不可用,所以,我们也可以单独设置,比如设置震动,但是不允许声音,如下:
在这里插入图片描述
我发现微信的3个频道中,有两个频道的 “悬浮通知权限” 是开的,有一个是关闭的,这是什么API控制的呢?其实就是创建通知频道时的importance参数控制的,设置为NotificationManager.IMPORTANCE_DEFAULT它默认就是关的,设置为NotificationManager.IMPORTANCE_HIGH它默认就会是开的。所有的常量如下:

public static final int IMPORTANCE_NONE = 0;
public static final int IMPORTANCE_MIN = 1;
public static final int IMPORTANCE_LOW = 2;
public static final int IMPORTANCE_DEFAULT = 3;
public static final int IMPORTANCE_HIGH = 4;
public static final int IMPORTANCE_MAX = 5;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

可以看到,DEFAULT 跟 HIGH 就差一个级别。MAX 目前是不可用的,我在代码中使用时IDE直接报错,它的源码注释为:Unused. 使用 MIN 和 LOW 又会有什么不同呢?待实验。

在观看Linphone的源代码时,发现它在发送通知时会先判断一下importance,通过通知频道的ID可以再次获取importance属性,代码如下:

val importance  = notificationManager.getNotificationChannel(channelId)
	?.importance ?: NotificationManagerCompat.IMPORTANCE_NONE
  • 1
  • 2

通过判断 importanceIMPORTANCE_NONE 则认为用户关闭了该通知频道。然后我看到,它设置的前台服务的通知频道使用IMPORTANCE_LOW,来电话时,它默认是使用这个对应的频道来发送通知的,然后判断如果这个频道被用户关闭了的话再用来电通知的那个频道来发消息,而且有提到,如果用户关闭了服务通知频道,然后再打开的话,则这个频道原先是IMPORTANCE_LOW,这样操作后就不是IMPORTANCE_LOW了,这也是一个细节点。我奇怪的是这个频道使用IMPORTANCE_LOW的话,它是如何让通知弹出来的,而且这个通知会一直显示,直到用户按接听或挂断按钮,通知对象中有个方法:setCategory(NotificationCompat.CATEGORY_CALL),不知道是否跟这个有关,有时间再去研究了。这个Linphone的关于通知的源码值得好好去研究,它还有兼容性处理,针对不同的版本有不同的处理。

因为低版本是没有通知频道说法的,所以可以想到在通知渠道的一些方法,比如设置通知声音、通知灯颜色、通知振动等的一些方法在NotificationCompat.Builder中也会有。

有时间真的可以好好研究Linphone的源码,人家还是用Kotlin写的,好多东西值得学习。

以前我一直不知道通知频道的id怎么定义,这时就可以参考一下别人是怎么写的,比如Linphone的,如下:

  • linphone_notification_service_id Linphone服务通知
  • linphone_notification_missed_call_id Linphone未接来电通知
  • linphone_notification_call_id Linphone来电通知
  • linphone_notification_chat_id Linphone即时通讯通知

从这看的话,这个id就是一个普通的字符串,能描述你这个通知频道即可,以后通过这个id可以获取频道对象:notificationManager.getNotificationChannel(channelId)

再来看看别人的频道名称和描述是怎么起的,以后自己就知道应该怎么写了,截图来自于我的小米11pro (Android 13),Linphone的如下:
在这里插入图片描述
可以看到,Linphone的是偷懒做法,名称和描述都写成一样的,但也没什么不可,因为通过名称其实就已经足够了解这个频道是做什么的了,所以名称和描述可以是一样的,但是对于 “Linphone服务通知” 这个是看不出来是做什么的,描述应该更详细一些。

下面是微信的:

在这里插入图片描述
对于不同的频道,有不一样的设置,比如对于 “新消息通知” 的铃声为默认铃声,即系统自带的通知铃声中的默认铃声,对于 “音视频通话邀请通知” 的铃声为显示为 phonering,我在另一手机上看到显示为phonering.mp3,所以小米系统隐藏了文件扩展名,这不是我系统自带的铃声,所以,如何给通知设置一个默认铃声和自定义铃声有时间可以学一下,不只是铃声,通知频道中的所有开关设置都是哪些API控制的都应该掌握。

下面是QQ的:
在这里插入图片描述
不知道为什么QQ的这么特殊,它的通知频道上有一个 “允许通知“ 的开关,用于控制所有的频道,但是最上方还有一个这种开关啊,如下:
在这里插入图片描述
别的app的通知频道列表的标题是 “通知类别”,而QQ的显示为 “消息通知”,这么神奇。另外QQ的通知频道都是只有名称,没有描述,所以描述不是必须的,因此对于前面Linphone的把通知频道的名称和描述写成一样就有点多余了,如果都一样的话只写名称就好了。

下面是美团外卖的:
在这里插入图片描述
天哪竟然这么多!所以,对于那些感觉没用的通知频道我们可以把它给禁用掉。

下面是支付宝的:
在这里插入图片描述

这么神奇,这么大个App竟然没有通知频道,支付宝不用发送通知的吗?我真的好像没在我手机上看到过支付宝的通知。

下面是京东的:

在这里插入图片描述
可以看到,“京东通知” 这个频道竟然有两个,说明通知频道的名称是可以重复的。

下面是今日头条的:
在这里插入图片描述
静默通知?长舍样的,学习下:
在这里插入图片描述
原来就是不弹窗、无声音、无振动、锁屏不显示。

下面是百度地图的:

在这里插入图片描述
下面是哈罗的:
在这里插入图片描述
哈罗的和QQ一样,没有显示 “通知类别”,它的显示为 “哈罗” 和 “其他”,这两个标题下的都是通知频道,刚开始我看到 “不重要”、“普通”,我以为又是一个什么奇怪的设置的,原来只是通知频道的名称而已,这里我有个大胆的猜测,通知频道可以分组,哈罗这里分成了两组,组名分别为 “哈罗” 和 “其他”,但是也有点奇怪,为什么哈罗第一组前面有一个 “允许通知” 的开关可以控制该组,但是 “其他” 这个组中又没有这个开关?是系统Bug吗?还是我理解有误,有时间再来研究。

下面是Edge浏览器的:
在这里插入图片描述
可以看到,Edge也把通知频道分成了两组,跟哈罗不同的是,这里每个组都有一个 “允许通知” 的总开关,分别用于控制每个组,所以我猜想,有分组的频道就会有一个总开关控制,如果同时有分组的也有没分组的,则没分组的会显示到 “其他” 这个类别下,但是由于他们不是一组的,所以没有总开关控制,就像我们一个组也不分时,它显示为 “通知类别”,也是没有总开关控制的。

下面是酷狗音乐的:
在这里插入图片描述
下面是TO DO的:
在这里插入图片描述
这个的感觉就不是很专业了,分的太细了,比如文件传输和文件传输完毕都用一个频道不就完了吗,非要搞成两个频道来发送通知。还有一些奇奇怪的“你今天将处理哪些工作”、“奇妙清单导入完毕”。

OK,看了这么多别人的通知频道的设置了,当我们自己开发的时候,对于通知频道我们应该知道要设置什么以及怎么设置比较合理了。

遇到的坑

1、通知无法弹出来

在公司的一台Android 6.0手机上,发现通知弹不出来,因为Android 6.0还没有通知频道的说法,所以对于重要性的属性也是通过NotificationCompat.Builder来设置,我把重要性设置为HIGH了,但是通知并没有弹出来,后来发现公司的一个app可以弹出来,然后我就复制了那个函数,一行一行的代码进行删除进行排查,最终发现删除震动之后通知就不会弹出来了,真坑。示例代码如下:

val builder = NotificationCompat.Builder(this, "channel_id")
    .setSmallIcon(R.drawable.icon)
    .setPriority(NotificationCompat.PRIORITY_HIGH)
    .setContentTitle("这是通知标题")
    .setContentText("这是通知内容")
    .setVibrate(longArrayOf(0, 500, 500, 500))
NotificationManagerCompat.from(this).notify(1, builder.build())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

总在,在这台Android6.0的手机上,要想通知能弹出来,关键代码是这两行:

setPriority(NotificationCompat.PRIORITY_HIGH)
setVibrate(longArrayOf(0, 500, 500, 500))
  • 1
  • 2

在一些高版本的手机上,我没设置震动它也能弹出来,所以这个就很坑,让人百思不得其解!

2、不显示设置的图标

setSmallIcon(R.drawable.notification)设置的图标不显示,显示的是应用图标,这个就没办法了,有的手机定制过了就是这样的,比如小米11pro就是这样的。

3、状态栏不显示通知图标

弹出通知、振动、铃声都正常,就是状态栏上不显示通知图标,下拉状态栏可以看到通知,这是在公司采购的一台Android 11的手机上测试的结果。跟厂家的人说了问题,结果他们录了个视频过来说QQ的可以,这样我以为是我代码有问题,又是各种修改代码各种尝试,以为是图标不规范,甚至反编译了QQ的代码拿他的图标来用,结果还是不行,后来我只能直接发代码给厂家,告诉他们我们这代码在别的手机都可以,只是在这台不行,问他们有没有示例代码可以提供一下。结果他们一会回复说是因为他们做了限制,微信和QQ都可以。真恶心,我试了一下,把我们的App包名改成和微信一样,结果真的可以了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/704133
推荐阅读
相关标签
  

闽ICP备14008679号