android 通知(Notification)
在使用手机时,大家经常看到状态栏有各种通知消息,例如QQ、微信、微薄等等,这些就是android中Notification的应用,通知在当前的手机必不可少,比如QQ有好友发信息给你,这时候需要通知到自己。今天来看看android 通知的使用。
Notification,是一种具有全局效果的通知,可以在系统的通知栏中显示。当 APP 向系统发出通知时,它将先以图标的形式显示在通知栏中。用户可以下拉通知栏查看通知的详细信息。通知栏和抽屉式通知栏均是由系统控制,用户可以随时查看。下面两张图均是来自 Google 官方文档。
图1 状态栏中通知
图 2 .抽屉式通知栏中的通知
通知主要涉及两个类 Notificaiton,NotificationManager。
通知一般的构建步骤:
1.获取NotificationManager对象:
val mNotifiManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
2.获取NotificationCompat.Builder对象,
val builder : NotificationCompat.Builder = NotificationCompat.Builder(this, channel)
第二个参数,NotificaitonChannel,是8.0后新增的消息通知渠道,后面会讲。
3.设置通知的属性,图标、标题、内容、点击响应等等。
//设置内容
builder.setContentText(content)
//设置标题
builder.setContentTitle(title)
//设置小图标,右边时间下面的图标
builder.setSmallIcon(R.mipmap.ic_launcher)
//设置大图标,左边大图标
builder.setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))
//
builder.setAutoCancel(true)
//设置通知的点击响应,这里是跳转到NotificationActivity
val intent = Intent(this@MainActivity, NotificationActivity::class.java)
val pendIntent = PendingIntent.getActivity(this, 0,
intent,0)
builder.setContentIntent(pendIntent)
//设置通知的发出时间
builder.setWhen(System.currentTimeMillis())
4.通过NotificationManager的notify发送通知
mNotifiManager.notify(103, builder.build())
notify()接口,
第一个参数是通知的id,id是唯一的,当此id通知已经发送显示在状态栏上,再次发送该通知,会有声音提示但状态栏上不会多增加一个,如果状态上的通知已经消息,会重新发送一个通知到状态栏
第二个参数是Notification对象(通过NotificaitonCompat.Builder的build()构建)
ps:当然也可以调用NotificationManager的cancel取消通知。
大家可能会发现有些通知是可以下拉的,而且布局样式也与传统的不一样,这就是remoteview实现的折叠通知也就是自定义通知。
自定义布局
代码如下
/**
* 发送折叠式通知
*/
fun sendRemoteViewNotification(){
val builder = NotificationCompat.Builder(this, channel2.id)
val remoteView : RemoteViews = RemoteViews(packageName, R.layout.remote_notifi)
//设置通知的点击响应,这里是跳转到NotificationActivity
val intent = Intent(this@MainActivity, NotificationActivity::class.java)
val pendIntent = PendingIntent.getActivity(this, 0,
intent,0)
//设置内容
builder.setPriority(NotificationManager.IMPORTANCE_HIGH)
builder.setContent(remoteView)
builder.setCustomBigContentView(remoteView)
builder.setSmallIcon(R.mipmap.ic_launcher)
remoteView.setImageViewResource(R.id.iv_tupian, R.mipmap.tupian1111)
remoteView.setTextViewText(R.id.tv_title,"自定义通知标题")
remoteView.setTextViewText(R.id.tv_content,"自定义通知内容自定义通知内容自定义通知内容自定义通知内容自定义通知内容")
remoteView.setTextViewText(R.id.tv_sure,"确认")
remoteView.setTextViewText(R.id.tv_cancel,"取消")
//确认的点击事件
remoteView.setOnClickPendingIntent(R.id.tv_sure, pendIntent)
builder.setAutoCancel(true)
mNotifiManager.notify(102, builder.build())
}
自定义通知通过builder的setContent()传入RemoteViews,想要实现下拉的功能,再调用setCustomBigContentView()传入一个下拉后的布局,自定义的布局内容设置,通过RemoteViews设置实现:
设置图片 setImageViewResource(id,imgid),设置文字:setTextViewText(id, text) ,设置点击 setOnClickPendingIntent(id ,PendingIntent)
相关set方法,参数1:要设置的控件id,参数2:要设置的内容
android 5.0之后可以发送位于屏幕顶部的通知(横幅),一般用来显示重要的消息,原生android通过设置优先级为high可以实现,
builder.setPriority(NotificationManager.IMPORTANCE_HIGH)
,但是国内各大手机厂商对这里做了限制,不能默认通知可以横幅显示,需要加入厂商的白名单(花钱)才可以;但是我们可以提供一个帮助页面来知道用户开始此项功能,需要用户手动设置。
以Honor V8为例
进入设置>>>应用和通知>>>通知管理>>>找我们的应用,点击进入通知设置界面可以看到
android 8.0对通知做了修改,引入通知渠道,给通知分类,这样我们就可以选择性的显示一些通知,避免app给我们发送垃圾通知消息。
顾名思义,就是每条通知都要属于一个对应的渠道。每个App都可以自由地创建当前App拥有哪些通知渠道,但是这些通知渠道的控制权都是掌握在用户手上的。用户可以自由地选择这些通知渠道的重要程度,是否响铃、是否振动、或者是否要关闭这个渠道的通知。
如何进行通知栏适配呢
1.首先确保你的工程设置,app/build.gradle中,确保targetSdkVersion已经指定到了26或者更高
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.gittest.tzt.notificationtest"
minSdkVersion 15
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
2.接下来进行通知渠道的创建,我放在了BaseActivity里
open class BaseActivity : AppCompatActivity() {
lateinit var mNotifiManager : NotificationManager
lateinit var mContext: Context
lateinit var channel1: NotificationChannel
lateinit var channel2: NotificationChannel
lateinit var channel3: NotificationChannel
@SuppressLint("WrongConstant")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mContext = this
mNotifiManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
channel1 = NotificationChannel("common","我的普通通知消息",NotificationManager.IMPORTANCE_LOW)
channel1.description = "普通通知消息"
mNotifiManager.createNotificationChannel(channel1)
channel2 = NotificationChannel("flod","我的折叠式通知消息",NotificationManager.IMPORTANCE_DEFAULT)
channel2.description = "折叠通知消息"
mNotifiManager.createNotificationChannel(channel2)
channel3 = NotificationChannel("suspension ","我的悬挂式通知消息",NotificationManager.IMPORTANCE_HIGH)
channel3.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
channel3.description = "悬挂通知消息"
mNotifiManager.createNotificationChannel(channel3)
}
}
}
通知渠道要求当前手机版本是Android 8.0或者更高,不做这个判断在低版本手机上崩溃。创建一个通知渠道至少需要渠道ID,渠道名称以及重要登记三个参数;渠道ID可以随便定义,要求全局唯一性。渠道名称是给用户看的,需要能够清楚表达这个渠道的用途。重要等级的不同则会决定通知的不同行为,当然这里只是初始状态下的重要等级,用户可以随时手动更改某个渠道的重要等级,App是无法干预的。
代码运行成功后,进入到设置 -> 应用 -> 通知当中,查看NotificationTest这个App的通知界面,如下图所示:
创建渠道的代码只要写在任何地方,只要确认确保发出通知前调用就可以了。并且创建渠道的代码只在第一次执行时才会创建,以后每次执行创建代码系统会检测到该通知渠道已经存在了,因此不会重复创建,也并不会影响任何效率。
8.0之后发送通知,需要在构造NotificaitonCompat.Builder对象时传入渠道ID
val builder = NotificationCompat.Builder(this, channel2.id)
按照一般通知的流程就可以发送通知了。
通知发送到状态栏时会有声音和振动,灯光,当然我们可以把声音和振动,灯光替换为我们想要展现的效果,android 8.0后需要再创建渠道前,设置好声音,振动,灯光。
/**
* 发送自定义声音,通知
*
*
*/
fun sendSuspensionNotification(){
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
val channel3 = NotificationChannel("suspension ","我的悬挂式通知消息",NotificationManager.IMPORTANCE_HIGH)
//设置振动
channel3.enableVibration(true)
channel3.vibrationPattern = longArrayOf(300, 400, 300, 400, 300, 400)
//设置提示音,url也可以设置为 "android.resource://"+ packageName + R.raw.girl_water
channel3.setSound(Uri.parse("android.resource://"+ packageName +"/raw/girl_water"), Notification.AUDIO_ATTRIBUTES_DEFAULT)
//设置闪光灯
channel3.enableLights(true)
channel3.lightColor = Color.BLUE
//设置任何情况下都会显示
channel3.lockscreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
channel3.description = "悬挂通知消息"
mNotifiManager.createNotificationChannel(channel3)
val builder = getNotificationBuilder("悬挂标题","悬挂内容悬挂内容悬挂内容悬挂内容悬挂内容悬挂内容",channel3.id)
mNotifiManager.notify(103, builder.build())
}
}
想要通知有声音,振动,灯光效果,需要再 获取NotificationChannel时设置重要等级为IMPORTANCE_HIGH何IMPORTANCE_MAX,否则不会有提示效果。
NotificationTest