Using Ionic Capacitor Camera for Cross‑Platform Photo Capture in Angular Apps
Learn how to add the Capacitor Camera plugin to an Ionic Angular project, configure native permissions, call the API, and display the image with a PWA fallback.
28 Aug 2026, 11:57 UTC

Problem: needing a reliable way to take a photo and show it in an Ionic Angular app
When building a mobile‑first Ionic app you often need to let users snap a picture with the device camera and display the result immediately. Writing separate code for iOS, Android, and the browser leads to duplication and makes maintenance harder.
Thesis: the Capacitor Camera plugin gives a single promise‑based API that works on native platforms and falls back to the browser’s file picker when running as a PWA
1. Install the plugin and sync native projects
Run the following commands in the root of your Ionic Angular workspace:
# Install the plugin
npm install @capacitor/camera
# Sync the native projects (Android, iOS)
npx cap sync
If you haven’t added the native platforms yet, do so first:
npx cap add android
npx cap add ios
After installing, verify that the plugin appears in your dependency list:
npm list @capacitor/camera
2. Declare platform‑specific permissions
Android – open android/app/src/main/AndroidManifest.xml and add:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
iOS – open ios/App/Info.plist and add the key:
<key>NSCameraUsageDescription</key>
<string>We need camera access to let you take a photo for your profile.</string>
These entries are required; without them the native camera will not launch.
3. Basic usage pattern in an Angular service
Create a service that encapsulates the call to Camera.getPhoto. The example below requests a JPEG, sets a reasonable quality, and returns the image as a base64 string (useful for direct binding).
import { Injectable } from '@angular/core';
import { Camera, CameraResultType, CameraSource } from '@capacitor/camera';
@Injectable({
providedIn: 'root'
})
export class PhotoService {
async takePicture(): Promise<string> {
const image = await Camera.getPhoto({
quality: 90,
allowEditing: true,
resultType: CameraResultType.Base64, // returns base64 string
source: CameraSource.Camera, // force camera, not gallery
});
// image.base64 contains the JPEG data
return `data:image/jpeg;base64,${image.base64}`;
}
}
In a component template you can bind the returned string directly to an <img> element:
<ion-button (click)="capture()">Take Photo</ion-button>
<img [src]="photoUrl" *ngIf="photoUrl" />
And the component code:
import { Component } from '@angular/core';
import { PhotoService } from '../services/photo.service';
@Component({
selector: 'app-photo',
templateUrl: './photo.page.html',
styleUrls: ['./photo.page.scss']
})
export class PhotoPage {
photoUrl: string | null = null;
constructor(private photoSvc: PhotoService) {}
async capture() {
try {
this.photoUrl = await this.photoSvc.takePicture();
} catch (err) {
console.error('Unable to take photo', err);
}
}
}
4. Verifying the implementation
- Native build: run
npx cap run android --livereload(or iOS) on a physical device or emulator. Tap the button; you should see the native camera UI, take a picture, and the image appear instantly. - PWA fallback: serve the web version with
ionic serve. Clicking the button opens the browser’s<input type=file>picker limited to camera capture. Selecting an image displays it the same way. - Check plugin version:
npm list @capacitor/camerashould show the installed version without errors. - Sync sanity: after any plugin version change, run
npx cap syncand rebuild the native projects; the sync command should exit with code 0.
Trade‑offs and limitations
While the plugin unifies the API, there are practical considerations:
- Web limitations: the PWA path relies on the browser’s
input[type=file]camera capture, which may not expose flash, focus, or manual exposure controls. It also requires the page to be served over HTTPS (or localhost) for the camera to be available. - Binary size: adding @capacitor/camera increases the native app size by a few megabytes due to the underlying camera libraries. This can affect download times and CI build durations.
- Rebuild requirement: any change to the plugin version necessitates a
npx cap syncand a rebuild of the native projects; hot‑reloading does not propagate native code changes.
To check whether the web fallback is functioning correctly, open Chrome DevTools, toggle the device toolbar, and verify that clicking the button opens a file picker with the “camera” option enabled. If the picker does not appear, ensure the app is served over HTTPS and that the browser permissions allow camera access.
Actionable closing
Start by installing @capacitor/camera, configuring the two permission files, and adding the service method shown above. Test on a real device to confirm the native UI, then run ionic serve to verify the PWA fallback. If you encounter permission‑related failures, double‑check the manifest and Info.plist entries and rebuild the native projects. With these steps you’ll have a reliable, cross‑platform photo capture feature that works uniformly across Ionic’s supported targets.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.