RZ Flutter Inspection Camera

A comprehensive Flutter package for capturing high-quality images and videos with location metadata, designed specifically for inspection and documentation workflows.

Features

  • Dual Media Support: Capture both images and videos with unified API
  • Location Integration: Automatic GPS metadata embedding with configurable caching strategies
  • Customizable UI: Fully customizable camera interface and controls
  • Multiple Capture Modes: Single capture, multiple sequential captures, and batch processing
  • Cross-Platform: Support for iOS, Android, and Web platforms
  • Image Processing: Built-in compression, metadata embedding, and EXIF handling
  • Video Processing: Automatic video editing and compression capabilities
  • Permission Handling: Comprehensive location and camera permission management
  • Error Handling: Robust error handling with customizable failure callbacks

Installation

Add the package to your pubspec.yaml:

dependencies:
  inspection_camera: ^0.1.0

Quick Start

Basic Image Capture

import 'package:multimedia_camera/inspection_camera.dart';

final cameraModule = CameraModule(
  navigationHandler: NavigationHandler.defaultNavigator(context),
);

final image = await cameraModule.capture(
  captureConfig: (defaultConfig) => defaultConfig,
);

Basic Video Capture

final video = await cameraModule.capture(
  captureConfig: (defaultConfig) => VideoCaptureConfig(
    maxLength: Duration(minutes: 2),
  ),
);

Usage Guidelines

Core Components

CameraModule

The main entry point for camera operations. Handles navigation, location caching, and capture coordination.

Constructor Parameters:

  • navigationHandler: Controls screen navigation (required)
  • cachedLocationHandler: Manages location data caching (optional)
  • defaultCaptureConfig: Default configuration for captures (optional)

Manages screen transitions during camera operations.

Default Implementation:

NavigationHandler.defaultNavigator(context)

Custom Implementation:

NavigationHandler(
  openScreen: (child) => Navigator.push(context, MaterialPageRoute(builder: (context) => child)),
  closeScreen: Navigator.pop,
)

Capture Configurations

ImageCaptureConfig

Configuration for image capture operations.

Parameters:

  • defaultCameraLensDirection: Initial camera lens (back/front/external)
  • allowCameraSwitching: Enable camera switching during capture
  • allowFlashSetting: Enable flash control
  • cameraOrientation: Preferred camera orientation
  • resolutionPreset: Image resolution quality
  • embedImageMetadata: Embed location and timestamp metadata
  • shouldCompress: Enable automatic image compression
  • captureWidgetBuilders: Custom UI component builders
  • cameraModuleCallbacks: Event callbacks
  • uniqueIdNumber: Unique identifier for the capture

Example:

ImageCaptureConfig(
  defaultCameraLensDirection: CameraLensDirection.back,
  resolutionPreset: ResolutionPreset.veryHigh,
  embedImageMetadata: true,
  shouldCompress: false,
  allowCameraSwitching: true,
  allowFlashSetting: true,
)

VideoCaptureConfig

Configuration for video capture operations.

Additional Parameters:

  • maxLength: Maximum video duration
  • shouldCompress: Enable video compression

Example:

VideoCaptureConfig(
  maxLength: Duration(minutes: 5),
  resolutionPreset: ResolutionPreset.high,
  shouldCompress: true,
)

Location Handling

CachedLocationHandler

Manages location data caching and permission handling.

LocationCachingStrategy Options:

  • compulsory: Location permission required, throws error if denied
  • optional: Location permission optional, continues without location if denied
  • disabled: Location functionality completely disabled

Example:

CachedLocationHandler(
  locationCachingStrategy: LocationCachingStrategy.optional,
)

Custom UI Components

CaptureWidgetBuilders

Provides custom builders for all UI components in the camera interface.

