0

我一直在研究如何在后台(在线广播)中保持活跃的不断运行的音频播放。最后,我为它制作了前台服务,它适用于大多数手机,但不适用于三星 Android P 及更高版本......(如本文“前台服务限制”部分所示:https ://proandroiddev.com/ android-foreground-service-restrictions-d3baa93b2f70 ) 我听说有一个高级的音频播放工具叫做 ExoPlayer。这个库可以帮助我吗?

我已经尝试过这些解决方案:

  • 每 2 秒 ping 一次 google.com
  • 请求电池优化忽略
  • 为 mediplayer 设置唤醒锁: setWakeMode(context, PowerManager.PARTIAL_WAKE_LOCK) (仍在使用)

启动服务:

viewModel.isMusicControlServiceNeedToStart.observe(this, Observer {
        if (it) {
            val intent = Intent(this, MusicControlForegroundServiceImpl::class.java).apply { action = ACTION_SHOW_MUSIC_CONTROL }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) startForegroundService(intent) else startService(intent)
        } else {
            stopService(Intent(this, MusicControlForegroundServiceImpl::class.java))
        }
    })

服务本身:

class MusicControlForegroundServiceImpl : Service(), KoinComponent {

private val notificationManager: NotificationManager by inject()
private val radioManager: RadioManager by inject()
private val context: Context by inject()
private val preferences: Preferences by inject()

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
    if (intent != null && intent.action == ACTION_SHOW_MUSIC_CONTROL) {
        val lastSelectedRadio = preferences.getJSON(Globals.LAST_SELECTED_RADIO_KEY, Radio::class.java)
                ?: return START_NOT_STICKY
        val notification = notificationManager.createMediaControlNotificationIfNeeded(context, lastSelectedRadio)
        startForeground(1, notification)
    }
    return START_NOT_STICKY
}

override fun onTaskRemoved(rootIntent: Intent?) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) startForegroundService(rootIntent) else startService(rootIntent)
    super.onTaskRemoved(rootIntent)
}

override fun onDestroy() {
    if (!notificationManager.musicControlServiceRestart) radioManager.release()
    synchronized(MUSIC_CONTROL_SERVICE_LOCK) { notificationManager.musicControlServiceRestart = false }
    synchronized(MEDIA_PLAYER_LOCK) { radioManager.lastPlayedMediaUrl = null }
    stopForeground(true)
    super.onDestroy()
}

override fun onBind(intent: Intent?): IBinder? = null

}

通知创建:

 override fun createMediaControlNotificationIfNeeded(context: Context, selectedRadio: Radio): Notification {
    val resultIntent = Intent(context, RadioDetailActivity::class.java)
    val resultPendingIntent: PendingIntent? = TaskStackBuilder.create(context).run {
        addNextIntentWithParentStack(resultIntent)
        getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
    }
    val playIntent = Intent(context, NotificationReceiver::class.java).apply {
        putExtra(MusicState::class.java.name, MusicState.PLAY)
    }
    val pauseIntent = Intent(context, NotificationReceiver::class.java).apply {
        putExtra(MusicState::class.java.name, MusicState.PAUSE)
    }

    val notificationManager = NotificationManagerCompat.from(context)

    @Suppress("DEPRECATION") val builder = NotificationCompat.Builder(context, CHANNEL_ID)
            .setSmallIcon(R.drawable.ic_notification_icon)
            .setContentTitle(selectedRadio.name)
            .setDefaults(0)
            .setOngoing(true)
            .setNotificationSilent()
            .addAction(
                    R.drawable.ic_notification_pause,
                    context.getString(R.string.pause),
                    PendingIntent.getBroadcast(context, 1, pauseIntent, 0)
            )
            .addAction(
                    R.drawable.ic_notification_play,
                    context.getString(R.string.play),
                    PendingIntent.getBroadcast(context, 2, playIntent, 0)
            )
            .setStyle(
                    androidx.media.app.NotificationCompat.MediaStyle().setMediaSession(
                            MediaSessionCompat(
                                    context,
                                    RadioDetailActivity::class.java.name
                            ).sessionToken
                    )
            )
            .setContentIntent(resultPendingIntent)

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        val channel = NotificationChannel(
                CHANNEL_ID,
                context.getString(R.string.app_name),
                NotificationManager.IMPORTANCE_LOW
        )
        notificationManager.createNotificationChannel(channel)
        builder.setChannelId(CHANNEL_ID)
    }

    return builder.build()
}

如果您需要任何其他资源,请让我知道并尽可能提供帮助!我已经为这个问题苦苦挣扎了好几个星期了.. :(

更新 现在我每 2 分钟抛出一次媒体控制通知以更新之前的更新,因此该应用程序可以在受影响的手机上存活 30 分钟,但仍然不是一个有效的解决方案......

4

0 回答 0