正在显示
5 个修改的文件
包含
126 行增加
和
5 行删除
| @@ -12,6 +12,7 @@ buildscript { | @@ -12,6 +12,7 @@ buildscript { | ||
| 12 | dependencies { | 12 | dependencies { |
| 13 | classpath 'com.android.tools.build:gradle:4.1.2' | 13 | classpath 'com.android.tools.build:gradle:4.1.2' |
| 14 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" | 14 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" |
| 15 | + classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" | ||
| 15 | classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.15' | 16 | classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.15' |
| 16 | // NOTE: Do not place your application dependencies here; they belong | 17 | // NOTE: Do not place your application dependencies here; they belong |
| 17 | // in the individual module build.gradle files | 18 | // in the individual module build.gradle files |
| 1 | apply plugin: 'com.android.library' | 1 | apply plugin: 'com.android.library' |
| 2 | apply plugin: 'kotlin-android' | 2 | apply plugin: 'kotlin-android' |
| 3 | +apply plugin: 'kotlinx-serialization' | ||
| 3 | apply plugin: 'com.google.protobuf' | 4 | apply plugin: 'com.google.protobuf' |
| 4 | 5 | ||
| 5 | android { | 6 | android { |
| @@ -53,6 +54,7 @@ dependencies { | @@ -53,6 +54,7 @@ dependencies { | ||
| 53 | implementation fileTree(dir: 'libs', include: ['*.jar']) | 54 | implementation fileTree(dir: 'libs', include: ['*.jar']) |
| 54 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" | 55 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" |
| 55 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2' | 56 | implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.2' |
| 57 | + implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.1.0' | ||
| 56 | implementation 'org.webrtc:google-webrtc:1.0.32006' | 58 | implementation 'org.webrtc:google-webrtc:1.0.32006' |
| 57 | implementation "com.squareup.okhttp3:okhttp:4.9.0" | 59 | implementation "com.squareup.okhttp3:okhttp:4.9.0" |
| 58 | implementation "com.google.protobuf:protobuf-java:${versions.protobuf}" | 60 | implementation "com.google.protobuf:protobuf-java:${versions.protobuf}" |
| @@ -19,3 +19,26 @@ | @@ -19,3 +19,26 @@ | ||
| 19 | # If you keep the line number information, uncomment this to | 19 | # If you keep the line number information, uncomment this to |
| 20 | # hide the original source file name. | 20 | # hide the original source file name. |
| 21 | #-renamesourcefileattribute SourceFile | 21 | #-renamesourcefileattribute SourceFile |
| 22 | + | ||
| 23 | +# Kotlin Serialization Proguard Rules | ||
| 24 | +######################################## | ||
| 25 | + | ||
| 26 | +-keepattributes *Annotation*, InnerClasses | ||
| 27 | +-dontnote kotlinx.serialization.AnnotationsKt # core serialization annotations | ||
| 28 | + | ||
| 29 | +# kotlinx-serialization-json specific. Add this if you have java.lang.NoClassDefFoundError kotlinx.serialization.json.JsonObjectSerializer | ||
| 30 | +-keepclassmembers class kotlinx.serialization.json.** { | ||
| 31 | + *** Companion; | ||
| 32 | +} | ||
| 33 | +-keepclasseswithmembers class kotlinx.serialization.json.** { | ||
| 34 | + kotlinx.serialization.KSerializer serializer(...); | ||
| 35 | +} | ||
| 36 | + | ||
| 37 | +# Change here com.yourcompany.yourpackage | ||
| 38 | +-keep,includedescriptorclasses class io.livekit.android.**$$serializer { *; } # <-- change package name to your app's | ||
| 39 | +-keepclassmembers class io.livekit.android.** { # <-- change package name to your app's | ||
| 40 | + *** Companion; | ||
| 41 | +} | ||
| 42 | +-keepclasseswithmembers class io.livekit.android.** { # <-- change package name to your app's | ||
| 43 | + kotlinx.serialization.KSerializer serializer(...); | ||
| 44 | +} |
| @@ -2,6 +2,9 @@ package io.livekit.android.room | @@ -2,6 +2,9 @@ package io.livekit.android.room | ||
| 2 | 2 | ||
| 3 | import com.github.ajalt.timberkt.Timber | 3 | import com.github.ajalt.timberkt.Timber |
| 4 | import com.google.protobuf.util.JsonFormat | 4 | import com.google.protobuf.util.JsonFormat |
| 5 | +import kotlinx.serialization.decodeFromString | ||
| 6 | +import kotlinx.serialization.encodeToString | ||
| 7 | +import kotlinx.serialization.json.Json | ||
| 5 | import livekit.Model | 8 | import livekit.Model |
| 6 | import livekit.Rtc | 9 | import livekit.Rtc |
| 7 | import okhttp3.Request | 10 | import okhttp3.Request |
| @@ -9,6 +12,7 @@ import okhttp3.Response | @@ -9,6 +12,7 @@ import okhttp3.Response | ||
| 9 | import okhttp3.WebSocket | 12 | import okhttp3.WebSocket |
| 10 | import okhttp3.WebSocketListener | 13 | import okhttp3.WebSocketListener |
| 11 | import okio.ByteString | 14 | import okio.ByteString |
| 15 | +import org.webrtc.IceCandidate | ||
| 12 | import org.webrtc.SessionDescription | 16 | import org.webrtc.SessionDescription |
| 13 | import javax.inject.Inject | 17 | import javax.inject.Inject |
| 14 | 18 | ||
| @@ -102,6 +106,85 @@ constructor( | @@ -102,6 +106,85 @@ constructor( | ||
| 102 | return sdBuilder.build() | 106 | return sdBuilder.build() |
| 103 | } | 107 | } |
| 104 | 108 | ||
| 109 | + fun sendOffer(offer: SessionDescription) { | ||
| 110 | + val sd = toProtoSessionDescription(offer) | ||
| 111 | + val request = Rtc.SignalRequest.newBuilder() | ||
| 112 | + .setOffer(sd) | ||
| 113 | + .build() | ||
| 114 | + | ||
| 115 | + sendRequest(request) | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + fun sendAnswer(answer: SessionDescription) { | ||
| 119 | + val sd = toProtoSessionDescription(answer) | ||
| 120 | + val request = Rtc.SignalRequest.newBuilder() | ||
| 121 | + .setAnswer(sd) | ||
| 122 | + .build() | ||
| 123 | + | ||
| 124 | + sendRequest(request) | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + fun sendCandidate(candidate: IceCandidate, target: Rtc.SignalTarget){ | ||
| 128 | + val iceCandidateJSON = IceCandidateJSON( | ||
| 129 | + sdp = candidate.sdp, | ||
| 130 | + sdpMid = candidate.sdpMid, | ||
| 131 | + sdpMLineIndex = candidate.sdpMLineIndex | ||
| 132 | + ) | ||
| 133 | + | ||
| 134 | + val trickleRequest = Rtc.TrickleRequest.newBuilder() | ||
| 135 | + .setCandidateInit(Json.encodeToString(iceCandidateJSON)) | ||
| 136 | + .setTarget(target) | ||
| 137 | + .build() | ||
| 138 | + | ||
| 139 | + val request = Rtc.SignalRequest.newBuilder() | ||
| 140 | + .setTrickle(trickleRequest) | ||
| 141 | + .build() | ||
| 142 | + | ||
| 143 | + sendRequest(request) | ||
| 144 | + } | ||
| 145 | + | ||
| 146 | + fun sendMuteTrack(trackSid: String, muted: Boolean) { | ||
| 147 | + val muteRequest = Rtc.MuteTrackRequest.newBuilder() | ||
| 148 | + .setSid(trackSid) | ||
| 149 | + .setMuted(muted) | ||
| 150 | + .build() | ||
| 151 | + | ||
| 152 | + val request = Rtc.SignalRequest.newBuilder() | ||
| 153 | + .setMute(muteRequest) | ||
| 154 | + .build() | ||
| 155 | + | ||
| 156 | + sendRequest(request) | ||
| 157 | + } | ||
| 158 | + | ||
| 159 | + fun sendAddTrack(cid: String, name: String, type: Model.TrackType) { | ||
| 160 | + val addTrackRequest = Rtc.AddTrackRequest.newBuilder() | ||
| 161 | + .setCid(cid) | ||
| 162 | + .setName(name) | ||
| 163 | + .setType(type) | ||
| 164 | + .build() | ||
| 165 | + | ||
| 166 | + val request = Rtc.SignalRequest.newBuilder() | ||
| 167 | + .setAddTrack(addTrackRequest) | ||
| 168 | + .build() | ||
| 169 | + | ||
| 170 | + sendRequest(request) | ||
| 171 | + } | ||
| 172 | + | ||
| 173 | + fun sendRequest(request: Rtc.SignalRequest) { | ||
| 174 | + Timber.v { "sending request: $request" } | ||
| 175 | + if (!isConnected || currentWs != null) { | ||
| 176 | + throw IllegalStateException("not connected!") | ||
| 177 | + } | ||
| 178 | + val message = toJson.print(request) | ||
| 179 | + val sent = currentWs?.send(message) ?: false | ||
| 180 | + | ||
| 181 | + if (!sent) { | ||
| 182 | + Timber.d { "error sending request: $request" } | ||
| 183 | + throw IllegalStateException() | ||
| 184 | + } | ||
| 185 | + | ||
| 186 | + } | ||
| 187 | + | ||
| 105 | fun handleSignalResponse(response: Rtc.SignalResponse) { | 188 | fun handleSignalResponse(response: Rtc.SignalResponse) { |
| 106 | if (!isConnected) { | 189 | if (!isConnected) { |
| 107 | Timber.e { "Received response while not connected. ${toJson.print(response)}" } | 190 | Timber.e { "Received response while not connected. ${toJson.print(response)}" } |
| @@ -116,9 +199,16 @@ constructor( | @@ -116,9 +199,16 @@ constructor( | ||
| 116 | val sd = fromProtoSessionDescription(response.offer) | 199 | val sd = fromProtoSessionDescription(response.offer) |
| 117 | listener?.onOffer(sd) | 200 | listener?.onOffer(sd) |
| 118 | } | 201 | } |
| 119 | -// Rtc.SignalResponse.MessageCase.TRICKLE -> { | ||
| 120 | -// TODO() | ||
| 121 | -// } | 202 | + Rtc.SignalResponse.MessageCase.TRICKLE -> { |
| 203 | + val iceCandidateJson = | ||
| 204 | + Json.decodeFromString<IceCandidateJSON>(response.trickle.candidateInit) | ||
| 205 | + val iceCandidate = IceCandidate( | ||
| 206 | + iceCandidateJson.sdpMid, | ||
| 207 | + iceCandidateJson.sdpMLineIndex, | ||
| 208 | + iceCandidateJson.sdp | ||
| 209 | + ) | ||
| 210 | + listener?.onTrickle(iceCandidate, response.trickle.target) | ||
| 211 | + } | ||
| 122 | Rtc.SignalResponse.MessageCase.UPDATE -> { | 212 | Rtc.SignalResponse.MessageCase.UPDATE -> { |
| 123 | listener?.onParticipantUpdate(response.update.participantsList) | 213 | listener?.onParticipantUpdate(response.update.participantsList) |
| 124 | } | 214 | } |
| @@ -131,7 +221,6 @@ constructor( | @@ -131,7 +221,6 @@ constructor( | ||
| 131 | Timber.v { "unhandled response type: ${response.messageCase.name}" } | 221 | Timber.v { "unhandled response type: ${response.messageCase.name}" } |
| 132 | } | 222 | } |
| 133 | } | 223 | } |
| 134 | - | ||
| 135 | } | 224 | } |
| 136 | 225 | ||
| 137 | interface Listener { | 226 | interface Listener { |
| @@ -140,7 +229,7 @@ constructor( | @@ -140,7 +229,7 @@ constructor( | ||
| 140 | fun onAnswer(sessionDescription: SessionDescription) | 229 | fun onAnswer(sessionDescription: SessionDescription) |
| 141 | fun onOffer(sessionDescription: SessionDescription) | 230 | fun onOffer(sessionDescription: SessionDescription) |
| 142 | 231 | ||
| 143 | - //fun onTrickle(candidate: RTCIceCandidate, target: Rtc.SignalTarget) | 232 | + fun onTrickle(candidate: IceCandidate, target: Rtc.SignalTarget) |
| 144 | fun onLocalTrackPublished(trackPublished: Rtc.TrackPublishedResponse) | 233 | fun onLocalTrackPublished(trackPublished: Rtc.TrackPublishedResponse) |
| 145 | fun onParticipantUpdate(updates: List<Model.ParticipantInfo>) | 234 | fun onParticipantUpdate(updates: List<Model.ParticipantInfo>) |
| 146 | fun onClose(reason: String, code: Int) | 235 | fun onClose(reason: String, code: Int) |
-
请 注册 或 登录 后发表评论