Microphone, camera, and notification permissions for Alaznah Calling.
Permissions
Two layers:
- Native config —
Info.plist/AndroidManifest.xml(required before the OS will prompt) - Runtime —
requestCallPermissionsbefore the first call
Rebuild the native app after changing plist or manifest.
Which permissions do you need?
| App offers | Native mic | Native camera | Runtime call |
|---|---|---|---|
| Voice only | Yes | No | requestCallPermissions('audio') |
| Video only | Yes | Yes | requestCallPermissions('video') |
| Voice and video | Yes | Yes | 'audio' or 'video' for the upcoming call (or 'video' at startup for mic + camera) |
Runtime (JavaScript)
import { requestCallPermissions } from '@alaznah/calling';
// for audio call
const audio = await requestCallPermissions('audio');
if (!audio.microphone) {
// show UI — mic denied
}
// for video call (mic + camera)
const video = await requestCallPermissions('video');
if (!video.microphone || !video.camera) {
// show UI — denied
}'audio' | 'video'. Returns { microphone, camera, bluetooth }.
On iOS, system prompts often appear on first getUserMedia; plist strings must still be present or the app can crash.
iOS — Info.plist
Add usage descriptions (edit ios/<AppName>/Info.plist or Xcode → Info):
<key>NSMicrophoneUsageDescription</key>
<string>Microphone access is required for audio and video calls.</string>
<!-- Required if your app places or accepts video calls -->
<key>NSCameraUsageDescription</key>
<string>Camera access is required for video calls.</string>Background modes (calling)
Xcode → Signing & Capabilities → Background Modes, enable at least:
- Audio, AirPlay, and Picture in Picture (
audio) — keep call audio in background - Voice over IP (
voip) — VoIP / PushKit wake
Or in plist:
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
<string>voip</string>
<string>remote-notification</string>
</array>Also enable Push Notifications capability. CallKit / PushKit setup: Background Calling.
Voice-only vs video (iOS)
| Key / capability | Voice only | Video / both |
|---|---|---|
NSMicrophoneUsageDescription | Required | Required |
NSCameraUsageDescription | Optional | Required |
| Background Modes → Audio | Recommended | Recommended |
| Background Modes → VoIP | For kill/background ring | For kill/background ring |
Android — AndroidManifest.xml
In android/app/src/main/AndroidManifest.xml, inside <manifest> (before <application>):
Minimum (voice)
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />Add for video (or voice + video app)
<uses-permission android:name="android.permission.CAMERA" />Recommended for notifications, Bluetooth, incoming UI
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />@alaznah/calling already declares several of these in its library manifest; merging usually picks them up. If a permission is missing after install, add it explicitly in the app manifest as above.
Voice-only vs video (Android)
| Permission | Voice only | Video / both |
|---|---|---|
INTERNET | Required | Required |
RECORD_AUDIO | Required | Required |
CAMERA | — | Required |
MODIFY_AUDIO_SETTINGS | Recommended | Recommended |
POST_NOTIFICATIONS | API 33+ notify | API 33+ notify |
BLUETOOTH_CONNECT | Headsets | Headsets |
| Full-screen / FGS | Native incoming + keep-alive | Native incoming + keep-alive + PiP |
What the SDK adds automatically (no host Kotlin/Java)
After npm install @alaznah/calling, the library manifest merges into your app:
| Merged by SDK | Purpose |
|---|---|
IncomingCallActivity, foreground services, action receiver | Native incoming UI + call keep-alive |
CallMessagingReceiver + removes default RN Firebase messaging receiver | Kill-state call invite/cancel before flaky headless JS (requires @react-native-firebase/messaging for non-call FCM) |
android:supportsPictureInPicture on ${applicationId}.MainActivity | Android video PiP on Home |
AlaznahPipActivity | Android Minimize-button system PiP |
You do not add CallMessagingReceiver, PiP manifest flags, or MainActivity onUserLeaveHint overrides for a standard React Native app whose launcher Activity is named MainActivity. Full list: Native Modules.
Custom launcher Activity name? If your main Activity is not <applicationId>.MainActivity, add PiP support manually:
<activity
android:name=".YourMainActivity"
android:supportsPictureInPicture="true"
android:resizeableActivity="true" />Push: Wire FCM in Firebase + Background Calling. The SDK receiver handles Alaznah call payloads; other FCM messages still flow to React Native Firebase when that package is installed.
iOS — Picture-in-Picture (video calls)
Dedicated guide: Picture in Picture. Host setup (plist, patch, rebuild): Native Modules.
No host AppDelegate / Swift PiP code. @alaznah/calling ships:
| SDK native (automatic) | Purpose |
|---|---|
AlaznahCallingBootstrap (+load) | CallKit + PushKit, WebRTC multitasking camera, CallKit ↔ WebRTC audio bridge |
AlaznahCallingPip module | Reports PiP support to JS |
enableBackgroundCamera / reportCallConnected | Camera + CallKit session for PiP mute/end chrome |
ActiveCallScreen + react-native-webrtc iosPIP | AVKit PiP on the remote video view when the app backgrounds |
Host Info.plist only (see iOS — Info.plist above):
NSCameraUsageDescription+NSMicrophoneUsageDescription- Background Modes → Audio (
audioinUIBackgroundModes) — required for video PiP while backgrounded - VoIP (
voip) — kill/background incoming via PushKit (not PiP itself, but same calling stack)
Expo: the @alaznah/calling config plugin injects audio, voip, and remote-notification background modes.
Simulator: iOS Simulator does not support AVKit Picture-in-Picture. AlaznahCallingPip.isSupported() returns false on simulator — this is expected. Test PiP on a physical iPhone (iOS 15+). In-app minimize bubble still works on simulator.
Custom PiP: Do not add your own AVPictureInPictureController in the host app — the SDK + react-native-webrtc own the video PiP path.
Expo
Expo Go is not supported. Use a development build with the @alaznah/calling config plugin — Installation. Still verify the generated plist / manifest after prebuild.
Checklist
- Add Info.plist / AndroidManifest entries for the features you ship
- Rebuild the native app (Metro reload is not enough)
- Call
requestCallPermissions('audio')orrequestCallPermissions('video')before the first call - Re-check after the user revokes permission in system Settings