tauri-plugin-native-camera

Crates.iotauri-plugin-native-camera
lib.rstauri-plugin-native-camera
version0.1.0
created_at2026-01-16 08:30:13.716745+00
updated_at2026-01-16 08:30:13.716745+00
descriptionA Tauri plugin to capture photos using the device's native camera app
homepage
repositoryhttps://github.com/kushaldas/tauri-plugin-native-camera
max_upload_size
id2048168
size218,366
Kushal Das (kushaldas)

documentation

https://docs.rs/tauri-plugin-native-camera

README

Tauri Plugin Native Camera

A Tauri plugin that captures photos using the device's native camera application.

Crates.io Documentation MIT License

Overview

This plugin uses Android's ACTION_IMAGE_CAPTURE intent to open the system camera app (Samsung Camera, Google Camera, Pixel Camera, etc.) rather than implementing a custom camera UI. This ensures:

  • Familiar UX: Users interact with their device's native camera app
  • Universal compatibility: Works on all Android devices
  • Proper safe area handling: No UI elements cut off by notches or navigation bars
  • Maintained by device manufacturers: Camera features and quality optimizations

Features

  • 📷 Opens the device's native camera application
  • 🖼️ Returns captured photos as base64-encoded JPEG data
  • 🔒 Handles camera permissions automatically
  • 📐 Automatic EXIF rotation correction
  • 📏 Automatic image resizing for large photos (max 2048px)
  • ✨ Works on all Android devices

Platform Support

Platform Supported
Android
iOS ❌ (planned)
Desktop

Installation

Rust

Add the plugin to your Cargo.toml:

[dependencies]
tauri-plugin-native-camera = "0.1"

Or for Android-only (recommended to avoid compilation issues on other platforms):

[target.'cfg(target_os = "android")'.dependencies]
tauri-plugin-native-camera = "0.1"

JavaScript/TypeScript

Install the JavaScript bindings:

npm install tauri-plugin-native-camera-api
# or
pnpm add tauri-plugin-native-camera-api
# or
yarn add tauri-plugin-native-camera-api

Setup

1. Register the plugin in your Tauri app

In your src-tauri/src/lib.rs:

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        // Register the plugin (Android-only)
        #[cfg(target_os = "android")]
        .plugin(tauri_plugin_native_camera::init())
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

2. Add capabilities

Create or update src-tauri/capabilities/android.json:

{
  "identifier": "android-capability",
  "platforms": ["android"],
  "windows": ["main"],
  "permissions": [
    "native-camera:allow-take-picture"
  ]
}

3. Ensure camera permission is in AndroidManifest

The plugin's manifest merger should add this automatically, but if needed, add to your src-tauri/gen/android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.CAMERA" />

Usage

TypeScript/JavaScript

import { takePicture } from 'tauri-plugin-native-camera-api';

async function capturePhoto() {
  try {
    const result = await takePicture();

    console.log('Photo captured!');
    console.log('Dimensions:', result.width, 'x', result.height);

    // Use the base64 image data
    const imgElement = document.getElementById('preview') as HTMLImageElement;
    imgElement.src = `data:image/jpeg;base64,${result.imageData}`;

  } catch (error) {
    if (error === 'Camera operation was cancelled by user') {
      console.log('User cancelled');
    } else {
      console.error('Camera error:', error);
    }
  }
}

Rust (Direct API)

use tauri_plugin_native_camera::NativeCameraExt;

#[tauri::command]
async fn take_photo(app: tauri::AppHandle) -> Result<String, String> {
    let result = app.native_camera().take_picture()
        .map_err(|e| e.to_string())?;

    Ok(result.image_data)
}

API Reference

takePicture()

Opens the device's native camera app and captures a photo.

Returns: Promise<CaptureResult>

interface CaptureResult {
  /** Base64-encoded JPEG image data */
  imageData: string;
  /** Width of the captured image in pixels */
  width: number;
  /** Height of the captured image in pixels */
  height: number;
}

Throws: Error with one of the following messages:

  • "Camera operation was cancelled by user" - User pressed back or cancelled
  • "Camera permission denied" - User denied camera permission
  • "No camera available on this device" - Device has no camera
  • "Failed to read captured photo: ..." - Error processing the image

How It Works

  1. Permission Check: The plugin first checks if camera permission is granted. If not, it requests permission from the user.

  2. Create Temp File: A temporary file is created in the app's cache directory to store the captured photo.

  3. Launch Camera Intent: The plugin creates an ACTION_IMAGE_CAPTURE intent with the temp file URI and launches the system camera app.

  4. Handle Result: When the user takes a photo and confirms, the plugin:

    • Reads the photo from the temp file
    • Applies EXIF rotation correction (handles portrait/landscape)
    • Resizes large images (max 2048px dimension)
    • Converts to base64-encoded JPEG
    • Cleans up the temp file
    • Returns the result to JavaScript

Comparison with Custom Camera UI Plugins

Feature Native Camera (this plugin) Custom Camera UI
UI Familiarity ✅ Users' own camera app ❌ Learning curve
Safe Area Handling ✅ Handled by system ⚠️ May have issues
Device Compatibility ✅ Universal ⚠️ May vary
Camera Features ✅ Full device features ❌ Limited
Code Complexity ✅ Simple (~200 lines) ❌ Complex (~1000+ lines)
Maintenance ✅ Minimal ❌ Ongoing

Troubleshooting

Camera permission denied

Ensure your app has the camera permission in the manifest and that the user has granted it. The plugin automatically requests permission if not granted.

Photo not returned

Make sure the FileProvider is correctly configured. Check logcat for errors:

adb logcat | grep -i NativeCameraPlugin

App crashes on photo capture

This is usually due to the photo file not being accessible. Ensure the FileProvider paths are correctly configured in the manifest.

Android 11+ Package Visibility

Starting with Android 11 (API level 30), apps need to declare which other apps they intend to interact with. This plugin automatically includes the necessary <queries> declaration in its manifest:

<queries>
    <intent>
        <action android:name="android.media.action.IMAGE_CAPTURE" />
    </intent>
</queries>

This allows the plugin to discover and launch camera apps on Android 11+. The manifest merger should include this automatically when you add the plugin dependency.

If you're experiencing issues with the camera not launching on Android 11+ devices, verify that the queries element is present in your merged manifest by checking:

# View merged manifest
cat src-tauri/gen/android/app/build/intermediates/merged_manifest/*/AndroidManifest.xml | grep -A3 "queries"

FileProvider Configuration

This plugin uses the host app's existing FileProvider (with authority ${applicationId}.fileprovider) to share the photo file URI with the camera app. Your app must have a FileProvider configured with cache-path access.

The default Tauri Android template includes this configuration. If you have a custom setup, ensure your file_paths.xml includes:

<cache-path name="my_cache_images" path="." />

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - see LICENSE for details.

Author

Kushal Das mail@kushaldas.in

Acknowledgments

Commit count: 0

cargo fmt