Skip to content
Closed
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
34 changes: 32 additions & 2 deletions mobile/utils/mediaPermissions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Alert, Linking } from 'react-native';
import { Alert, Linking, AppState, Platform } from 'react-native';
import * as ImagePicker from 'expo-image-picker';
import { Camera } from 'expo-camera';
import i18n from '../i18n/i18n';
Expand Down Expand Up @@ -74,6 +74,28 @@ export const ensurePermission = async ({
}
};

/**
* On Android 12+, the permission dialog dismissal puts the activity into a
* transient pause. Launching the camera immediately after causes Android to
* silently drop the intent. We wait until the activity is fully active again.
*/
const waitForAppActive = (): Promise<void> => {
return new Promise((resolve) => {
if (AppState.currentState === 'active') {
resolve();
return;
}

const sub = AppState.addEventListener('change', (state) => {
if (state === 'active') {
sub.remove();
// Small buffer for the activity window to fully settle
setTimeout(resolve, 100);
}
});
});
};

export const openCameraWithPermission = async (
flow: string,
options: ImagePicker.ImagePickerOptions
Expand All @@ -90,6 +112,12 @@ export const openCameraWithPermission = async (
return null;
}

// Wait for activity to fully resume before launching camera.
// Only needed on Android — iOS handles this natively.
if (Platform.OS === 'android') {
await waitForAppActive();
}

console.warn(`[${flow}] Opening camera picker`);
const result = await ImagePicker.launchCameraAsync(options);
console.warn(
Expand All @@ -111,7 +139,9 @@ export const openLibraryWithPermission = async (
});

if (!hasPermission) {
console.warn(`[${flow}] Media library permission denied, picker will not open`);
console.warn(
`[${flow}] Media library permission denied, picker will not open`
);
return null;
}

Expand Down