[fix](client): scan QR codes with MLKit's barcode output, not the iOS-only object output
Tapping "Scan a QR code" crashed the app on Android:
com.facebook.react.common.JavascriptException: Error:
CameraFactory.createObjectOutput(...): java.lang.Error:
CameraObjectOutput is not available on Android!
`useObjectOutput` is Apple Vision only — the comment claiming v5 ships a
cross-platform code scanner in core was wrong, and the native factory throws as
soon as the screen mounts. The Barcode Scanner output is the cross-platform one
(MLKit on Android, Vision on iOS); it is attached to the same `<Camera>` via
`outputs`, scans `qr-code` only, and keeps the hand-paste fallback. The scan
callback now takes the barcode values directly instead of the object-output
shape.
This commit is contained in:
@@ -14,8 +14,8 @@ import {
|
||||
Camera,
|
||||
useCameraDevice,
|
||||
useCameraPermission,
|
||||
useObjectOutput,
|
||||
} from 'react-native-vision-camera';
|
||||
import { useBarcodeScannerOutput } from 'react-native-vision-camera-barcode-scanner';
|
||||
import { ScanLine, X } from 'lucide-react-native';
|
||||
import { AppText, Button, ErrorBanner, Field, Header, TextInputBox } from '../components/ui';
|
||||
import { useAlarm } from '../state/AlarmContext';
|
||||
@@ -158,32 +158,42 @@ export default function ScannerScreen() {
|
||||
[busy, joinAlert, navigation, perms],
|
||||
);
|
||||
|
||||
const onScanned = useCallback(
|
||||
(objects: readonly { type: string; value?: string }[]) => {
|
||||
for (const obj of objects) {
|
||||
const value = typeof obj.value === 'string' ? obj.value : undefined;
|
||||
if (obj.type !== 'qr' || !value) continue;
|
||||
const parsed = parseQrPayload(value);
|
||||
if (parsed.ok) {
|
||||
if (targetAlertId && parsed.payload.alertId !== targetAlertId) {
|
||||
setError('That code is for a different alert.');
|
||||
continue;
|
||||
}
|
||||
complete(parsed.payload.alertId, parsed.payload.subscribeToken);
|
||||
} else {
|
||||
setError(qrErrorMessage(parsed.error));
|
||||
// Both platforms scan through MLKit here. The core library's
|
||||
// `useObjectOutput` is Apple-Vision only: on Android its native factory
|
||||
// throws `CameraObjectOutput is not available on Android!` the moment the
|
||||
// screen mounts, which crashed the app on "Scan a QR code". The Barcode
|
||||
// Scanner output is cross-platform (MLKit on Android, Vision on iOS).
|
||||
const handleScanValue = useCallback(
|
||||
(value: string) => {
|
||||
const parsed = parseQrPayload(value);
|
||||
if (parsed.ok) {
|
||||
if (targetAlertId && parsed.payload.alertId !== targetAlertId) {
|
||||
setError('That code is for a different alert.');
|
||||
return;
|
||||
}
|
||||
return;
|
||||
complete(parsed.payload.alertId, parsed.payload.subscribeToken);
|
||||
} else {
|
||||
setError(qrErrorMessage(parsed.error));
|
||||
}
|
||||
},
|
||||
[complete, targetAlertId],
|
||||
);
|
||||
|
||||
// v5 ships the scanner in core: `useObjectOutput` is the code-scanner — there
|
||||
// is no separate vision-camera-code-scanner plugin for 5.x.
|
||||
const objectOutput = useObjectOutput({
|
||||
types: ['qr'],
|
||||
onObjectsScanned: onScanned,
|
||||
const barcodeOutput = useBarcodeScannerOutput({
|
||||
barcodeFormats: ['qr-code'],
|
||||
onBarcodeScanned(barcodes) {
|
||||
for (const barcode of barcodes) {
|
||||
const value = barcode.rawValue;
|
||||
if (typeof value === 'string' && value.length > 0) {
|
||||
handleScanValue(value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
},
|
||||
onError(error) {
|
||||
setError('The camera could not start scanning. You can paste the code by hand.');
|
||||
console.log('barcode scanner error', error.message);
|
||||
},
|
||||
});
|
||||
|
||||
const submitManual = async () => {
|
||||
@@ -236,7 +246,7 @@ export default function ScannerScreen() {
|
||||
style={StyleSheet.absoluteFill}
|
||||
device={device}
|
||||
isActive={!joinedName}
|
||||
outputs={[objectOutput]}
|
||||
outputs={[barcodeOutput]}
|
||||
/>
|
||||
) : (
|
||||
<View style={styles.permission}>
|
||||
|
||||
Reference in New Issue
Block a user