diff --git a/example/libs/sellycloudsdk-1.0.0.aar b/example/libs/sellycloudsdk-1.0.0.aar index 1414a03..5869442 100644 Binary files a/example/libs/sellycloudsdk-1.0.0.aar and b/example/libs/sellycloudsdk-1.0.0.aar differ diff --git a/example/src/main/java/com/demo/SellyCloudSDK/FeatureHubActivity.kt b/example/src/main/java/com/demo/SellyCloudSDK/FeatureHubActivity.kt index 093e38d..fff849d 100644 --- a/example/src/main/java/com/demo/SellyCloudSDK/FeatureHubActivity.kt +++ b/example/src/main/java/com/demo/SellyCloudSDK/FeatureHubActivity.kt @@ -117,7 +117,14 @@ class FeatureHubActivity : AppCompatActivity() { private fun setupActions() { binding.btnHomeLivePush.setOnClickListener { - showPushSettingsDialog { showPushProtocolSheet() } + showPushSettingsDialog { + val settings = settingsStore.read() + if (settings.useUrlMode) { + startActivity(LivePushActivity.createIntent(this, SellyLiveMode.RTMP)) + } else { + showPushProtocolSheet() + } + } } binding.btnHomeLivePull.setOnClickListener { showPlayConfigDialog() @@ -341,6 +348,7 @@ class FeatureHubActivity : AppCompatActivity() { val current = settingsStore.read() dialogBinding.etStreamId.setText(generateRandomStreamId()) + dialogBinding.etPushUrl.setText(current.pushUrl) dialogBinding.etFps.setText(current.fps.toString()) dialogBinding.etMaxBitrate.setText(current.maxBitrateKbps.toString()) dialogBinding.etMinBitrate.setText(current.minBitrateKbps.toString()) @@ -354,16 +362,39 @@ class FeatureHubActivity : AppCompatActivity() { } ) + fun updateModeVisibility(urlMode: Boolean) { + dialogBinding.groupUrlMode.visibility = if (urlMode) View.VISIBLE else View.GONE + dialogBinding.groupStreamIdMode.visibility = if (urlMode) View.GONE else View.VISIBLE + } + + dialogBinding.rgPushMode.check( + if (current.useUrlMode) R.id.rbModeUrl else R.id.rbModeStreamId + ) + updateModeVisibility(current.useUrlMode) + + dialogBinding.rgPushMode.setOnCheckedChangeListener { _, checkedId -> + updateModeVisibility(checkedId == R.id.rbModeUrl) + } + dialogBinding.btnClose.setOnClickListener { dialog.dismiss() } dialogBinding.btnApply.setOnClickListener { + val useUrlMode = dialogBinding.rgPushMode.checkedRadioButtonId == R.id.rbModeUrl + val pushUrl = dialogBinding.etPushUrl.text?.toString()?.trim().orEmpty() val streamId = dialogBinding.etStreamId.text?.toString()?.trim().orEmpty() val fps = dialogBinding.etFps.text?.toString()?.trim()?.toIntOrNull() val maxKbps = dialogBinding.etMaxBitrate.text?.toString()?.trim()?.toIntOrNull() val minKbps = dialogBinding.etMinBitrate.text?.toString()?.trim()?.toIntOrNull() - if (streamId.isEmpty()) { - Toast.makeText(this, "请输入 Stream ID", Toast.LENGTH_SHORT).show() - return@setOnClickListener + if (useUrlMode) { + if (pushUrl.isEmpty()) { + Toast.makeText(this, "请输入推流地址", Toast.LENGTH_SHORT).show() + return@setOnClickListener + } + } else { + if (streamId.isEmpty()) { + Toast.makeText(this, "请输入 Stream ID", Toast.LENGTH_SHORT).show() + return@setOnClickListener + } } if (fps == null || fps <= 0) { Toast.makeText(this, "请输入正确的 FPS", Toast.LENGTH_SHORT).show() @@ -392,7 +423,9 @@ class FeatureHubActivity : AppCompatActivity() { fps = fps, maxBitrateKbps = maxKbps, minBitrateKbps = minKbps, - xorKeyHex = xorKey + xorKeyHex = xorKey, + useUrlMode = useUrlMode, + pushUrl = pushUrl ) settingsStore.write(updated) dialog.dismiss() diff --git a/example/src/main/java/com/demo/SellyCloudSDK/avdemo/AvDemoSettingsStore.kt b/example/src/main/java/com/demo/SellyCloudSDK/avdemo/AvDemoSettingsStore.kt index c80e86e..fba3bc0 100644 --- a/example/src/main/java/com/demo/SellyCloudSDK/avdemo/AvDemoSettingsStore.kt +++ b/example/src/main/java/com/demo/SellyCloudSDK/avdemo/AvDemoSettingsStore.kt @@ -10,6 +10,8 @@ data class AvDemoSettings( val maxBitrateKbps: Int, val minBitrateKbps: Int, val xorKeyHex: String = "", + val useUrlMode: Boolean = false, + val pushUrl: String = "", ) { enum class Resolution { P360, P480, P540, P720 } @@ -38,7 +40,9 @@ class AvDemoSettingsStore(context: Context) { fps = prefs.getInt(KEY_FPS, DEFAULT_FPS), maxBitrateKbps = prefs.getInt(KEY_MAX_KBPS, DEFAULT_MAX_KBPS), minBitrateKbps = prefs.getInt(KEY_MIN_KBPS, DEFAULT_MIN_KBPS), - xorKeyHex = prefs.getString(KEY_XOR_KEY_HEX, "").orEmpty() + xorKeyHex = prefs.getString(KEY_XOR_KEY_HEX, "").orEmpty(), + useUrlMode = prefs.getBoolean(KEY_USE_URL_MODE, false), + pushUrl = prefs.getString(KEY_PUSH_URL, "").orEmpty() ) } @@ -50,6 +54,8 @@ class AvDemoSettingsStore(context: Context) { putInt(KEY_MAX_KBPS, settings.maxBitrateKbps) putInt(KEY_MIN_KBPS, settings.minBitrateKbps) putString(KEY_XOR_KEY_HEX, settings.xorKeyHex) + putBoolean(KEY_USE_URL_MODE, settings.useUrlMode) + putString(KEY_PUSH_URL, settings.pushUrl) } } @@ -66,5 +72,7 @@ class AvDemoSettingsStore(context: Context) { private const val DEFAULT_MAX_KBPS = 2000 private const val DEFAULT_MIN_KBPS = 500 private const val KEY_XOR_KEY_HEX = "xor_key_hex" + private const val KEY_USE_URL_MODE = "use_url_mode" + private const val KEY_PUSH_URL = "push_url" } } diff --git a/example/src/main/java/com/demo/SellyCloudSDK/live/LivePushActivity.kt b/example/src/main/java/com/demo/SellyCloudSDK/live/LivePushActivity.kt index 140fe8c..d833803 100644 --- a/example/src/main/java/com/demo/SellyCloudSDK/live/LivePushActivity.kt +++ b/example/src/main/java/com/demo/SellyCloudSDK/live/LivePushActivity.kt @@ -130,22 +130,31 @@ class LivePushActivity : AppCompatActivity() { pusher.stopLive() } else { val settings = settingsStore.read() - val env = envStore.read() - val streamId = settings.streamId - val authError = LiveAuthHelper.validateAuthConfig(env, streamId) - if (authError != null) { - Toast.makeText(this, authError, Toast.LENGTH_SHORT).show() - return@setOnClickListener - } - val auth = LiveAuthHelper.buildAuthParams( - env = env, - channelId = streamId, - type = LiveTokenSigner.TokenType.PUSH - ) applyStreamConfig(settings) - pusher.token = auth?.tokenResult?.token pusher.setXorKey(settings.xorKeyHex) - pusher.startLiveWithStreamId(streamId) + if (settings.useUrlMode) { + val pushUrl = settings.pushUrl + if (pushUrl.isEmpty()) { + Toast.makeText(this, "请先在设置中输入推流地址", Toast.LENGTH_SHORT).show() + return@setOnClickListener + } + pusher.startLiveWithUrl(pushUrl) + } else { + val env = envStore.read() + val streamId = settings.streamId + val authError = LiveAuthHelper.validateAuthConfig(env, streamId) + if (authError != null) { + Toast.makeText(this, authError, Toast.LENGTH_SHORT).show() + return@setOnClickListener + } + val auth = LiveAuthHelper.buildAuthParams( + env = env, + channelId = streamId, + type = LiveTokenSigner.TokenType.PUSH + ) + pusher.token = auth?.tokenResult?.token + pusher.startLiveWithStreamId(streamId) + } } } diff --git a/example/src/main/res/layout/dialog_live_preset_settings.xml b/example/src/main/res/layout/dialog_live_preset_settings.xml index fa75370..62da0f8 100644 --- a/example/src/main/res/layout/dialog_live_preset_settings.xml +++ b/example/src/main/res/layout/dialog_live_preset_settings.xml @@ -40,28 +40,112 @@ app:tint="@color/brand_primary" /> + - + android:background="@drawable/bg_av_segment_container" + android:orientation="horizontal"> + + + + + + + + + + + + + + + + + + + + + 应用 Stream ID 关闭设置 + 推流模式 + StreamID + URL + 推流地址 播放配置 播放协议