Available Builders:

  • overlayBuilder(BuildContext context, Orientation orientation): Custom overlay on camera preview
    • Parameters: BuildContext context, Orientation orientation
  • flashIconBuilder(BuildContext context, FlashMode flashMode): Custom flash control icon
    • Parameters: BuildContext context, FlashMode flashMode
  • cameraSwitchIconBuilder(BuildContext context): Custom camera switch icon
    • Parameters: BuildContext context
  • acceptIconBuilder(BuildContext context): Custom accept button icon
    • Parameters: BuildContext context
  • retakeIconBuilder(BuildContext context): Custom retake button icon
    • Parameters: BuildContext context
  • shutterIconBuilder(BuildContext context): Custom shutter button
    • Parameters: BuildContext context
  • screenOrientationBuilder(BuildContext context, Orientation orientation): Custom orientation indicator
    • Parameters: BuildContext context, Orientation orientation
  • videoCaptureIconBuilder(BuildContext context, {required bool isVideoCapturing}): Custom video capture button
    • Parameters: BuildContext context, {required bool isVideoCapturing}
  • videoOverlayBuilder(BuildContext context, Timer? timer): Custom video recording overlay
    • Parameters: BuildContext context, Timer? timer
  • mediaPreviewBuilder(BuildContext context, Widget mediaWidget): Custom media preview widget
    • Parameters: BuildContext context, Widget mediaWidget

Example:

CaptureWidgetBuilders(
  overlayBuilder: (context, orientation) => 
    Positioned(
      top: 20,
      left: 20,
      child: Text('Camera Overlay', style: TextStyle(color: Colors.white)),
    ),
  flashIconBuilder: (context, flashMode) => 
    Icon(
      flashMode == FlashMode.on ? Icons.flash_on : Icons.flash_off,
      color: Colors.white,
    ),
  shutterIconBuilder: (context) => 
    Container(
      width: 80,
      height: 80,
      decoration: BoxDecoration(
        shape: BoxShape.circle,
        color: Colors.white,
      ),
      child: Icon(Icons.camera, color: Colors.black),
    ),
  acceptIconBuilder: (context) => 
    Icon(Icons.check, color: Colors.green, size: 30),
  retakeIconBuilder: (context) => 
    Icon(Icons.refresh, color: Colors.red, size: 30),
  videoCaptureIconBuilder: (context, {required bool isVideoCapturing}) => 
    Icon(
      isVideoCapturing ? Icons.stop : Icons.videocam,
      color: isVideoCapturing ? Colors.red : Colors.white,
    ),
  videoOverlayBuilder: (context, timer) => 
    Positioned(
      top: 50,
      right: 20,
      child: Text(
        'Recording...',
        style: TextStyle(color: Colors.red, fontSize: 16),
      ),
    ),
  mediaPreviewBuilder: (context, mediaWidget) => 
    Container(
      decoration: BoxDecoration(border: Border.all(color: Colors.white)),
      child: mediaWidget,
    ),
)

Event Callbacks

CameraModuleCallbacks

Handles various camera events and user interactions.

Available Callbacks:

  • onCameraLoaded(): Camera initialization complete
  • onRotationPrompt(Orientation currentOrientation): Device orientation change
    • Parameters: Orientation currentOrientation
  • onFlashToggle(FlashMode flashMode): Flash mode changed
    • Parameters: FlashMode flashMode
  • onCapture(): Media captured
  • onPreviewLoad(): Preview loaded
  • onPreviewAccepted(): Preview accepted by user
  • onPreviewRejected(): Preview rejected by user
  • onRetakeClick(): Retake button pressed
    • Returns: Future<bool>
  • onCameraChange(CameraDescription camera): Camera lens changed
    • Parameters: CameraDescription camera

Video-Specific Callbacks:

  • videoProcessingTime(Duration duration): Video processing duration
    • Parameters: Duration duration
  • onVideoCompress(int originalFileSize, int newFileSize): Video compression progress
    • Parameters: int originalFileSize, int newFileSize
  • onTimerExpired(): Video recording timer expired
    • Returns: Future<bool>

