碰到的问题差不多两个:
-
首先是离线推送的问题,如果离线推送需要语音播报的话,需要APP运行一个前台服务,这个服务运行才行,否则自己的代码都没有,怎么实现语音播报呢?
-
第二就是怎么用服务去获取到离线推送的消息的问题.
对于第一个问题就是启动前台服务,对于第二个问题就是使用NotificationListenerService来监听离线收到通知信息
清单文件加入代码:
<service
android:name=".service.NotificationService"
android:enabled="true"
android:permission="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
相应的服务类创建
class NotificationService : NotificationListenerService() {}
复写这两个方法
override fun onNotificationPosted(sbn: StatusBarNotification?) {
super.onNotificationPosted(sbn)
}
override fun onCreate() {
super.onCreate()
}
其中在 onCreate方法中开启一个通知,否则的话,此服务到底是运行与否不得而知,添加代码:
val notification = createForegroundNotification()
notification.flags = Notification.FLAG_NO_CLEAR
startForeground(1, notification)
private fun createForegroundNotification(): Notification {
val channelId = "NotificationService";
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channelName = "语音播报";
val importance = NotificationManager.IMPORTANCE_HIGH
val channel = NotificationChannel(channelId, channelName, importance)
channel.lightColor = Color.BLUE
channel.lockscreenVisibility = Notification.VISIBILITY_PRIVATE
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
val pendingIntent = PendingIntent.getActivity(this, 0, Intent(this, MainActivity::class.java), 0)
return NotificationCompat.Builder(this, channelId)
.setContentTitle("语音播报")
.setContentText("为保持语音播报流畅,勿关闭此服务")
.setSmallIcon(R.mipmap.notification_icon)
.setContentIntent(pendingIntent)
.setWhen(System.currentTimeMillis())
.build()
}
而监听通知的话需要 onNotificationPosted 方法回调的数据:
数据都在 sbn?.notification?.extras 里面,打印和各种判断然后根据实际情况,播报即可.
需要注意的点
1.清单文件需要添加权限
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.BIND_NOTIFICATION_LISTENER_SERVICE" />
2.动态请求 BIND_NOTIFICATION_LISTENER_SERVICE 请求,否则的话服务不会自启动,而且监听不到通知变化
请求权限用:
activity.startActivityForResult(Intent("android.settings.ACTION_NOTIFICATION_LISTENER_SETTINGS"), 1001)
判断权限是否已经授权的判断:
// 是否有监听使用权 权限
fun isNLServiceEnabled(): Boolean {
val packages = NotificationManagerCompat.getEnabledListenerPackages(APP.instance.applicationContext)
Log.e("授权的包名:", "isNLServiceEnabled: " + packages)
if (packages.contains(APP.instance.packageName)) {
return true
}
return false
}
fun isServiceEnabled(): Boolean {
//下面的应用包名和服务名需要根据自身应用实际情况去修改
val cn = ComponentName.unflattenFromString("包名/路径.NotificationService")
val notificationManager: NotificationManager = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
APP.instance.getSystemService(NotificationManager::class.java)
} else {
APP.instance.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
}
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
notificationManager.isNotificationListenerAccessGranted(cn)
} else {
isNLServiceEnabled()
}
}
3.开启服务一定要用 startForegroundService
val intent = Intent(activity, NotificationService::class.java)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
activity.startForegroundService(intent)
} else {
activity.startService(intent)
}