从Android 8.0系统开始,Google引入了通知渠道这个概念。
什么是通知渠道呢?顾名思义,就是每条通知都要属于一个对应的渠道。每个App都可以自由地创建当前App拥有哪些通知渠道,但是这些通知渠道的控制权都是掌握在用户手上的。用户可以自由地选择这些通知渠道的重要程度,是否响铃、是否振动、或者是否要关闭这个渠道的通知。
拥有了这些控制权之后,用户就再也不用害怕那些垃圾推送消息的打扰了,因为用户可以自主地选择自己关心哪些通知、不关心哪些通知。举个具体的例子,我希望可以即时收到支付宝的收款信息,因为我不想错过任何一笔收益,但是我又不想收到支付宝给我推荐的周围美食,因为我没钱只吃得起公司食堂。这种情况,支付宝就可以创建两种通知渠道,一个收支,一个推荐,而我作为用户对推荐类的通知不感兴趣,那么我就可以直接将推荐通知渠道关闭,这样既不影响我关心的通知,又不会让那些我不关心的通知来打扰我了。
下面是个例子:
package com.example.notificationtest
import android.annotation.TargetApi
import android.app.NotificationManager
import android.content.Context
import android.graphics.BitmapFactory
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*
import android.app.NotificationChannel
import android.app.PendingIntent
import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.provider.Settings
import android.support.v4.app.NotificationCompat
import android.widget.Toast
class MainActivity : AppCompatActivity(), View.OnClickListener {
private val TAG = MainActivity::class.java.simpleName
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
send_notice.setOnClickListener(this)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//检查当前系统API等级是否大于或等于26(8.0系统)
//如果当前系统是8.0或以上系统就必须创建通知渠道,否则通知无法显示
var channelId = "chat"
var channelName = "聊天消息"
var importance = NotificationManager.IMPORTANCE_HIGH //设置消息等级
createNotificationChannel(channelId, channelName, importance)
channelId = "subscribe"
channelName = "订阅消息"
importance = NotificationManager.IMPORTANCE_DEFAULT //设置消息等级
createNotificationChannel(channelId, channelName, importance)
}
}
@TargetApi(Build.VERSION_CODES.O)//将函数块内的API级别指定为Build.VERSION_CODES.O(26),忽略项目设置的API级别
private fun createNotificationChannel(channelId: String, channelName: String, importance: Int) {
//创建通道前的所有设置,通道创建成功后,之后的修改都不会生效,除非删除这个通知渠道从新创建,或者卸载APP后重新安装,新的设置才会生效。
val channel = NotificationChannel(channelId, channelName, importance)
channel.setShowBadge(true)//开启角标
//设置通知时震动
channel.enableVibration(true)//开启震动
channel.vibrationPattern = longArrayOf(0, 1000, 1000, 1000, 1000, 1000, 1000, 1000)//设置震动模式
/*设置通知声音,用的是res目录下raw文件夹中的msg.wav声音文件,注意路径一定要别搞错了,弄错了通知的时候是不会发出声音的,
即使后面修改正确了也没用,除非删除这个通知渠道从新创建,或者卸载APP后重新安装,新的设置才会生效。*/
//channel.setSound(Uri.parse("android.resource://$packageName/raw/msg"),null)//这种路径也是可以的,不可以带文件后缀
channel.setSound(Uri.parse("android.resource://$packageName/${R.raw.msg}"), null)//推荐这种路径
//设置LED灯(此功能未得到验证,没有呼吸灯手机)
channel.enableLights(true)//开启LED灯
channel.lightColor = Color.GREEN//设置LED灯颜色
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.createNotificationChannel(channel)//创建通知渠道
}
override fun onClick(v: View) {
when (v.id) {
R.id.send_notice -> sendAChatMessage()
else -> Log.d(TAG, "onClick: 没有匹配到view id")
}
}
private fun sendAChatMessage() {
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = manager.getNotificationChannel("chat")//获取chat渠道设置
if (channel.importance == NotificationManager.IMPORTANCE_NONE) {
//渠道被关闭,提示用户打开
Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS).run {
putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
putExtra(Settings.EXTRA_CHANNEL_ID, channel.id)
startActivity(this)
Toast.makeText(this@MainActivity, "请手动将通知打开", Toast.LENGTH_SHORT).show()
}
}
/* 除了以上管理通知渠道的方式之外,Android 8.0还赋予了我们删除通知渠道的功能,只需使用如下代码即可删除:
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
manager.deleteNotificationChannel(channelId)
但是这个功能非常不建议大家使用。因为Google为了防止应用程序随意地创建垃圾通知渠道,会在通知设置界面显示
所有被删除的通知渠道数量。
这样是非常不美观的,所以对于开发者来说最好的做法就是仔细规划好通知渠道,而不要轻易地使用删除功能。*/
}
//通知被点击后跳转到的活动
val pendingIntent = Intent(this, NotificationActivity::class.java).run {
PendingIntent.getActivity(this@MainActivity, 0, this, 0)
}
//要在android8.0系统中显示通知,必须用使用渠道,而使用的渠道必须是已经创建了的。
val notification = NotificationCompat.Builder(this, "chat")
.setContentTitle("Android 8.0还赋予了我们删除通知渠道的功能")
.setStyle(//在通知中显示长文本,这个跟显示大图片不能同时显示
NotificationCompat.BigTextStyle().bigText(
"但是这个功能非常不建议大家使用。因为Google为了防止" +
"应用程序随意地创建垃圾通知渠道,会在通知设置界面显示所有被删除的通知渠道数量。"
)
)
.setStyle(//在通知里显示一张大图片,这个跟长文本不能同时显示
NotificationCompat.BigPictureStyle().bigPicture(
BitmapFactory.decodeResource(
resources,
R.drawable.timg
)
)
)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))
.setNumber(2)//设置角标未读消息数量
.setContentIntent(pendingIntent) //通知被点击后跳转的pendingIntent
.setAutoCancel(true)//设置自动取消系统状态栏的图标
.build()
manager.notify(1, notification)
}
}
更多通知栏详情请参考:
Android通知栏微技巧,8.0系统中通知栏的适配
https://blog.csdn.net/guolin_blog/article/details/79854070 (本文出处)
Android通知栏微技巧,那些你所没关注过的小细节
https://blog.csdn.net/guolin_blog/article/details/50945228