Multiple Capture Callbacks:

  • onCaptureFailure(int failureAtIndex, MediaCaptureConfig captureConfig, ({Object? exception, StackTrace? stackTrace}) exceptionInfo): Called when a capture fails during multiple capture sequence
    • Parameters: int failureAtIndex, MediaCaptureConfig captureConfig, ({Object? exception, StackTrace? stackTrace}) exceptionInfo
    • Returns: bool (return true to continue, false to exit the capture flow)

Example:

ImageCaptureCallbacks(
  onCameraLoaded: () => print('Camera ready'),
  onRotationPrompt: (orientation) => print('Orientation: $orientation'),
  onFlashToggle: (flashMode) => print('Flash mode: $flashMode'),
  onCapture: () => print('Image captured'),
  onPreviewAccepted: () => print('Image accepted'),
  onRetakeClick: () async {
    // Show confirmation dialog
    return await showDialog(...);
  },
  onCameraChange: (camera) => print('Camera changed to: ${camera.name}'),
)

Advanced Usage

Multiple Sequential Captures

Capture multiple images or videos in sequence with different configurations.

await cameraModule.captureMultiple(
  captureConfigs: (defaultConfig) {
    return [
      defaultConfig.copyWith(
        defaultCameraLensDirection: CameraLensDirection.back,
      ),
      defaultConfig.copyWith(
        defaultCameraLensDirection: CameraLensDirection.front,
      ),
    ];
  },
  onPictureTaken: (index, config, data) {
    print('Captured item $index');
  },
  onCaptureFailure: (index, config, exception) {
    print('Failed at index $index: ${exception.exception}');
    return true; // Continue with next capture
  },
  captureFlowHandler: (index, config) async {
    // Custom flow control logic
    return index < 5; // Stop after 5 captures
  },
);

Custom Navigation

Implement custom navigation patterns for your app.

class CustomNavigationHandler extends NavigationHandler {
  CustomNavigationHandler({
    required super.openScreen,
    required super.closeScreen,
  });

  factory CustomNavigationHandler.modal(BuildContext context) {
    return CustomNavigationHandler(
      openScreen: (child) => showModalBottomSheet(
        context: context,
        isScrollControlled: true,
        builder: (context) => child,
      ),
      closeScreen: Navigator.pop,
    );
  }
}

Resolution Presets

Available resolution presets for different quality requirements:

  • ResolutionPreset.low: 240p
  • ResolutionPreset.medium: 480p
  • ResolutionPreset.high: 720p
  • ResolutionPreset.veryHigh: 1080p
  • ResolutionPreset.ultraHigh: 2160p
  • ResolutionPreset.max: Maximum available resolution

Camera Lens Directions

Supported camera lens directions:

  • CameraLensDirection.back: Rear camera
  • CameraLensDirection.front: Front camera
  • CameraLensDirection.external: External camera (if available)

Error Handling

The package provides comprehensive error handling with customizable failure callbacks:

try {
  final media = await cameraModule.capture();
} catch (e) {
  if (e is LocationCacheHandlerException) {
    // Handle location permission errors
  } else if (e is CameraException) {
    // Handle camera-specific errors
  }
}

Platform-Specific Considerations

iOS

  • Requires camera and location permissions in Info.plist
  • Location services must be enabled for GPS metadata

Android

  • Requires camera and location permissions in AndroidManifest.xml
  • Location services must be enabled for GPS metadata

Web

  • Uses browser's camera API
  • Location requires HTTPS and user permission
  • File handling uses Blob URLs for memory efficiency

Dependencies

The package includes the following key dependencies:

  • camera: Core camera functionality
  • geolocator: Location services
  • flutter_image_compress: Image compression
  • video_compress: Video compression
  • path_provider: File system access
  • permission_handler: Permission management

License

This project is licensed under the terms specified in the LICENSE file.

Contributing

Contributions are welcome. Please ensure all code follows the project's coding standards and includes appropriate tests.