集成 Timber 日志框架,降级 AGP/Gradle 适配 JDK 17,修复构建设置
- 新增 PosefitApplication 初始化 Timber DebugTree - WebRtcSenderClient/MainActivity/SimpleSdpObserver 添加 Timber 日志 - AGP 9.2.1 → 8.7.3,Gradle 9.4.1 → 8.11.1 适配 JDK 17 - compileSdk/targetSdk 恢复为 34,minSdk 保持 29 支持 Android 10 - 添加 android.useAndroidX=true 修复构建检查 - 删除 gradle-daemon-jvm.properties (JDK 21 残留配置) - 信令端口默认改为 8765
This commit is contained in:
@@ -29,6 +29,7 @@ android {
|
|||||||
}
|
}
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
compose true
|
compose true
|
||||||
|
buildConfig true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,6 +48,7 @@ dependencies {
|
|||||||
testImplementation libs.junit
|
testImplementation libs.junit
|
||||||
androidTestImplementation libs.espresso.core
|
androidTestImplementation libs.espresso.core
|
||||||
androidTestImplementation libs.ext.junit
|
androidTestImplementation libs.ext.junit
|
||||||
|
implementation libs.timber
|
||||||
implementation "io.getstream:stream-webrtc-android:1.3.10"
|
implementation "io.getstream:stream-webrtc-android:1.3.10"
|
||||||
implementation "com.squareup.okhttp3:okhttp:4.12.0"
|
implementation "com.squareup.okhttp3:okhttp:4.12.0"
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
android:required="true" />
|
android:required="true" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
|
android:name=".PosefitApplication"
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.kimgo.posefit.sender.WebRtcSenderClient
|
import com.kimgo.posefit.sender.WebRtcSenderClient
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
@@ -23,11 +24,14 @@ class MainActivity : ComponentActivity() {
|
|||||||
if (granted) {
|
if (granted) {
|
||||||
val url = getSavedSignalingUrl()
|
val url = getSavedSignalingUrl()
|
||||||
startWebRtc(url)
|
startWebRtc(url)
|
||||||
|
} else {
|
||||||
|
Timber.w("Camera permission denied")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
Timber.d("MainActivity onCreate")
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
MaterialTheme {
|
MaterialTheme {
|
||||||
@@ -87,7 +91,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
private fun getSavedSignalingUrl(): String {
|
private fun getSavedSignalingUrl(): String {
|
||||||
val prefs = getSharedPreferences("posefit_prefs", Context.MODE_PRIVATE)
|
val prefs = getSharedPreferences("posefit_prefs", Context.MODE_PRIVATE)
|
||||||
return prefs.getString("signaling_url", "ws://192.168.110.240:8080") ?: "ws://192.168.110.240:8080"
|
return prefs.getString("signaling_url", "ws://192.168.2.10:8765") ?: "ws://192.168.2.10:8765"
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun saveSignalingUrl(url: String) {
|
private fun saveSignalingUrl(url: String) {
|
||||||
@@ -96,6 +100,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun startWebRtc(url: String) {
|
private fun startWebRtc(url: String) {
|
||||||
|
Timber.i("startWebRtc: %s", url)
|
||||||
webRtcClient?.release()
|
webRtcClient?.release()
|
||||||
webRtcClient = WebRtcSenderClient(
|
webRtcClient = WebRtcSenderClient(
|
||||||
context = this,
|
context = this,
|
||||||
@@ -105,6 +110,7 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun stopWebRtc() {
|
private fun stopWebRtc() {
|
||||||
|
Timber.i("stopWebRtc")
|
||||||
webRtcClient?.release()
|
webRtcClient?.release()
|
||||||
webRtcClient = null
|
webRtcClient = null
|
||||||
}
|
}
|
||||||
@@ -112,5 +118,6 @@ class MainActivity : ComponentActivity() {
|
|||||||
override fun onDestroy() {
|
override fun onDestroy() {
|
||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
stopWebRtc()
|
stopWebRtc()
|
||||||
|
Timber.d("MainActivity onDestroy")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.kimgo.posefit
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
class PosefitApplication : Application() {
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Timber.plant(Timber.DebugTree())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,11 +2,16 @@ package com.kimgo.posefit.sender
|
|||||||
|
|
||||||
import org.webrtc.SdpObserver
|
import org.webrtc.SdpObserver
|
||||||
import org.webrtc.SessionDescription
|
import org.webrtc.SessionDescription
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
|
||||||
open class SimpleSdpObserver : SdpObserver {
|
open class SimpleSdpObserver : SdpObserver {
|
||||||
override fun onCreateSuccess(desc: SessionDescription) {}
|
override fun onCreateSuccess(desc: SessionDescription) {}
|
||||||
override fun onSetSuccess() {}
|
override fun onSetSuccess() {}
|
||||||
override fun onCreateFailure(error: String) {}
|
override fun onCreateFailure(error: String) {
|
||||||
override fun onSetFailure(error: String) {}
|
Timber.e("SDP onCreateFailure: %s", error)
|
||||||
|
}
|
||||||
|
override fun onSetFailure(error: String) {
|
||||||
|
Timber.e("SDP onSetFailure: %s", error)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ import android.content.Context
|
|||||||
import okhttp3.*
|
import okhttp3.*
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import org.webrtc.*
|
import org.webrtc.*
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
class WebRtcSenderClient(
|
class WebRtcSenderClient(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
@@ -23,6 +24,7 @@ class WebRtcSenderClient(
|
|||||||
private var surfaceTextureHelper: SurfaceTextureHelper? = null
|
private var surfaceTextureHelper: SurfaceTextureHelper? = null
|
||||||
|
|
||||||
fun start() {
|
fun start() {
|
||||||
|
Timber.i("WebRTC starting, signalingUrl=%s", signalingUrl)
|
||||||
initPeerConnectionFactory()
|
initPeerConnectionFactory()
|
||||||
connectSignaling()
|
connectSignaling()
|
||||||
}
|
}
|
||||||
@@ -47,6 +49,8 @@ class WebRtcSenderClient(
|
|||||||
.setVideoEncoderFactory(encoderFactory)
|
.setVideoEncoderFactory(encoderFactory)
|
||||||
.setVideoDecoderFactory(decoderFactory)
|
.setVideoDecoderFactory(decoderFactory)
|
||||||
.createPeerConnectionFactory()
|
.createPeerConnectionFactory()
|
||||||
|
|
||||||
|
Timber.d("PeerConnectionFactory initialized")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun connectSignaling() {
|
private fun connectSignaling() {
|
||||||
@@ -57,6 +61,7 @@ class WebRtcSenderClient(
|
|||||||
webSocket = okHttpClient.newWebSocket(request, object : WebSocketListener() {
|
webSocket = okHttpClient.newWebSocket(request, object : WebSocketListener() {
|
||||||
|
|
||||||
override fun onOpen(webSocket: WebSocket, response: Response) {
|
override fun onOpen(webSocket: WebSocket, response: Response) {
|
||||||
|
Timber.d("Signaling WebSocket connected")
|
||||||
createPeerConnection()
|
createPeerConnection()
|
||||||
startCamera()
|
startCamera()
|
||||||
createOffer()
|
createOffer()
|
||||||
@@ -65,6 +70,14 @@ class WebRtcSenderClient(
|
|||||||
override fun onMessage(webSocket: WebSocket, text: String) {
|
override fun onMessage(webSocket: WebSocket, text: String) {
|
||||||
handleSignalingMessage(text)
|
handleSignalingMessage(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {
|
||||||
|
Timber.e(t, "Signaling WebSocket failure")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
|
||||||
|
Timber.w("Signaling WebSocket closed, code=%d, reason=%s", code, reason)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,10 +106,16 @@ class WebRtcSenderClient(
|
|||||||
webSocket.send(json.toString())
|
webSocket.send(json.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onIceConnectionChange(state: PeerConnection.IceConnectionState) {
|
||||||
|
Timber.d("ICE connection state: %s", state)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onIceGatheringChange(state: PeerConnection.IceGatheringState) {
|
||||||
|
Timber.d("ICE gathering state: %s", state)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onSignalingChange(state: PeerConnection.SignalingState) {}
|
override fun onSignalingChange(state: PeerConnection.SignalingState) {}
|
||||||
override fun onIceConnectionChange(state: PeerConnection.IceConnectionState) {}
|
|
||||||
override fun onIceConnectionReceivingChange(receiving: Boolean) {}
|
override fun onIceConnectionReceivingChange(receiving: Boolean) {}
|
||||||
override fun onIceGatheringChange(state: PeerConnection.IceGatheringState) {}
|
|
||||||
override fun onIceCandidatesRemoved(candidates: Array<out IceCandidate>) {}
|
override fun onIceCandidatesRemoved(candidates: Array<out IceCandidate>) {}
|
||||||
override fun onAddStream(stream: MediaStream) {}
|
override fun onAddStream(stream: MediaStream) {}
|
||||||
override fun onRemoveStream(stream: MediaStream) {}
|
override fun onRemoveStream(stream: MediaStream) {}
|
||||||
@@ -137,6 +156,8 @@ class WebRtcSenderClient(
|
|||||||
videoTrack,
|
videoTrack,
|
||||||
listOf("posefit_stream")
|
listOf("posefit_stream")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Timber.d("Camera started: %s, resolution=1280x720@30fps", cameraName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createOffer() {
|
private fun createOffer() {
|
||||||
@@ -160,17 +181,27 @@ class WebRtcSenderClient(
|
|||||||
}
|
}
|
||||||
|
|
||||||
webSocket.send(json.toString())
|
webSocket.send(json.toString())
|
||||||
|
Timber.d("Offer sent via signaling")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSetFailure(error: String) {
|
||||||
|
Timber.e("setLocalDescription failed: %s", error)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSetFailure(error: String) {}
|
|
||||||
override fun onCreateSuccess(desc: SessionDescription) {}
|
override fun onCreateSuccess(desc: SessionDescription) {}
|
||||||
override fun onCreateFailure(error: String) {}
|
override fun onCreateFailure(error: String) {
|
||||||
|
Timber.e("createOffer failed: %s", error)
|
||||||
|
}
|
||||||
}, desc)
|
}, desc)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onSetSuccess() {}
|
override fun onSetSuccess() {}
|
||||||
override fun onCreateFailure(error: String) {}
|
override fun onCreateFailure(error: String) {
|
||||||
override fun onSetFailure(error: String) {}
|
Timber.e("createOffer failed: %s", error)
|
||||||
|
}
|
||||||
|
override fun onSetFailure(error: String) {
|
||||||
|
Timber.e("setLocalDescription failed: %s", error)
|
||||||
|
}
|
||||||
|
|
||||||
}, constraints)
|
}, constraints)
|
||||||
}
|
}
|
||||||
@@ -189,6 +220,7 @@ class WebRtcSenderClient(
|
|||||||
SimpleSdpObserver(),
|
SimpleSdpObserver(),
|
||||||
sdp
|
sdp
|
||||||
)
|
)
|
||||||
|
Timber.d("Answer received from server")
|
||||||
}
|
}
|
||||||
|
|
||||||
"candidate" -> {
|
"candidate" -> {
|
||||||
@@ -204,6 +236,8 @@ class WebRtcSenderClient(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun release() {
|
fun release() {
|
||||||
|
Timber.i("WebRTC releasing")
|
||||||
|
|
||||||
try {
|
try {
|
||||||
videoCapturer?.stopCapture()
|
videoCapturer?.stopCapture()
|
||||||
} catch (_: Exception) {
|
} catch (_: Exception) {
|
||||||
@@ -219,5 +253,7 @@ class WebRtcSenderClient(
|
|||||||
eglBase.release()
|
eglBase.release()
|
||||||
webSocket.close(1000, "close")
|
webSocket.close(1000, "close")
|
||||||
okHttpClient.dispatcher.executorService.shutdown()
|
okHttpClient.dispatcher.executorService.shutdown()
|
||||||
|
|
||||||
|
Timber.d("WebRTC released")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
plugins {
|
plugins {
|
||||||
alias(libs.plugins.android.application) apply false
|
alias(libs.plugins.android.application) apply false
|
||||||
|
alias(libs.plugins.jetbrains.kotlin.android) apply false
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,8 @@
|
|||||||
# Specifies the JVM arguments used for the daemon process.
|
# Specifies the JVM arguments used for the daemon process.
|
||||||
# The setting is particularly useful for tweaking memory settings.
|
# The setting is particularly useful for tweaking memory settings.
|
||||||
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
||||||
|
org.gradle.java.home=C\:\\Program Files\\Java\\jdk-17
|
||||||
|
android.useAndroidX=true
|
||||||
# When configured, Gradle will run in incubating parallel mode.
|
# When configured, Gradle will run in incubating parallel mode.
|
||||||
# This option should only be used with decoupled projects. For more details, visit
|
# This option should only be used with decoupled projects. For more details, visit
|
||||||
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
|
# https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
#This file is generated by updateDaemonJvm
|
|
||||||
toolchainUrl.FREE_BSD.AARCH64=https\://api.foojay.io/disco/v3.0/ids/ec7520a1e057cd116f9544c42142a16b/redirect
|
|
||||||
toolchainUrl.FREE_BSD.X86_64=https\://api.foojay.io/disco/v3.0/ids/4c4f879899012ff0a8b2e2117df03b0e/redirect
|
|
||||||
toolchainUrl.LINUX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/ec7520a1e057cd116f9544c42142a16b/redirect
|
|
||||||
toolchainUrl.LINUX.X86_64=https\://api.foojay.io/disco/v3.0/ids/4c4f879899012ff0a8b2e2117df03b0e/redirect
|
|
||||||
toolchainUrl.MAC_OS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/73bcfb608d1fde9fb62e462f834a3299/redirect
|
|
||||||
toolchainUrl.MAC_OS.X86_64=https\://api.foojay.io/disco/v3.0/ids/846ee0d876d26a26f37aa1ce8de73224/redirect
|
|
||||||
toolchainUrl.UNIX.AARCH64=https\://api.foojay.io/disco/v3.0/ids/ec7520a1e057cd116f9544c42142a16b/redirect
|
|
||||||
toolchainUrl.UNIX.X86_64=https\://api.foojay.io/disco/v3.0/ids/4c4f879899012ff0a8b2e2117df03b0e/redirect
|
|
||||||
toolchainUrl.WINDOWS.AARCH64=https\://api.foojay.io/disco/v3.0/ids/9482ddec596298c84656d31d16652665/redirect
|
|
||||||
toolchainUrl.WINDOWS.X86_64=https\://api.foojay.io/disco/v3.0/ids/39701d92e1756bb2f141eb67cd4c660e/redirect
|
|
||||||
toolchainVersion=21
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
[versions]
|
[versions]
|
||||||
agp = "9.2.1"
|
agp = "8.7.3"
|
||||||
kotlin = "2.0.0"
|
kotlin = "2.0.0"
|
||||||
composeBom = "2024.02.00"
|
composeBom = "2024.02.00"
|
||||||
composeCompiler = "1.5.8"
|
composeCompiler = "1.5.8"
|
||||||
@@ -11,8 +11,10 @@ junitVersion = "1.1.5"
|
|||||||
espressoCore = "3.5.1"
|
espressoCore = "3.5.1"
|
||||||
appcompat = "1.6.1"
|
appcompat = "1.6.1"
|
||||||
material = "1.10.0"
|
material = "1.10.0"
|
||||||
|
timber = "5.0.1"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
|
timber = { group = "com.jakewharton.timber", name = "timber", version.ref = "timber" }
|
||||||
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
junit = { group = "junit", name = "junit", version.ref = "junit" }
|
||||||
ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
|
||||||
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
|
||||||
|
|||||||
+2
-3
@@ -1,9 +1,8 @@
|
|||||||
#Mon Jun 01 17:35:27 CST 2026
|
#Mon Jun 01 17:35:27 CST 2026
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionSha256Sum=2ab2958f2a1e51120c326cad6f385153bb11ee93b3c216c5fccebfdfbb7ec6cb
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
|
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=false
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
Reference in New Issue
Block a user