android(call): Increment 2a — native LiveKit call audio, background service, speaker/BT routing
Replaces WebView call media on Android with a native LiveKit connection (iOS parity), so call audio survives backgrounding and the output can be switched to Speaker/Bluetooth/Earpiece — the #3 (missing speaker control) and #4 (background audio) items. Gated behind a new, default-off server flag ANDROID_NATIVE_MEDIA (independent of ANDROID_CALLS, which only governs the native ring). Flag off = today's WebView media, video included; flag on = native audio (video is Increment 2b, so enable it for VOICE testing first). No behavior change until flipped. Native (mobile/plugins/native-call/android): - build.gradle: add kotlin-android + io.livekit:livekit-android 2.29.2 (+ twilio audioswitch, coroutines) + JitPack repo; minSdk 24 (LiveKit floor). - CallMedia.kt: LiveKit Room wrapper — connect/mic/disconnect + AudioSwitchHandler routing (auto + selectDevice) and route-change events. - CallForegroundService.java: microphone-type foreground service for background audio (no-ops without RECORD_AUDIO so it never crashes the call). - NativeCallPlugin.java: real bodies for reportOutgoingCall/reconnectRoom/setMuted /endCall + new setAudioRoute/getAudioRoute; fires callConnected/callError/audioRoute. - AndroidManifest: FG service + FOREGROUND_SERVICE(_MICROPHONE)/RECORD_AUDIO/ MODIFY_AUDIO_SETTINGS/BLUETOOTH_CONNECT. - android-patch.js: bump the generated app minSdk to 24. Server: - config.js/routes.js: ANDROID_NATIVE_MEDIA → /api/meetings/config.androidNativeMedia. Web (home.html): - Android flips to the native-media path when androidNativeMedia is set; the existing outgoing/answer/mic/end code then drives the plugin unchanged. - Speaker button wired for Android native: cycles speaker/earpiece/bluetooth via NC.setAudioRoute and reflects the real output from the audioRoute event. Video stays no-op on the native path (Increment 2b). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
08eff043ec
commit
aa4aeeaba1
9 files changed
+444
-24
No files matched your search
@@ -1,32 +1,48 @@
|
||||
// Android build for the native-call plugin. Mirrors the official @capacitor/* plugin module layout (see
|
||||
// node_modules/@capacitor/status-bar/android/build.gradle) so it drops into the CI-generated app exactly like
|
||||
// the plugins that already build. Java (not Kotlin) to match the proven official-plugin structure — no extra
|
||||
// kotlin-gradle-plugin wiring in the library module, one less thing to fail when authored blind.
|
||||
// node_modules/@capacitor/status-bar/android/build.gradle) so it drops into the CI-generated app like the
|
||||
// plugins that already build.
|
||||
//
|
||||
// INCREMENT 2 adds native LiveKit call media (background audio + Speaker/Bluetooth routing), which is a Kotlin +
|
||||
// coroutines SDK — so this module now also applies kotlin-android (the ring/plugin glue stays Java). Capacitor
|
||||
// pulls the Kotlin stdlib via a BOM but does NOT apply the Kotlin Gradle plugin at the root, so we bring it here
|
||||
// (the standard community-plugin pattern); the classpath is additive to the generated root's AGP.
|
||||
ext {
|
||||
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
||||
androidxCoreVersion = project.hasProperty('androidxCoreVersion') ? rootProject.ext.androidxCoreVersion : '1.12.0'
|
||||
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.6.1'
|
||||
// Same FCM version the @capacitor/push-notifications plugin pulls in, so we don't fork the Firebase version.
|
||||
firebaseMessagingVersion = project.hasProperty('firebaseMessagingVersion') ? rootProject.ext.firebaseMessagingVersion : '23.3.1'
|
||||
// Follow the project's Kotlin (Capacitor pins kotlin_version at the root); fall back to a recent stable.
|
||||
bzcKotlinVersion = rootProject.hasProperty('kotlin_version') ? rootProject.ext.kotlin_version : '1.9.24'
|
||||
// LiveKit Android SDK — native background call media (Increment 2). Pinned; bump deliberately.
|
||||
livekitVersion = '2.29.2'
|
||||
audioswitchVersion = '1.2.0'
|
||||
coroutinesVersion = '1.8.1'
|
||||
}
|
||||
|
||||
buildscript {
|
||||
ext.bzc_kotlin = rootProject.hasProperty('kotlin_version') ? rootProject.ext.kotlin_version : '1.9.24'
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.2.1'
|
||||
// Kotlin Gradle plugin so this module can compile the .kt LiveKit wrapper. Additive to the root's AGP.
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$bzc_kotlin"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
android {
|
||||
namespace "com.bizgaze.connect.nativecall"
|
||||
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 34
|
||||
// LiveKit 2.29 compiles against a recent platform; honor the CI root (Capacitor 8 = 35) and floor at 35.
|
||||
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
|
||||
defaultConfig {
|
||||
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
|
||||
// LiveKit Android's floor. The app min is bumped to 24 in CI (android-patch.js) so the merge holds.
|
||||
minSdkVersion 24
|
||||
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 34
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
@@ -44,11 +60,16 @@ android {
|
||||
sourceCompatibility JavaVersion.VERSION_17
|
||||
targetCompatibility JavaVersion.VERSION_17
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '17'
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
// LiveKit pulls transitive artifacts (its WebRTC fork) that live on JitPack.
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
@@ -62,4 +83,11 @@ dependencies {
|
||||
// RemoteMessage / FirebaseMessaging (transitive from the push plugin, but declared so this module compiles
|
||||
// against it directly; same version → no resolution conflict).
|
||||
implementation "com.google.firebase:firebase-messaging:$firebaseMessagingVersion"
|
||||
// Kotlin + coroutines for the native LiveKit media wrapper (CallMedia.kt).
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$bzcKotlinVersion"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion"
|
||||
// Native call media (background audio) + audio-device routing (speaker/bluetooth/earpiece).
|
||||
implementation "io.livekit:livekit-android:$livekitVersion"
|
||||
// AudioDevice types used by LiveKit's AudioSwitchHandler; declared so they're on our compile classpath.
|
||||
implementation "com.twilio:audioswitch:$audioswitchVersion"
|
||||
}
|
||||
Reference in new issue
Block a user