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)
NavigationHandler
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 captureallowFlashSetting: Enable flash controlcameraOrientation: Preferred camera orientationresolutionPreset: Image resolution qualityembedImageMetadata: Embed location and timestamp metadatashouldCompress: Enable automatic image compressioncaptureWidgetBuilders: Custom UI component builderscameraModuleCallbacks: Event callbacksuniqueIdNumber: 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 durationshouldCompress: 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 deniedoptional: Location permission optional, continues without location if denieddisabled: 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
- Parameters:
flashIconBuilder(BuildContext context, FlashMode flashMode): Custom flash control icon- Parameters:
BuildContext context,FlashMode flashMode
- Parameters:
cameraSwitchIconBuilder(BuildContext context): Custom camera switch icon- Parameters:
BuildContext context
- Parameters:
acceptIconBuilder(BuildContext context): Custom accept button icon- Parameters:
BuildContext context
- Parameters:
retakeIconBuilder(BuildContext context): Custom retake button icon- Parameters:
BuildContext context
- Parameters:
shutterIconBuilder(BuildContext context): Custom shutter button- Parameters:
BuildContext context
- Parameters:
screenOrientationBuilder(BuildContext context, Orientation orientation): Custom orientation indicator- Parameters:
BuildContext context,Orientation orientation
- Parameters:
videoCaptureIconBuilder(BuildContext context, {required bool isVideoCapturing}): Custom video capture button- Parameters:
BuildContext context,{required bool isVideoCapturing}
- Parameters:
videoOverlayBuilder(BuildContext context, Timer? timer): Custom video recording overlay- Parameters:
BuildContext context,Timer? timer
- Parameters:
mediaPreviewBuilder(BuildContext context, Widget mediaWidget): Custom media preview widget- Parameters:
BuildContext context,Widget mediaWidget
- Parameters:
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 completeonRotationPrompt(Orientation currentOrientation): Device orientation change- Parameters:
Orientation currentOrientation
- Parameters:
onFlashToggle(FlashMode flashMode): Flash mode changed- Parameters:
FlashMode flashMode
- Parameters:
onCapture(): Media capturedonPreviewLoad(): Preview loadedonPreviewAccepted(): Preview accepted by useronPreviewRejected(): Preview rejected by useronRetakeClick(): Retake button pressed- Returns:
Future<bool>
- Returns:
onCameraChange(CameraDescription camera): Camera lens changed- Parameters:
CameraDescription camera
- Parameters:
Video-Specific Callbacks:
videoProcessingTime(Duration duration): Video processing duration- Parameters:
Duration duration
- Parameters:
onVideoCompress(int originalFileSize, int newFileSize): Video compression progress- Parameters:
int originalFileSize,int newFileSize
- Parameters:
onTimerExpired(): Video recording timer expired- Returns:
Future<bool>
- Returns:
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(returntrueto continue,falseto exit the capture flow)
- Parameters:
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: 240pResolutionPreset.medium: 480pResolutionPreset.high: 720pResolutionPreset.veryHigh: 1080pResolutionPreset.ultraHigh: 2160pResolutionPreset.max: Maximum available resolution
Camera Lens Directions
Supported camera lens directions:
CameraLensDirection.back: Rear cameraCameraLensDirection.front: Front cameraCameraLensDirection.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 functionalitygeolocator: Location servicesflutter_image_compress: Image compressionvideo_compress: Video compressionpath_provider: File system accesspermission_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.