Android端离线推送语音播报原理实现

碰到的问题差不多两个:

  1. 首先是离线推送的问题,如果离线推送需要语音播报的话,需要APP运行一个前台服务,这个服务运行才行,否则自己的代码都没有,怎么实现语音播报呢?

  2. 第二就是怎么用服务去获取到离线推送的消息的问题.

对于第一个问题就是启动前台服务,对于第二个问题就是使用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)
}

查看权限和服务正常运行后,可以杀死APP,然后测试离线推送了.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值