diff --git a/example/src/main/AndroidManifest.xml b/example/src/main/AndroidManifest.xml
index ccf03a3..9f2d07e 100644
--- a/example/src/main/AndroidManifest.xml
+++ b/example/src/main/AndroidManifest.xml
@@ -12,6 +12,7 @@
+
@@ -75,6 +76,11 @@
android:exported="false"
android:foregroundServiceType="camera|microphone|mediaProjection" />
+
+
diff --git a/example/src/main/java/com/demo/SellyCloudSDK/live/LivePlayActivity.kt b/example/src/main/java/com/demo/SellyCloudSDK/live/LivePlayActivity.kt
index 4add4ae..c01094b 100644
--- a/example/src/main/java/com/demo/SellyCloudSDK/live/LivePlayActivity.kt
+++ b/example/src/main/java/com/demo/SellyCloudSDK/live/LivePlayActivity.kt
@@ -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)
diff --git a/example/src/main/java/com/demo/SellyCloudSDK/live/LivePlayForegroundService.kt b/example/src/main/java/com/demo/SellyCloudSDK/live/LivePlayForegroundService.kt
new file mode 100644
index 0000000..53a64ac
--- /dev/null
+++ b/example/src/main/java/com/demo/SellyCloudSDK/live/LivePlayForegroundService.kt
@@ -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)
+ }
+ }
+}
diff --git a/example/src/main/res/values/strings.xml b/example/src/main/res/values/strings.xml
index 90b639d..8f7a198 100644
--- a/example/src/main/res/values/strings.xml
+++ b/example/src/main/res/values/strings.xml
@@ -97,6 +97,8 @@
取消静音
截图
画中画
+ 正在播放
+ 直播播放保持中
直播数据