添加前台播放服务以支持直播播放,更新相关权限和通知逻辑
This commit is contained in:
@@ -12,6 +12,7 @@
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION"/>
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"/>
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
|
||||
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
|
||||
@@ -75,6 +76,11 @@
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="camera|microphone|mediaProjection" />
|
||||
|
||||
<service
|
||||
android:name=".live.LivePlayForegroundService"
|
||||
android:exported="false"
|
||||
android:foregroundServiceType="mediaPlayback" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
||||
@@ -244,6 +244,7 @@ class LivePlayActivity : AppCompatActivity() {
|
||||
if (isPlaying) {
|
||||
logEvent("用户操作: 暂停")
|
||||
playerClient.pause()
|
||||
stopPlaybackForegroundService()
|
||||
return
|
||||
}
|
||||
logEvent("用户操作: 播放")
|
||||
@@ -272,6 +273,7 @@ class LivePlayActivity : AppCompatActivity() {
|
||||
if (hasReleasedPlayer) return
|
||||
hasReleasedPlayer = true
|
||||
playerClient.release()
|
||||
stopPlaybackForegroundService()
|
||||
}
|
||||
|
||||
private fun finishForNewPlayback() {
|
||||
@@ -343,12 +345,21 @@ class LivePlayActivity : AppCompatActivity() {
|
||||
}
|
||||
|
||||
private fun beginPlayback() {
|
||||
startPlaybackForegroundService()
|
||||
startPlayAttempt()
|
||||
resetPreviewForPlayback()
|
||||
playerClient.prepareToPlay()
|
||||
playerClient.play()
|
||||
}
|
||||
|
||||
private fun startPlaybackForegroundService() {
|
||||
LivePlayForegroundService.start(this)
|
||||
}
|
||||
|
||||
private fun stopPlaybackForegroundService() {
|
||||
LivePlayForegroundService.stop(this)
|
||||
}
|
||||
|
||||
private fun setPlayingUi(playing: Boolean) {
|
||||
isPlaying = playing
|
||||
binding.tvPlayLabel.setText(if (playing) R.string.play_ctrl_pause else R.string.play_ctrl_play)
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.demo.SellyCloudSDK.live
|
||||
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.ServiceCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.demo.SellyCloudSDK.R
|
||||
|
||||
/**
|
||||
* 前台播放服务:用于在后台持续拉流并避免系统回收。
|
||||
* 仅负责展示常驻通知,不绑定播放业务。
|
||||
*/
|
||||
class LivePlayForegroundService : Service() {
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
ServiceCompat.startForeground(
|
||||
this,
|
||||
NOTIFICATION_ID,
|
||||
buildNotification(),
|
||||
android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK
|
||||
)
|
||||
} else {
|
||||
startForeground(NOTIFICATION_ID, buildNotification())
|
||||
}
|
||||
return START_STICKY
|
||||
}
|
||||
|
||||
override fun onBind(intent: Intent?) = null
|
||||
|
||||
override fun onDestroy() {
|
||||
try {
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun buildNotification(): Notification {
|
||||
ensureChannel()
|
||||
return NotificationCompat.Builder(this, CHANNEL_ID)
|
||||
.setContentTitle(getString(R.string.live_play_foreground_title))
|
||||
.setContentText(getString(R.string.live_play_foreground_text))
|
||||
.setSmallIcon(android.R.drawable.ic_media_play)
|
||||
.setOngoing(true)
|
||||
.setOnlyAlertOnce(true)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun ensureChannel() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
val manager = getSystemService(NotificationManager::class.java) ?: return
|
||||
val existing = manager.getNotificationChannel(CHANNEL_ID)
|
||||
if (existing == null) {
|
||||
val channel = NotificationChannel(
|
||||
CHANNEL_ID,
|
||||
"Live Playback",
|
||||
NotificationManager.IMPORTANCE_LOW
|
||||
)
|
||||
manager.createNotificationChannel(channel)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val CHANNEL_ID = "live_play_foreground"
|
||||
private const val NOTIFICATION_ID = 0x201
|
||||
|
||||
fun start(context: Context) {
|
||||
val intent = Intent(context, LivePlayForegroundService::class.java)
|
||||
ContextCompat.startForegroundService(context, intent)
|
||||
}
|
||||
|
||||
fun stop(context: Context) {
|
||||
val intent = Intent(context, LivePlayForegroundService::class.java)
|
||||
context.stopService(intent)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -97,6 +97,8 @@
|
||||
<string name="play_ctrl_unmute">取消静音</string>
|
||||
<string name="play_ctrl_screenshot">截图</string>
|
||||
<string name="play_ctrl_pip">画中画</string>
|
||||
<string name="live_play_foreground_title">正在播放</string>
|
||||
<string name="live_play_foreground_text">直播播放保持中</string>
|
||||
|
||||
<string name="live_stats_title">直播数据</string>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user