Files
BizGaze_Remote/mobile/plugins/native-call/android/src/main/AndroidManifest.xml
T
SravanandClaude Opus 4.8 aa4aeeaba1 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>
2026-10-30 17:25:18 +05:30

54 lines
3.2 KiB
XML

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<!-- Full-screen incoming-call UI over the lock screen (Android's answer to CallKit). VIBRATE + WAKE_LOCK
for the ring; POST_NOTIFICATIONS is also added app-side by android-patch.js. -->
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<!-- Increment 2 (native LiveKit call media): a foreground service keeps call audio alive in the background;
the microphone type lets the call keep publishing the mic. RECORD_AUDIO/MODIFY_AUDIO_SETTINGS for capture
+ routing (also added app-side by android-patch.js — merge dedups); BLUETOOTH_CONNECT (API 31+) so the
audio-device switch can route to a Bluetooth headset. -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<application>
<!-- Our FirebaseMessagingService REPLACES the @capacitor/push-notifications one: it handles call-wake
DATA messages natively (to ring when the app is closed) and forwards everything else to Capacitor's
push handling via super.onMessageReceived(). Capacitor's service is removed in the APP manifest
(android-patch.js, highest merge priority) so there is exactly one MESSAGING_EVENT receiver; the high
intent-filter priority here is belt-and-braces so ours wins even if that removal ever no-ops. -->
<service
android:name="com.bizgaze.connect.nativecall.BzCallMessagingService"
android:exported="false">
<intent-filter android:priority="999">
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<!-- The full-screen incoming-call screen. showWhenLocked + turnScreenOn make it appear over the lock
screen and wake the display; excludeFromRecents keeps it out of the recents list. -->
<activity
android:name="com.bizgaze.connect.nativecall.IncomingCallActivity"
android:exported="false"
android:launchMode="singleTop"
android:excludeFromRecents="true"
android:showOnLockScreen="true"
android:showWhenLocked="true"
android:turnScreenOn="true"
android:theme="@android:style/Theme.DeviceDefault.NoActionBar" />
<!-- Keeps the call process alive for background audio (Increment 2). The microphone type is required on
Android 14+ for a service that uses the mic. -->
<service
android:name="com.bizgaze.connect.nativecall.CallForegroundService"
android:exported="false"
android:foregroundServiceType="microphone" />
</application>
</manifest>