Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions app/app/hooks/useAudioStreamer.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// useAudioStreamer.ts
import { useState, useRef, useCallback, useEffect } from 'react';
import { PermissionsAndroid, Platform } from 'react-native';
import { Alert, PermissionsAndroid, Platform } from 'react-native';
import notifee, { AndroidImportance } from '@notifee/react-native';
import NetInfo from '@react-native-community/netinfo';

Expand Down Expand Up @@ -53,10 +53,46 @@ async function ensureNotificationPermission() {
}
}

// On Android 14+ (API 34+), FOREGROUND_SERVICE_MICROPHONE is a separate manifest permission
// with normal protection level (auto-granted at install time), but it does NOT replace RECORD_AUDIO.
// The manifest must declare FOREGROUND_SERVICE_MICROPHONE, and the app must request/obtain
// RECORD_AUDIO as a runtime permission BEFORE starting the foreground service.
// RECORD_AUDIO remains a dangerous permission that must be requested at runtime.
async function ensureForegroundServiceMicPermission() {
if (Platform.OS !== 'android' || Platform.Version < 34) {
return true;
}
try {
const audioGranted = await PermissionsAndroid.check(
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO
);

if (!audioGranted) {
console.log('[AudioStreamer] Requesting RECORD_AUDIO permission...');
const audioResult = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO
);
if (audioResult !== PermissionsAndroid.RESULTS.GRANTED) {
Alert.alert('RECORD_AUDIO permission is required for microphone foreground service. Please grant microphone permission in app settings.');
return false;
}
}

console.log('[AudioStreamer] RECORD_AUDIO permission granted. FOREGROUND_SERVICE_MICROPHONE must be declared in manifest.');
return true;
} catch (error) {
console.error('[AudioStreamer] Error ensuring foreground service mic permission:', error);
return false;
}
}

async function startForegroundServiceNotification(title: string, body: string) {
ensureFgsRegistered();
await ensureNotificationPermission();

const success = await ensureForegroundServiceMicPermission();
if (!success) {
return;
}
// Create channel if needed
await notifee.createChannel({
id: FGS_CHANNEL_ID,
Expand Down
Loading