添加画中画模式支持,优化直播播放体验

This commit is contained in:
2026-01-13 11:05:31 +08:00
parent 951b473ec8
commit 8ef459510d
5 changed files with 62 additions and 16 deletions

View File

@@ -56,9 +56,11 @@
<activity
android:name=".live.LivePlayActivity"
android:exported="false"
android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize|screenLayout|uiMode"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation|keyboardHidden"
android:screenOrientation="fullSensor"
android:theme="@style/Theme.AVDemo.NoActionBar"
android:resizeableActivity="true"
android:supportsPictureInPicture="true"
android:parentActivityName=".FeatureHubActivity" />
<activity

View File

@@ -6,6 +6,7 @@ import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.Typeface
@@ -44,6 +45,7 @@ import com.sellycloud.sellycloudsdk.SellyLatencyChasingUpdate
import com.sellycloud.sellycloudsdk.SellyLiveMode
import com.sellycloud.sellycloudsdk.SellyLiveVideoPlayer
import com.sellycloud.sellycloudsdk.SellyLiveVideoPlayerDelegate
import com.sellycloud.sellycloudsdk.SellyPipController
import com.sellycloud.sellycloudsdk.SellyPlayerState
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@@ -64,6 +66,7 @@ class LivePlayActivity : AppCompatActivity() {
private lateinit var args: Args
private lateinit var playerClient: SellyLiveVideoPlayer
private lateinit var pipController: SellyPipController
private var isPlaying: Boolean = false
private var isMuted: Boolean = false
@@ -82,6 +85,7 @@ class LivePlayActivity : AppCompatActivity() {
private var logDialog: AlertDialog? = null
private var logSummaryView: TextView? = null
private var logContentView: TextView? = null
private var logFloatingButton: View? = null
private val storagePermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission()
@@ -99,6 +103,7 @@ class LivePlayActivity : AppCompatActivity() {
addLogFloatingButton()
envStore = LiveEnvSettingsStore(this)
pipController = SellyPipController(this)
val env = envStore.read().also { it.applyToSdkRuntimeConfig(this) }
args = Args.from(intent, env)
Log.d(TAG, "init liveMode=${args.liveMode} input=${args.streamIdOrUrl} autoStart=${args.autoStart}")
@@ -184,7 +189,7 @@ class LivePlayActivity : AppCompatActivity() {
binding.actionPlay.setOnClickListener { togglePlay() }
binding.actionMute.setOnClickListener { toggleMute() }
binding.actionScreenshot.setOnClickListener { captureCurrentFrame() }
binding.actionSeek10.setOnClickListener { seekForward10s() }
binding.actionPip.setOnClickListener { enterPipMode() }
playerClient.attachRenderView(binding.renderContainer)
@@ -203,6 +208,22 @@ class LivePlayActivity : AppCompatActivity() {
uiScope.cancel()
}
override fun onStop() {
super.onStop()
if (isInPictureInPictureMode) return
}
override fun onUserLeaveHint() {
super.onUserLeaveHint()
if (!isPlaying) return
enterPipMode()
}
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
updatePipUi(isInPictureInPictureMode)
}
private fun togglePlay() {
if (isPlaying) {
logEvent("用户操作: 暂停")
@@ -224,15 +245,11 @@ class LivePlayActivity : AppCompatActivity() {
logEvent(if (isMuted) "用户操作: 静音" else "用户操作: 取消静音")
}
private fun seekForward10s() {
logEvent("用户操作: 快进10秒")
if (args.liveMode == SellyLiveMode.RTC) {
Toast.makeText(this, "RTC 暂不支持快进", Toast.LENGTH_SHORT).show()
return
}
val ok = playerClient.seekBy(10_000L)
if (!ok) Toast.makeText(this, "当前流不支持快进", Toast.LENGTH_SHORT).show()
logEvent(if (ok) "快进结果: 成功" else "快进结果: 失败")
private fun enterPipMode() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) return
if (!isPlaying) return
val renderView = playerClient.getRenderView() ?: binding.renderContainer
pipController.enterPictureInPictureMode(renderView)
}
private fun startPlayback() {
@@ -327,10 +344,26 @@ class LivePlayActivity : AppCompatActivity() {
}
private fun updatePreviewVisibility() {
if (isInPictureInPictureMode) {
binding.ivPreview.visibility = View.GONE
return
}
val shouldShow = !previewImageUrl.isNullOrBlank() && !hasFirstVideoFrameRendered
binding.ivPreview.visibility = if (shouldShow) View.VISIBLE else View.GONE
}
private fun updatePipUi(isInPip: Boolean) {
val controlsVisibility = if (isInPip) View.GONE else View.VISIBLE
binding.controlBar.visibility = controlsVisibility
binding.btnClose.visibility = controlsVisibility
logFloatingButton?.visibility = controlsVisibility
if (isInPip) {
binding.ivPreview.visibility = View.GONE
} else {
updatePreviewVisibility()
}
}
private fun captureCurrentFrame() {
logEvent("用户操作: 截图")
val view = playerClient.getRenderView()
@@ -425,6 +458,7 @@ class LivePlayActivity : AppCompatActivity() {
bottomMargin = marginBottomPx
}
addContentView(button, params)
logFloatingButton = button
}
private fun showLogDialog() {

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M19,7H5c-1.1,0-2,0.9-2,2v8c0,1.1,0.9,2,2,2h14c1.1,0,2-0.9,2-2V9c0-1.1-0.9-2-2-2zm0,10h-6v-4h6v4z" />
</vector>

View File

@@ -143,7 +143,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/actionSeek10"
android:id="@+id/actionPip"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
@@ -158,15 +158,15 @@
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:contentDescription="@string/play_ctrl_seek_10"
android:src="@drawable/ic_av_replay_10"
android:contentDescription="@string/play_ctrl_pip"
android:src="@drawable/ic_av_pip"
app:tint="@color/brand_primary_text_on" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:text="@string/play_ctrl_seek_10"
android:text="@string/play_ctrl_pip"
android:textColor="@color/brand_primary_text_on"
android:textSize="12sp" />
</LinearLayout>

View File

@@ -96,7 +96,7 @@
<string name="play_ctrl_mute">静音</string>
<string name="play_ctrl_unmute">取消静音</string>
<string name="play_ctrl_screenshot">截图</string>
<string name="play_ctrl_seek_10">快进10秒</string>
<string name="play_ctrl_pip">画中画</string>
<string name="live_stats_title">直播数据</string>