Camera
ImagePicker.capture() (see Image picker) opens the system camera
over your app. For a camera inside your own screen - a scanner, a custom shutter - register the
<expo-camera> view and import the Camera directive, which applies to every <expo-camera> in
the template.
import { Camera } from '@ng-native/expo';
<expo-camera> once Camera is in the component's importsInstall
npx expo install expo-cameraimport { Camera } from '@ng-native/expo/camera';The smallest thing that works
import { Component, viewChild } from '@angular/core';
import { Pressable, Text } from '@ng-native/components';
import { Permission, registerExpoViews } from '@ng-native/expo';
import { Camera } from '@ng-native/expo/camera';
import * as ExpoCamera from 'expo-camera';
registerExpoViews('expo-camera'); // once, before the app mounts
@Component({
selector: 'app-shutter',
imports: [Camera, Pressable, Text],
template: `
@if (permission.granted()) {
<expo-camera facing="back" class="flex-1" />
<pressable (press)="shoot()"><text>Take picture</text></pressable>
} @else if (permission.blocked()) {
<text>Enable camera access in Settings to take a picture.</text>
} @else {
<pressable (press)="permission.ensure()"><text>Allow camera access</text></pressable>
}
`,
})
export class Shutter {
private readonly camera = viewChild(Camera);
protected readonly permission = Permission.of(
ExpoCamera.Camera.getCameraPermissionsAsync,
ExpoCamera.Camera.requestCameraPermissionsAsync,
);
protected async shoot(): Promise<void> {
const picture = await this.camera()?.takePicture({ quality: 0.8 });
if (picture) console.log(picture.uri, picture.width, picture.height);
}
}The camera renders only once permission.granted() is true, and shoot() is only reachable from
that branch. permission.blocked() is the state where the platform will not show its own dialog
again - ensure() would resolve to the same refusal without asking - so that branch sends the
user to Settings instead of retrying.
Registering the view
<expo-camera> is not registered by default. Call registerExpoViews('expo-camera') once at
startup, before the first commit that uses the element - it teaches the engine the Fabric
component name for expo-camera's view. expo-camera registers as the module's default view
(the Fabric name is ViewManagerAdapter_ExpoCamera, with no view name suffix), because the camera
is the only view the module renders.
The camera permission
The view needs the camera permission before it shows anything. Nothing in Camera asks for it -
the directive only takes pictures - so ask yourself, with Permission.of() against
expo-camera's own permission functions (see Permissions):
protected readonly permission = Permission.of(
ExpoCamera.Camera.getCameraPermissionsAsync,
ExpoCamera.Camera.requestCameraPermissionsAsync,
);Add to Info.plist:
<key>NSCameraUsageDescription</key>
<string>Allow this app to access your camera</string>
<key>NSMicrophoneUsageDescription</key>
<string>Allow this app to access your microphone</string>The CAMERA (and, for video with audio, RECORD_AUDIO) Android permissions are added
automatically by the module's config plugin.
Taking a picture
takePicture(options) takes expo-camera's own CameraPictureOptions (minus
onPictureSaved and pictureRef, which do not apply here) and resolves to a
CameraCapturedPicture - uri, width, height, and base64 or exif if asked for. It
resolves to null before the view has reached the screen, or without the module.
In React, takePictureAsync is a method on the camera component's ref. Underneath, it is one of
the functions Expo defines on the view itself (AsyncFunction('takePicture') in the native
module), which native finds by reading the tag off whatever it is called on. Camera calls that
same function with the tag the engine committed the view under, so no ref is needed - takePicture
is a method on the directive instance a viewChild reaches.
Reference
expo-cameradirective@ng-native/expoimport { Camera } from '@ng-native/expo';and add Camera to the component's importsMethods
takePicture(options: PictureOptions = {}): Promise<CameraPicture | null>Take a picture. Null without the module, or before the view has reached the screen - there is no camera to take it with yet.