diff --git a/README.md b/README.md
index 60e8078b..4e854965 100644
--- a/README.md
+++ b/README.md
@@ -159,15 +159,12 @@
- 2、作为独立的流媒体服务器使用,不想做c/c++开发的,可以参考 [restful api](https://github.com/ZLMediaKit/ZLMediaKit/wiki/MediaServer支持的HTTP-API) 和 [web hook](https://github.com/ZLMediaKit/ZLMediaKit/wiki/MediaServer支持的HTTP-HOOK-API ).
- 3、如果想做c/c++开发,添加业务逻辑增加功能,可以参考这里的[测试程序](https://github.com/ZLMediaKit/ZLMediaKit/tree/master/tests).
-## 二进制文件下载
-zlmediakit采用 github action 持续集成自动编译打包上传编译产出包,请在[issue列表](https://github.com/ZLMediaKit/ZLMediaKit/issues/483)下载最新sdk库文件以及可执行文件。
-
## Docker 镜像
你可以从Docker Hub下载已经编译好的镜像并启动它:
```bash
-#此镜像为github action 持续集成自动编译推送,跟代码(master分支)保持最新状态
+#此镜像为github持续集成自动编译推送,跟代码(master分支)保持最新状态
docker run -id -p 1935:1935 -p 8080:80 -p 8443:443 -p 8554:554 -p 10000:10000 -p 10000:10000/udp -p 8000:8000/udp -p 9000:9000/udp zlmediakit/zlmediakit:master
```
@@ -191,6 +188,7 @@ bash build_docker_images.sh
- [jessibuca](https://github.com/langhuihui/jessibuca) 基于wasm支持H265的播放器
- [wsPlayer](https://github.com/v354412101/wsPlayer) 基于MSE的websocket-fmp4播放器
- [BXC_gb28181Player](https://github.com/any12345com/BXC_gb28181Player) C++开发的支持国标GB28181协议的视频流播放器
+ - [RTCPlayer](https://github.com/leo94666/RTCPlayer) 一个基于Android客户端的的RTC播放器
- WEB管理网站
- [zlm_webassist](https://github.com/1002victor/zlm_webassist) 本项目配套的前后端分离web管理项目
@@ -366,6 +364,7 @@ bash build_docker_images.sh
[jamesZHANG500](https://github.com/jamesZHANG500)
[weidelong](https://github.com/wdl1697454803)
[小强先生](https://github.com/linshangqiang)
+[李之阳](https://github.com/leo94666)
同时感谢JetBrains对开源项目的支持,本项目使用CLion开发与调试:
diff --git a/README_en.md b/README_en.md
index 865a2e7f..34294b4f 100644
--- a/README_en.md
+++ b/README_en.md
@@ -367,12 +367,15 @@ bash build_docker_images.sh
- [Push client implemented based on C SDK](https://github.com/hctym1995/ZLM_ApiDemo)
- [Http API and Hook in C#](https://github.com/chengxiaosheng/ZLMediaKit.HttpApi)
- [RESTful client in DotNetCore](https://github.com/MingZhuLiu/ZLMediaKit.DotNetCore.Sdk)
+
- Player
- [Player supporting H265 based on wasm](https://github.com/numberwolf/h265web.js)
- [WebSocket-fmp4 player based on MSE](https://github.com/v354412101/wsPlayer)
- [Domestic webrtc sdk(metaRTC)](https://github.com/metartc/metaRTC)
- [GB28181 player implemented in C++](https://github.com/any12345com/BXC_gb28181Player)
+ - [Android RTCPlayer](https://github.com/leo94666/RTCPlayer)
+
## License
@@ -525,6 +528,7 @@ Thanks to all those who have supported this project in various ways, including b
[jamesZHANG500](https://github.com/jamesZHANG500)
[weidelong](https://github.com/wdl1697454803)
[小强先生](https://github.com/linshangqiang)
+[李之阳](https://github.com/leo94666)
Also thank to JetBrains for their support for open source project, we developed and debugged zlmediakit with CLion:
diff --git a/webrtc_player/android/.gitignore b/webrtc_player/android/.gitignore
index d4c3a57e..aa724b77 100644
--- a/webrtc_player/android/.gitignore
+++ b/webrtc_player/android/.gitignore
@@ -13,4 +13,3 @@
.externalNativeBuild
.cxx
local.properties
-/.idea/
diff --git a/webrtc_player/android/.idea/.gitignore b/webrtc_player/android/.idea/.gitignore
new file mode 100644
index 00000000..26d33521
--- /dev/null
+++ b/webrtc_player/android/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/webrtc_player/android/.idea/.name b/webrtc_player/android/.idea/.name
new file mode 100644
index 00000000..377c1793
--- /dev/null
+++ b/webrtc_player/android/.idea/.name
@@ -0,0 +1 @@
+RTCPlayer
\ No newline at end of file
diff --git a/webrtc_player/android/.idea/compiler.xml b/webrtc_player/android/.idea/compiler.xml
new file mode 100644
index 00000000..b589d56e
--- /dev/null
+++ b/webrtc_player/android/.idea/compiler.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/webrtc_player/android/.idea/deploymentTargetDropDown.xml b/webrtc_player/android/.idea/deploymentTargetDropDown.xml
new file mode 100644
index 00000000..0c0c3383
--- /dev/null
+++ b/webrtc_player/android/.idea/deploymentTargetDropDown.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/webrtc_player/android/.idea/gradle.xml b/webrtc_player/android/.idea/gradle.xml
new file mode 100644
index 00000000..0897082f
--- /dev/null
+++ b/webrtc_player/android/.idea/gradle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/webrtc_player/android/.idea/kotlinc.xml b/webrtc_player/android/.idea/kotlinc.xml
new file mode 100644
index 00000000..8d81632f
--- /dev/null
+++ b/webrtc_player/android/.idea/kotlinc.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/webrtc_player/android/.idea/migrations.xml b/webrtc_player/android/.idea/migrations.xml
new file mode 100644
index 00000000..f8051a6f
--- /dev/null
+++ b/webrtc_player/android/.idea/migrations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/webrtc_player/android/.idea/misc.xml b/webrtc_player/android/.idea/misc.xml
new file mode 100644
index 00000000..8978d23d
--- /dev/null
+++ b/webrtc_player/android/.idea/misc.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/webrtc_player/android/.idea/vcs.xml b/webrtc_player/android/.idea/vcs.xml
new file mode 100644
index 00000000..b2bdec2d
--- /dev/null
+++ b/webrtc_player/android/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/webrtc_player/android/README.md b/webrtc_player/android/README.md
new file mode 100644
index 00000000..8889ccee
--- /dev/null
+++ b/webrtc_player/android/README.md
@@ -0,0 +1,106 @@
+# RTCPlayer 播放器
+
+一个基于Android客户端的的RTC播放器
+
+## 项目特点
+
+- :white_check_mark:低延迟(200~500ms)
+- :white_check_mark:支持[ZLMediakit](https://github.com/ZLMediaKit/ZLMediaKit)流媒体
+- :black_square_button:支持[SRS](https://github.com/ossrs/srs)
+- :black_square_button:支持[Janus](https://github.com/meetecho/janus-gateway)
+
+如果您需要支持SRS或者Janus,请寻找下方联系我!
+
+
+
+
+
+
+
+## 延迟情况
+
+- **网页端推流,Android端播放**
+
+
+
+
+
+
+
+三次延迟分别为:490ms、526ms、560ms
+
+- **Android端推屏幕流,网页端播放**
+
+
+
+
+
+
+
+三次延迟分别为:440ms、430ms、387ms
+
+## 接口说明
+
+### Player
+
+- bind(surface: RTCSurfaceView)
+
+ 绑定视图
+
+- play(app: String, streamId: String)
+
+ 播放
+- setVolume(volume:Float)
+
+ 设置音量,范围: 0.0~1.0f
+- stop()
+
+ 停止播放
+- pause()
+
+ 暂停播放
+- resume()
+
+ 恢复播放
+- capture(listener: (bitmap: Bitmap) -> Unit)
+
+ 截图
+- record(duration: Long, result: (path: String) -> Unit)
+
+ 录制
+- setOnErrorListener(listener: (code: Int, msg: String) -> Unit)
+
+ 设置播放器错误监听回调
+- setOnStatusListener(listener: (status: Status) -> Unit)
+
+ 设置播放器状态回调
+
+### Pusher
+
+- bind(surface: RTCSurfaceView, localPreview: Boolean)
+
+ 绑定视图
+
+- push(app: String, streamId: String, mode: PushMode = PushMode.CAMERA, inputFile: String = "")
+
+ 推流,支持Camera、Screen、File
+
+- stop()
+
+ 停止推流
+
+- setOnErrorListener(listener: (code: Int, msg: String) -> Unit)
+
+ 设置播放器错误监听回调
+
+## 联系作者
+如果您需要深度二次开发,深度优化延迟,并支持其他流媒体服务,可以找我哦!
+[李之阳](https://github.com/leo94666)
+
+## 特别感谢
+
+感谢[ZLMediakit](https://github.com/ZLMediaKit/ZLMediaKit)开源项目
+
+同时感谢JetBrains对开源项目的支持,本项目使用Android Studio开发与调试:
+
+[](https://developer.android.com/studio?hl=zh-cn)
\ No newline at end of file
diff --git a/webrtc_player/android/app-debug.apk b/webrtc_player/android/app-debug.apk
deleted file mode 100644
index 969d48b7..00000000
Binary files a/webrtc_player/android/app-debug.apk and /dev/null differ
diff --git a/webrtc_player/android/app/.gitignore b/webrtc_player/android/app/.gitignore
index c591fdeb..42afabfd 100644
--- a/webrtc_player/android/app/.gitignore
+++ b/webrtc_player/android/app/.gitignore
@@ -1,2 +1 @@
-/build
-.cxx
\ No newline at end of file
+/build
\ No newline at end of file
diff --git a/webrtc_player/android/app/build.gradle b/webrtc_player/android/app/build.gradle
deleted file mode 100644
index cfd25638..00000000
--- a/webrtc_player/android/app/build.gradle
+++ /dev/null
@@ -1,54 +0,0 @@
-plugins {
- id 'com.android.application'
- id 'org.jetbrains.kotlin.android'
- id 'kotlin-android-extensions'
- id 'kotlin-kapt'
-
-}
-apply plugin: 'kotlin-android'
-
-android {
- compileSdk 32
-
- defaultConfig {
- applicationId "com.zlmediakit.webrtc"
- minSdk 21
- targetSdk 32
- versionCode 1
- versionName "1.0"
-
- testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
- }
-
- buildTypes {
- release {
- minifyEnabled false
- proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
- }
- }
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
- kotlinOptions {
- jvmTarget = '1.8'
- }
-}
-
-dependencies {
-
- implementation 'androidx.core:core-ktx:1.7.0'
- implementation 'androidx.appcompat:appcompat:1.5.1'
- implementation 'com.google.android.material:material:1.6.1'
- implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
- testImplementation 'junit:junit:4.13.2'
- androidTestImplementation 'androidx.test.ext:junit:1.1.3'
- androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
- implementation 'com.google.code.gson:gson:2.8.9'
-
- implementation("com.squareup.okhttp3:okhttp:4.10.0")
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
-
- implementation 'org.webrtc:google-webrtc:1.0.32006'
-
-}
\ No newline at end of file
diff --git a/webrtc_player/android/app/build.gradle.kts b/webrtc_player/android/app/build.gradle.kts
new file mode 100644
index 00000000..9ca6cebf
--- /dev/null
+++ b/webrtc_player/android/app/build.gradle.kts
@@ -0,0 +1,58 @@
+plugins {
+ id("com.android.application")
+ id("org.jetbrains.kotlin.android")
+
+}
+
+android {
+ namespace = "com.top.player"
+ compileSdk = 34
+
+ defaultConfig {
+ applicationId = "com.top.player"
+ minSdk = 24
+ targetSdk = 34
+ versionCode = 1
+ versionName = "1.0"
+
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+
+ }
+
+ buildTypes {
+ release {
+ isMinifyEnabled = false
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro"
+ )
+ }
+ }
+ compileOptions {
+ sourceCompatibility = JavaVersion.VERSION_1_8
+ targetCompatibility = JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = "1.8"
+ }
+ viewBinding {
+ enable = true
+ }
+}
+
+dependencies {
+
+ implementation("androidx.appcompat:appcompat:1.5.1")
+ implementation("com.google.android.material:material:1.6.1")
+ implementation("androidx.constraintlayout:constraintlayout:2.1.4")
+ testImplementation("junit:junit:4.13.2")
+ androidTestImplementation("androidx.test.ext:junit:1.1.3")
+ androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0")
+
+ implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.22")
+ implementation("com.guolindev.permissionx:permissionx:1.7.1")
+
+ //implementation(project(":RTCPlayer"))
+ implementation("com.rtc.core:RTCPlayer:1.0.0.beta")
+
+}
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/androidTest/java/com/top/player/ExampleInstrumentedTest.java b/webrtc_player/android/app/src/androidTest/java/com/top/player/ExampleInstrumentedTest.java
new file mode 100644
index 00000000..2c5af40e
--- /dev/null
+++ b/webrtc_player/android/app/src/androidTest/java/com/top/player/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.top.player;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ assertEquals("com.top.player", appContext.getPackageName());
+ }
+}
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/androidTest/java/com/zlmediakit/webrtc/ExampleInstrumentedTest.kt b/webrtc_player/android/app/src/androidTest/java/com/zlmediakit/webrtc/ExampleInstrumentedTest.kt
deleted file mode 100644
index 645a1102..00000000
--- a/webrtc_player/android/app/src/androidTest/java/com/zlmediakit/webrtc/ExampleInstrumentedTest.kt
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.zlmediakit.webrtc
-
-import androidx.test.platform.app.InstrumentationRegistry
-import androidx.test.ext.junit.runners.AndroidJUnit4
-
-import org.junit.Test
-import org.junit.runner.RunWith
-
-import org.junit.Assert.*
-
-/**
- * Instrumented test, which will execute on an Android device.
- *
- * See [testing documentation](http://d.android.com/tools/testing).
- */
-@RunWith(AndroidJUnit4::class)
-class ExampleInstrumentedTest {
- @Test
- fun useAppContext() {
- // Context of the app under test.
- val appContext = InstrumentationRegistry.getInstrumentation().targetContext
- assertEquals("com.zlmediakit.webrtc", appContext.packageName)
- }
-}
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/AndroidManifest.xml b/webrtc_player/android/app/src/main/AndroidManifest.xml
index 81281350..1e944e3c 100644
--- a/webrtc_player/android/app/src/main/AndroidManifest.xml
+++ b/webrtc_player/android/app/src/main/AndroidManifest.xml
@@ -1,24 +1,27 @@
+ xmlns:tools="http://schemas.android.com/tools">
-
-
+
+
+ android:required="true" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+ android:hardwareAccelerated="true"
+ tools:overrideLibrary="com.rtc.core"
+ android:name=".App">
@@ -41,6 +45,13 @@
+
+
+
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/java/com/top/player/App.kt b/webrtc_player/android/app/src/main/java/com/top/player/App.kt
new file mode 100644
index 00000000..1c457ffd
--- /dev/null
+++ b/webrtc_player/android/app/src/main/java/com/top/player/App.kt
@@ -0,0 +1,11 @@
+package com.top.player
+
+import android.app.Application
+
+class App: Application() {
+
+ override fun onCreate() {
+ super.onCreate()
+
+ }
+}
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/java/com/top/player/MainActivity.kt b/webrtc_player/android/app/src/main/java/com/top/player/MainActivity.kt
new file mode 100644
index 00000000..8cb2a7e5
--- /dev/null
+++ b/webrtc_player/android/app/src/main/java/com/top/player/MainActivity.kt
@@ -0,0 +1,25 @@
+package com.top.player
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.View
+import androidx.appcompat.app.AppCompatActivity
+
+class MainActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ }
+
+ fun toPlayActivity(view: View) {
+ startActivity(Intent(this, PlayerDemoActivity::class.java))
+ }
+
+ fun toPushActivity(view: View) {
+ startActivity(Intent(this, PusherDemoActivity::class.java))
+
+ }
+
+}
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/java/com/top/player/PlayerDemoActivity.kt b/webrtc_player/android/app/src/main/java/com/top/player/PlayerDemoActivity.kt
new file mode 100644
index 00000000..50f810cb
--- /dev/null
+++ b/webrtc_player/android/app/src/main/java/com/top/player/PlayerDemoActivity.kt
@@ -0,0 +1,112 @@
+package com.top.player
+
+import android.os.Bundle
+import android.view.View
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import com.rtc.core.ZLMRTCPlayer
+import com.rtc.core.play.Status
+import com.rtc.core.play.ZLMRTCPlayerImpl
+import com.top.player.databinding.ActivityPlayerBinding
+
+
+class PlayerDemoActivity : AppCompatActivity() {
+
+
+ private val player: ZLMRTCPlayer by lazy {
+ ZLMRTCPlayerImpl(this)
+ }
+
+
+ private val binding by lazy {
+ ActivityPlayerBinding.inflate(layoutInflater)
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContentView(binding.root)
+
+ //ffmpeg -re -stream_loop -1 -i "D:\li\hot\data\data\baseline.mp4" -vcodec h264 -acodec aac -f rtsp -rtsp_transport tcp -bf 0 rtsp://zlmediakit.com/live/li
+ //ffmpeg -re -stream_loop -1 -i "D:\li\hot\data\data\test.mp4" -vcodec h264 -acodec aac -f flv -bf 0 rtmp://zlmediakit.com/live/li
+
+ setTitle("Player Demo")
+ player.bind(binding.surfaceViewRender)
+
+ player.setOnErrorListener { code, msg ->
+ Toast.makeText(this, "code:$code,msg:${msg}", Toast.LENGTH_SHORT).show()
+
+ }
+
+ player.setOnStatusListener {
+ when (it) {
+ Status.PREPARING -> {
+ binding.tvStatus.text = "准备播放"
+ }
+
+ Status.PLAYING -> {
+ binding.tvStatus.text = "播放中.."
+ }
+
+ Status.PAUSE -> {
+ binding.tvStatus.text = "暂停中.."
+ }
+
+ Status.RESUME -> {
+ binding.tvStatus.text = "播放中.."
+ }
+
+ Status.STOP -> {
+ binding.tvStatus.text = ""
+ }
+
+ Status.ERROR -> {
+ binding.tvStatus.text = "播放异常"
+ }
+
+ else -> {}
+ }
+ }
+
+ }
+
+
+ override fun onDestroy() {
+ super.onDestroy()
+ player.stop()
+ }
+
+ fun onPlayClick(view: View) {
+
+ player.play(binding.tvApp.text.toString(), binding.tvStreamId.text.toString())
+ }
+
+ fun onPauseClick(view: View) {
+ player.pause()
+ //Toast.makeText(this, "ok", Toast.LENGTH_SHORT).show()
+ }
+
+ fun onStopClick(view: View) {
+ player.stop()
+ }
+
+ fun onResumeClick(view: View) {
+ player.resume()
+ }
+
+ fun onCapture(view: View) {
+ player.capture {
+ Toast.makeText(this, "capture ok", Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ fun onRecord(view: View) {
+ player.record(10 * 1000) {
+ Toast.makeText(this, "" + it, Toast.LENGTH_SHORT).show()
+ }
+ }
+
+ fun onVolume(view: View) {
+ player.setVolume(0.0f)
+ }
+}
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/java/com/top/player/PusherDemoActivity.kt b/webrtc_player/android/app/src/main/java/com/top/player/PusherDemoActivity.kt
new file mode 100644
index 00000000..168dafe5
--- /dev/null
+++ b/webrtc_player/android/app/src/main/java/com/top/player/PusherDemoActivity.kt
@@ -0,0 +1,97 @@
+package com.top.player
+
+import android.Manifest
+import android.content.Intent
+import android.os.Bundle
+import android.view.View
+import android.widget.Toast
+import androidx.appcompat.app.AppCompatActivity
+import com.permissionx.guolindev.PermissionX
+import com.rtc.core.RTCSurfaceView
+import com.rtc.core.ZLMRTCPusher
+import com.rtc.core.push.PushMode
+import com.rtc.core.push.ZLMRTCPusherImpl
+import com.top.player.databinding.ActivityPlayerBinding
+import com.top.player.databinding.ActivityPusherBinding
+
+
+class PusherDemoActivity : AppCompatActivity() {
+
+
+ private val pusher: ZLMRTCPusher by lazy {
+ ZLMRTCPusherImpl(this)
+ }
+
+
+ private val binding by lazy {
+ ActivityPusherBinding.inflate(layoutInflater)
+ }
+
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContentView(R.layout.activity_pusher)
+
+ val rtcSurfaceView = findViewById(R.id.surface_view_render)
+
+ pusher.bind(rtcSurfaceView, true)
+ setTitle("Pusher Demo")
+
+
+ pusher.setOnErrorListener { code, msg ->
+ Toast.makeText(this, "code:${code},msg:${msg}", Toast.LENGTH_SHORT).show()
+ }
+
+ }
+
+ fun onPushCamera(view: View) {
+ PermissionX.init(this)
+ .permissions(Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO)
+ .request { allGranted, grantedList, deniedList ->
+ if (allGranted) {
+ pusher.push(binding.tvApp.text.toString(), binding.tvStreamId.text.toString())
+ }
+ }
+ }
+
+ fun onPushScreen(view: View) {
+ PermissionX.init(this)
+ .permissions(Manifest.permission.RECORD_AUDIO)
+ .request { allGranted, grantedList, deniedList ->
+ if (allGranted) {
+ pusher.push(
+ binding.tvApp.text.toString(),
+ binding.tvStreamId.text.toString(),
+ PushMode.SCREEN
+ )
+ }
+ }
+ }
+
+ fun onPushFile(view: View) {
+ PermissionX.init(this)
+ .permissions(Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE)
+ .request { allGranted, grantedList, deniedList ->
+ if (allGranted) {
+ pusher.push(
+ binding.tvApp.text.toString(),
+ binding.tvStreamId.text.toString(),
+ PushMode.FILE,
+ ""
+ )
+ }
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ pusher.stop()
+ }
+
+ fun onStopPush(view: View) {
+ pusher.stop()
+ }
+
+
+}
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/java/com/zlmediakit/webrtc/MainActivity.kt b/webrtc_player/android/app/src/main/java/com/zlmediakit/webrtc/MainActivity.kt
deleted file mode 100644
index 15a8efc8..00000000
--- a/webrtc_player/android/app/src/main/java/com/zlmediakit/webrtc/MainActivity.kt
+++ /dev/null
@@ -1,79 +0,0 @@
-package com.zlmediakit.webrtc
-
-import android.annotation.SuppressLint
-import android.graphics.drawable.BitmapDrawable
-import android.graphics.drawable.Drawable
-import android.os.Bundle
-import android.widget.Toast
-import androidx.appcompat.app.AppCompatActivity
-import kotlinx.android.synthetic.main.activity_main.*
-import kotlinx.android.synthetic.main.activity_main.view.*
-
-
-class MainActivity : AppCompatActivity() {
-
- private var isSpeaker = true
-
- @SuppressLint("SetTextI18n")
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- setContentView(R.layout.activity_main)
-
- lifecycle.addObserver(web_rtc_sv)
-
- //http://124.223.98.45/index/api/webrtc?app=live&stream=test&type=play
- url.setText("http://124.223.98.45/index/api/webrtc?app=live&stream=test&type=play")
-
- //http://192.168.1.17/index/api/webrtc?app=live&stream=test&type=play
- btn_play.setOnClickListener {
- web_rtc_sv?.setVideoPath(url.text.toString())
- web_rtc_sv.start()
- }
-
- web_rtc_sv.setOnErrorListener { errorCode, errorMsg ->
- runOnUiThread {
- Toast.makeText(this, "errorCode:$errorCode,errorMsg:$errorMsg", Toast.LENGTH_SHORT)
- .show()
- }
- }
-
-
- btn_pause.setOnClickListener {
- web_rtc_sv?.pause()
- }
-
- btn_resume.setOnClickListener {
- web_rtc_sv?.resume()
- }
-
- btn_screenshot.setOnClickListener {
- web_rtc_sv?.screenshot {
- runOnUiThread {
- iv_screen.setImageDrawable(BitmapDrawable(it))
- }
- }
- }
-
- btn_mute.setOnClickListener {
- web_rtc_sv.mute(true)
- }
-
-
- selectAudio()
- btn_speaker.setOnClickListener {
- selectAudio()
- }
-
- }
-
- fun selectAudio(){
- if (isSpeaker){
- btn_speaker.setText("扬声器")
- web_rtc_sv.setSpeakerphoneOn(isSpeaker)
- }else{
- btn_speaker.setText("话筒")
- web_rtc_sv.setSpeakerphoneOn(isSpeaker)
- }
- isSpeaker=!isSpeaker
- }
-}
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/java/com/zlmediakit/webrtc/WebRTCSurfaceView.kt b/webrtc_player/android/app/src/main/java/com/zlmediakit/webrtc/WebRTCSurfaceView.kt
deleted file mode 100644
index 3e94171c..00000000
--- a/webrtc_player/android/app/src/main/java/com/zlmediakit/webrtc/WebRTCSurfaceView.kt
+++ /dev/null
@@ -1,439 +0,0 @@
-package com.zlmediakit.webrtc
-
-import android.content.Context
-import android.graphics.Bitmap
-import android.media.AudioManager
-import android.util.AttributeSet
-import android.util.Log
-import android.view.LayoutInflater
-import android.widget.RelativeLayout
-import androidx.lifecycle.DefaultLifecycleObserver
-import androidx.lifecycle.LifecycleOwner
-import com.google.gson.Gson
-import okhttp3.*
-import okhttp3.MediaType.Companion.toMediaType
-import okhttp3.MediaType.Companion.toMediaTypeOrNull
-import org.webrtc.*
-import org.webrtc.RendererCommon.ScalingType
-import org.webrtc.audio.AudioDeviceModule
-import org.webrtc.audio.JavaAudioDeviceModule
-import java.io.IOException
-import java.util.*
-
-public class WebRTCSurfaceView(context: Context, attrs: AttributeSet?) :
- RelativeLayout(context, attrs), DefaultLifecycleObserver, RendererCommon.RendererEvents {
-
-
- private data class sdp(var sdp: String, var username: String, var password: String)
-
- private data class SdpResponse(var code: Int, var id: String, var sdp: String, var type: String)
-
- private enum class ErrorCode(val errorCode: Int) {
- SUCCESS(0x00),
- GET_REMOTE_SDP_ERROR(0x01);
- }
-
-
- companion object {
- private val TAG = "WebRTCSurfaceView"
-
- }
-
- private var mContext: Context = context
-
- private val eglBase: EglBase = EglBase.create()
- private var mEGLBaseContext: EglBase.Context = eglBase.eglBaseContext
-
- private lateinit var videoUrl: String;
-
- private var mPeerConnectionFactory: PeerConnectionFactory? = null
-
- private var mLocalMediaStream: MediaStream? = null
- private var mLocalAudioTrack: AudioTrack? = null
- private var mAudioSource: AudioSource? = null
-
- private var mLocalSessionDescription: SessionDescription? = null
- private var mRemoteSessionDescription: SessionDescription? = null
-
- private var mLocalPeer: Peer? = null
-
- private var mSurfaceViewRenderer: SurfaceViewRenderer
-
- private lateinit var OnErrorListener: (errorCode: Int, errorMsg: String) -> Unit?
-
- fun setOnErrorListener(listener: (errorCode: Int, errorMsg: String) -> Unit) {
- this.OnErrorListener = listener
- }
-
- private lateinit var OnPreparedListener: () -> Unit?
-
- fun setOnPreparedListener(listener: () -> Unit) {
- this.OnPreparedListener = listener
- }
-
- private val audioManager: AudioManager
-
-
- init {
-
- val view = LayoutInflater.from(mContext).inflate(R.layout.layout_videoview, this)
-
- mPeerConnectionFactory = createConnectionFactory()
-
- mSurfaceViewRenderer = view.findViewById(R.id.surface_view_renderer)
-
- mSurfaceViewRenderer.init(mEGLBaseContext, this)
- mSurfaceViewRenderer.setScalingType(ScalingType.SCALE_ASPECT_FILL)
- mSurfaceViewRenderer.setEnableHardwareScaler(true)
-
-
- //创建媒体流
- mLocalMediaStream = mPeerConnectionFactory?.createLocalMediaStream("ARDAMS")
- //采集音频
- mAudioSource = mPeerConnectionFactory?.createAudioSource(createAudioConstraints())
- mLocalAudioTrack = mPeerConnectionFactory?.createAudioTrack("ARDAMSa0", mAudioSource)
-
- //添加Tracks
- mLocalMediaStream?.addTrack(mLocalAudioTrack)
-
- audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
- audioManager.isSpeakerphoneOn = false
-
-
- }
-
-
- private fun set(width: Int, height: Int) {
- layoutParams.width = width
- layoutParams.height = height
- }
-
- private fun createConnectionFactory(): PeerConnectionFactory? {
-
- val options = PeerConnectionFactory.InitializationOptions.builder(mContext)
- .setEnableInternalTracer(false)
- .createInitializationOptions()
-
- PeerConnectionFactory.initialize(options)
-
- val videoEncoderFactory = DefaultVideoEncoderFactory(
- mEGLBaseContext,
- true,
- true
- )
-
- val videoDecoderFactory = DefaultVideoDecoderFactory(mEGLBaseContext)
-
-
- val audioDevice = createJavaAudioDevice()
- val peerConnectionFactory = PeerConnectionFactory.builder()
- .setAudioDeviceModule(audioDevice)
- .setVideoEncoderFactory(videoEncoderFactory)
- .setVideoDecoderFactory(videoDecoderFactory)
- .createPeerConnectionFactory()
- audioDevice.release()
-
- return peerConnectionFactory
-
- }
-
- private fun createAudioConstraints(): MediaConstraints {
- val audioConstraints = MediaConstraints()
- audioConstraints.mandatory.add(
- MediaConstraints.KeyValuePair(
- "googEchoCancellation",
- "true"
- )
- )
- audioConstraints.mandatory.add(
- MediaConstraints.KeyValuePair(
- "googAutoGainControl",
- "false"
- )
- )
- audioConstraints.mandatory.add(
- MediaConstraints.KeyValuePair(
- "googHighpassFilter",
- "true"
- )
- )
- audioConstraints.mandatory.add(
- MediaConstraints.KeyValuePair(
- "googNoiseSuppression",
- "true"
- )
- )
- return audioConstraints
- }
-
- private fun offerOrAnswerConstraint(): MediaConstraints {
- val mediaConstraints = MediaConstraints()
- val keyValuePairs = java.util.ArrayList()
- keyValuePairs.add(MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"))
- keyValuePairs.add(MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"))
- mediaConstraints.mandatory.addAll(keyValuePairs)
- return mediaConstraints
- }
-
- private fun createJavaAudioDevice(): AudioDeviceModule {
- val audioTrackErrorCallback: JavaAudioDeviceModule.AudioTrackErrorCallback = object :
- JavaAudioDeviceModule.AudioTrackErrorCallback {
- override fun onWebRtcAudioTrackInitError(errorMessage: String) {
- Log.i(TAG, "onWebRtcAudioTrackInitError ============> $errorMessage")
-
- }
-
- override fun onWebRtcAudioTrackStartError(
- errorCode: JavaAudioDeviceModule.AudioTrackStartErrorCode, errorMessage: String
- ) {
- Log.i(TAG, "onWebRtcAudioTrackStartError ============> $errorCode:$errorMessage")
-
- }
-
- override fun onWebRtcAudioTrackError(errorMessage: String) {
- Log.i(TAG, "onWebRtcAudioTrackError ============> $errorMessage")
-
- }
- }
-
-
- // Set audio track state callbacks.
- val audioTrackStateCallback: JavaAudioDeviceModule.AudioTrackStateCallback = object :
- JavaAudioDeviceModule.AudioTrackStateCallback {
- override fun onWebRtcAudioTrackStart() {
- Log.i(TAG, "onWebRtcAudioTrackStart ============>")
-
- }
-
- override fun onWebRtcAudioTrackStop() {
- Log.i(TAG, "onWebRtcAudioTrackStop ============>")
-
- }
- }
-
- return JavaAudioDeviceModule.builder(mContext)
- .setUseHardwareAcousticEchoCanceler(true)
- .setUseHardwareNoiseSuppressor(true)
- .setAudioTrackErrorCallback(audioTrackErrorCallback)
- .setAudioTrackStateCallback(audioTrackStateCallback)
- .setUseStereoOutput(true) //立体声
- .createAudioDeviceModule()
- }
-
- fun setVideoPath(url: String) {
- videoUrl = url
- }
-
- fun start() {
-
- mLocalPeer = Peer {
- val okHttpClient = OkHttpClient.Builder().build()
-
-
- val body = RequestBody.create("text/plain; charset=utf-8".toMediaType(), it!!)
-
-
- val request: Request = Request.Builder()
- .url(videoUrl)
- .post(body)
- .build()
-
- val call: Call = okHttpClient.newCall(request)
-
- call.enqueue(object : Callback {
- override fun onFailure(call: Call, e: IOException) {
- Log.i(TAG, "onFailure")
- OnErrorListener?.invoke(
- ErrorCode.GET_REMOTE_SDP_ERROR.errorCode,
- e.message.toString()
- )
- }
-
- override fun onResponse(call: Call, response: Response) {
- val body = response.body?.string()
- val sdpResponse = Gson().fromJson(body, SdpResponse::class.java)
-
- try {
- mRemoteSessionDescription = SessionDescription(
- SessionDescription.Type.fromCanonicalForm("answer"),
- sdpResponse.sdp
- )
- Log.i(
- TAG,
- "RemoteSdpObserver onCreateSuccess:[SessionDescription[type=${mRemoteSessionDescription?.type?.name},description=${mRemoteSessionDescription?.description}]]"
- )
- mLocalPeer?.setRemoteDescription(mRemoteSessionDescription!!)
- } catch (e: Exception) {
- Log.i(TAG, e.toString())
- OnErrorListener.invoke(
- ErrorCode.GET_REMOTE_SDP_ERROR.errorCode,
- e.localizedMessage
- )
- }
- }
- })
- }
- }
-
- fun pause() {
- mSurfaceViewRenderer.pauseVideo()
- //mSurfaceViewRenderer.disableFpsReduction()
- }
-
- fun resume() {
- mSurfaceViewRenderer.setFpsReduction(15f)
- }
-
- fun screenshot(listener: (bitmap: Bitmap) -> Unit) {
- mSurfaceViewRenderer.addFrameListener({
- listener.invoke(it)
- }, 1f)
- }
-
- fun setSpeakerphoneOn(on: Boolean) {
- audioManager.isSpeakerphoneOn = on
- }
-
- fun mute(on:Boolean) {
- audioManager.isMicrophoneMute=on
- }
-
- override fun onDestroy(owner: LifecycleOwner) {
- super.onDestroy(owner)
- mSurfaceViewRenderer.release()
- mLocalPeer?.mPeerConnection?.dispose()
- mAudioSource?.dispose()
- mPeerConnectionFactory?.dispose()
- }
-
- override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec)
-
- }
-
- inner class Peer(var sdp: (String?) -> Unit = {}) : PeerConnection.Observer, SdpObserver {
-
- var mPeerConnection: PeerConnection? = null
-
- init {
- mPeerConnection = createPeerConnection()
- mPeerConnection?.createOffer(this, offerOrAnswerConstraint())
- }
-
- //初始化 RTCPeerConnection 连接管道
- private fun createPeerConnection(): PeerConnection? {
- if (mPeerConnectionFactory == null) {
- mPeerConnectionFactory = createConnectionFactory()
- }
- // 管道连接抽象类实现方法
- val ICEServers = LinkedList()
- val rtcConfig = PeerConnection.RTCConfiguration(ICEServers)
- //修改模式 PlanB无法使用仅接收音视频的配置
- //rtcConfig.sdpSemantics = PeerConnection.SdpSemantics.PLAN_B
- return mPeerConnectionFactory?.createPeerConnection(rtcConfig, this)
- }
-
- fun setRemoteDescription(sdp: SessionDescription) {
- mPeerConnection?.setRemoteDescription(this, sdp)
- }
-
- override fun onCreateSuccess(sessionDescription: SessionDescription?) {
- mPeerConnection?.setLocalDescription(this, sessionDescription)
- mPeerConnection?.addStream(mLocalMediaStream)
- sdp.invoke(sessionDescription?.description)
- }
-
- override fun onSetSuccess() {
-
- }
-
- override fun onCreateFailure(p0: String?) {
-
- }
-
- override fun onSetFailure(p0: String?) {
-
- }
-
- override fun onSignalingChange(signalingState: PeerConnection.SignalingState?) {
- Log.i(TAG, "onSignalingChange ============> " + signalingState.toString())
- }
-
- override fun onIceConnectionChange(iceConnectionState: PeerConnection.IceConnectionState?) {
- Log.i(TAG, "onIceConnectionChange ============> " + iceConnectionState.toString())
-
- }
-
- override fun onIceConnectionReceivingChange(p0: Boolean) {
- Log.i(TAG, "onIceConnectionReceivingChange ============> $p0")
-
- }
-
- override fun onIceGatheringChange(iceGatheringState: PeerConnection.IceGatheringState?) {
- Log.i(TAG, "onIceGatheringChange ============> ${iceGatheringState.toString()}")
- }
-
- override fun onIceCandidate(iceCandidate: IceCandidate?) {
- Log.i(TAG, "onIceCandidate ============> ${iceCandidate.toString()}")
-
-
- }
-
- override fun onIceCandidatesRemoved(p0: Array?) {
- Log.i(TAG, "onIceCandidatesRemoved ============> ${p0.toString()}")
- }
-
- override fun onAddStream(mediaStream: MediaStream?) {
- Log.i(TAG, "onAddStream ============> ${mediaStream?.toString()}")
-
- if (mediaStream?.videoTracks?.isEmpty() != true) {
- val remoteVideoTrack = mediaStream?.videoTracks?.get(0)
- remoteVideoTrack?.setEnabled(true)
- remoteVideoTrack?.addSink(mSurfaceViewRenderer)
- }
-
- if (mediaStream?.audioTracks?.isEmpty() != true) {
- val remoteAudioTrack = mediaStream?.audioTracks?.get(0)
- remoteAudioTrack?.setEnabled(true)
- remoteAudioTrack?.setVolume(1.0)
- }
-
-
- }
-
- override fun onRemoveStream(mediaStream: MediaStream?) {
- Log.i(TAG, "onRemoveStream ============> ${mediaStream.toString()}")
-
- }
-
- override fun onDataChannel(dataChannel: DataChannel?) {
- Log.i(TAG, "onDataChannel ============> ${dataChannel.toString()}")
-
- }
-
- override fun onRenegotiationNeeded() {
- Log.i(TAG, "onRenegotiationNeeded ============>")
-
- }
-
- override fun onAddTrack(rtpReceiver: RtpReceiver?, p1: Array?) {
- Log.i(TAG, "onAddTrack ============>" + rtpReceiver?.track())
- Log.i(TAG, "onAddTrack ============>" + p1?.size)
-
- }
- }
-
- override fun onFirstFrameRendered() {
- Log.i(TAG, "onFirstFrameRendered ============>")
-
- }
-
- override fun onFrameResolutionChanged(frameWidth: Int, frameHeight: Int, rotation: Int) {
- Log.i(TAG, "onFrameResolutionChanged ============> $frameWidth:$frameHeight:$rotation")
- //set(frameWidth,frameHeight)
- }
-
-
-
-
-}
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/webrtc_player/android/app/src/main/res/drawable/ic_launcher_foreground.xml
similarity index 100%
rename from webrtc_player/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
rename to webrtc_player/android/app/src/main/res/drawable/ic_launcher_foreground.xml
diff --git a/webrtc_player/android/app/src/main/res/layout/activity_main.xml b/webrtc_player/android/app/src/main/res/layout/activity_main.xml
index fdefb4e5..afb6529b 100644
--- a/webrtc_player/android/app/src/main/res/layout/activity_main.xml
+++ b/webrtc_player/android/app/src/main/res/layout/activity_main.xml
@@ -1,93 +1,22 @@
-
+ android:orientation="vertical">
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:onClick="toPushActivity"
+ android:text="推流" />
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/res/layout/activity_player.xml b/webrtc_player/android/app/src/main/res/layout/activity_player.xml
new file mode 100644
index 00000000..eebedc84
--- /dev/null
+++ b/webrtc_player/android/app/src/main/res/layout/activity_player.xml
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/res/layout/activity_pusher.xml b/webrtc_player/android/app/src/main/res/layout/activity_pusher.xml
new file mode 100644
index 00000000..484ee730
--- /dev/null
+++ b/webrtc_player/android/app/src/main/res/layout/activity_pusher.xml
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/res/layout/layout_videoview.xml b/webrtc_player/android/app/src/main/res/layout/layout_videoview.xml
deleted file mode 100644
index 43c56e5e..00000000
--- a/webrtc_player/android/app/src/main/res/layout/layout_videoview.xml
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/webrtc_player/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
index eca70cfe..6f3b755b 100644
--- a/webrtc_player/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ b/webrtc_player/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -2,4 +2,5 @@
+
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/webrtc_player/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
index eca70cfe..6f3b755b 100644
--- a/webrtc_player/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ b/webrtc_player/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -2,4 +2,5 @@
+
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/res/values-night/themes.xml b/webrtc_player/android/app/src/main/res/values-night/themes.xml
index 6a2a7eac..79caf632 100644
--- a/webrtc_player/android/app/src/main/res/values-night/themes.xml
+++ b/webrtc_player/android/app/src/main/res/values-night/themes.xml
@@ -1,16 +1,7 @@
-
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/res/values/colors.xml b/webrtc_player/android/app/src/main/res/values/colors.xml
index f8c6127d..c8524cd9 100644
--- a/webrtc_player/android/app/src/main/res/values/colors.xml
+++ b/webrtc_player/android/app/src/main/res/values/colors.xml
@@ -1,10 +1,5 @@
- #FFBB86FC
- #FF6200EE
- #FF3700B3
- #FF03DAC5
- #FF018786
#FF000000
#FFFFFFFF
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/res/values/strings.xml b/webrtc_player/android/app/src/main/res/values/strings.xml
index a7484826..5fb2987c 100644
--- a/webrtc_player/android/app/src/main/res/values/strings.xml
+++ b/webrtc_player/android/app/src/main/res/values/strings.xml
@@ -1,3 +1,3 @@
- AndroidWebRTC
+ RTCPlayer
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/main/res/values/themes.xml b/webrtc_player/android/app/src/main/res/values/themes.xml
index 119a9df9..df2c41fa 100644
--- a/webrtc_player/android/app/src/main/res/values/themes.xml
+++ b/webrtc_player/android/app/src/main/res/values/themes.xml
@@ -1,16 +1,9 @@
-
+
+
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/test/java/com/top/player/ExampleUnitTest.java b/webrtc_player/android/app/src/test/java/com/top/player/ExampleUnitTest.java
new file mode 100644
index 00000000..efe0b02d
--- /dev/null
+++ b/webrtc_player/android/app/src/test/java/com/top/player/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.top.player;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/webrtc_player/android/app/src/test/java/com/zlmediakit/webrtc/ExampleUnitTest.kt b/webrtc_player/android/app/src/test/java/com/zlmediakit/webrtc/ExampleUnitTest.kt
deleted file mode 100644
index 5f47259f..00000000
--- a/webrtc_player/android/app/src/test/java/com/zlmediakit/webrtc/ExampleUnitTest.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.zlmediakit.webrtc
-
-import org.junit.Test
-
-import org.junit.Assert.*
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * See [testing documentation](http://d.android.com/tools/testing).
- */
-class ExampleUnitTest {
- @Test
- fun addition_isCorrect() {
- assertEquals(4, 2 + 2)
- }
-}
\ No newline at end of file
diff --git a/webrtc_player/android/build.gradle b/webrtc_player/android/build.gradle
deleted file mode 100644
index c9fd0fc4..00000000
--- a/webrtc_player/android/build.gradle
+++ /dev/null
@@ -1,19 +0,0 @@
-// Top-level build file where you can add configuration options common to all sub-projects/modules.
-buildscript {
- ext.kotlin_version = '1.7.10'
- repositories {
- mavenCentral()
- }
- dependencies {
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- }
-}
-plugins {
- id 'com.android.application' version '7.2.1' apply false
- id 'com.android.library' version '7.2.1' apply false
- id 'org.jetbrains.kotlin.android' version '1.7.10' apply false
-}
-
-task clean(type: Delete) {
- delete rootProject.buildDir
-}
\ No newline at end of file
diff --git a/webrtc_player/android/build.gradle.kts b/webrtc_player/android/build.gradle.kts
new file mode 100644
index 00000000..2d2e5395
--- /dev/null
+++ b/webrtc_player/android/build.gradle.kts
@@ -0,0 +1,6 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ id("com.android.application") version "8.2.2" apply false
+ id("com.android.library") version "8.2.2" apply false
+ id("org.jetbrains.kotlin.android") version "1.9.22" apply false
+}
\ No newline at end of file
diff --git a/webrtc_player/android/doc/home.jpg b/webrtc_player/android/doc/home.jpg
new file mode 100644
index 00000000..186a2482
Binary files /dev/null and b/webrtc_player/android/doc/home.jpg differ
diff --git a/webrtc_player/android/gradle.properties b/webrtc_player/android/gradle.properties
index cd0519bb..3e927b11 100644
--- a/webrtc_player/android/gradle.properties
+++ b/webrtc_player/android/gradle.properties
@@ -12,11 +12,9 @@ org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
# AndroidX package structure to make it clearer which packages are bundled with the
-# Android operating system, and which are packaged with your app"s APK
+# Android operating system, and which are packaged with your app's APK
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
-# Kotlin code style for this project: "official" or "obsolete":
-kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
diff --git a/webrtc_player/android/gradle/wrapper/gradle-wrapper.properties b/webrtc_player/android/gradle/wrapper/gradle-wrapper.properties
index 8a5b4f05..7325acda 100644
--- a/webrtc_player/android/gradle/wrapper/gradle-wrapper.properties
+++ b/webrtc_player/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon Sep 19 22:08:36 CST 2022
+#Fri May 31 15:05:44 CST 2024
distributionBase=GRADLE_USER_HOME
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
distributionPath=wrapper/dists
-zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/webrtc_player/android/settings.gradle b/webrtc_player/android/settings.gradle
deleted file mode 100644
index 4a669b32..00000000
--- a/webrtc_player/android/settings.gradle
+++ /dev/null
@@ -1,24 +0,0 @@
-pluginManagement {
- repositories {
- gradlePluginPortal()
- google()
- mavenCentral()
- jcenter() // Warning: this repository is going to shut down soon
-
- maven { url 'https://jitpack.io' }
-
- }
-}
-dependencyResolutionManagement {
- repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
- repositories {
- google()
- mavenCentral()
- jcenter() // Warning: this repository is going to shut down soon
-
- maven { url 'https://jitpack.io' }
-
- }
-}
-rootProject.name = "android"
-include ':app'
diff --git a/webrtc_player/android/settings.gradle.kts b/webrtc_player/android/settings.gradle.kts
new file mode 100644
index 00000000..742455a4
--- /dev/null
+++ b/webrtc_player/android/settings.gradle.kts
@@ -0,0 +1,25 @@
+pluginManagement {
+ repositories {
+ mavenCentral()
+ gradlePluginPortal()
+ google()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ mavenCentral()
+ google()
+ maven {
+ credentials {
+ username = ("6256cd6c7e8dbc28d896a661")
+ password = ("KRuEgA3WYUVy")
+ }
+ url = uri("https://packages.aliyun.com/maven/repository/2302596-release-mpvXBR/")
+ }
+ }
+}
+
+rootProject.name = "RTCPlayer"
+include(":app")
+//include(":RTCPlayer")