A powerful and easy-to-use Flutter plugin for camera operations on Android. This plugin provides seamless integration for image capture, video recording, and audio recording with automatic permission handling.
🚀 Easy Integration - Simple API with minimal setup required
📸 Image Capture - High-quality image capture with Base64 encoding
🎥 Video Recording - Full video recording capabilities
🎙️ Audio Recording - Audio recording functionality
🔐 Automatic Permissions - Built-in permission handling for camera and microphone
⚡ CameraX Integration - Uses Android's modern CameraX library for optimal performance
🛡️ Error Handling - Comprehensive error handling and user feedback
| Platform | Support |
|---|---|
| Android | ✅ |
| iOS | ❌ (Coming Soon) |
- Flutter SDK:
>=3.3.0 - Dart SDK:
>=3.8.1 - Android: API level 21 (Android 5.0) or higher
Add this to your package's pubspec.yaml file:
dependencies:
camera_service_plugin:
git:
url: https://github.com/De-pitcher/camera_service_plugin.gitOr for local development:
dependencies:
camera_service_plugin:
path: ../path/to/camera_service_pluginThen run:
flutter pub getEnsure your app targets the correct SDK versions:
android {
compileSdkVersion 34
defaultConfig {
minSdkVersion 21
targetSdkVersion 34
}
}Add the following permissions to your android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />Add to your android/app/proguard-rules.pro:
-keep class androidx.camera.** { *; }
-keep class com.rodeni.camera_service_plugin.** { *; }
import 'package:camera_service_plugin/camera_service_plugin.dart';
import 'package:flutter/material.dart';
class CameraExample extends StatefulWidget {
@override
_CameraExampleState createState() => _CameraExampleState();
}
class _CameraExampleState extends State<CameraExample> {
String? _capturedImage;
bool _isLoading = false;
Future<void> _captureImage() async {
setState(() => _isLoading = true);
try {
final String? result = await CameraServicePlugin.captureImage();
if (result != null) {
setState(() => _capturedImage = result);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Image captured successfully!')),
);
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error: $e')),
);
} finally {
setState(() => _isLoading = false);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Camera Service Example')),
body: Column(
children: [
ElevatedButton(
onPressed: _isLoading ? null : _captureImage,
child: _isLoading
? CircularProgressIndicator()
: Text('Capture Image'),
),
if (_capturedImage != null)
Expanded(
child: Image.memory(
base64Decode(_capturedImage!),
fit: BoxFit.contain,
),
),
],
),
);
}
}import 'package:camera_service_plugin/camera_service_plugin.dart';
import 'package:flutter/material.dart';
import 'dart:convert';
class FullCameraExample extends StatefulWidget {
@override
_FullCameraExampleState createState() => _FullCameraExampleState();
}
class _FullCameraExampleState extends State<FullCameraExample> {
String? _lastResult;
bool _isProcessing = false;
Future<void> _performCameraOperation(
Future<String?> Function() operation,
String operationName,
) async {
setState(() => _isProcessing = true);
try {
final result = await operation();
setState(() => _lastResult = result);
if (result != null) {
_showSuccess('$operationName completed successfully!');
} else {
_showError('$operationName failed');
}
} catch (e) {
_showError('$operationName error: $e');
} finally {
setState(() => _isProcessing = false);
}
}
void _showSuccess(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
backgroundColor: Colors.green,
),
);
}
void _showError(String message) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
backgroundColor: Colors.red,
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Camera Service Plugin'),
backgroundColor: Colors.blue,
),
body: Padding(
padding: EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Camera Operations',
style: Theme.of(context).textTheme.headlineSmall,
textAlign: TextAlign.center,
),
SizedBox(height: 20),
_buildOperationButton(
'Capture Image',
Icons.camera_alt,
() => _performCameraOperation(
CameraServicePlugin.captureImage,
'Image capture',
),
),
_buildOperationButton(
'Record Video',
Icons.videocam,
() => _performCameraOperation(
() => CameraServicePlugin.recordVideo(
maxDuration: Duration(seconds: 15),
),
'Video recording',
),
),
_buildOperationButton(
'Record Audio',
Icons.mic,
() => _performCameraOperation(
() => CameraServicePlugin.recordAudio(
maxDuration: Duration(seconds: 30),
),
'Audio recording',
),
),
if (_lastResult != null) ...[
SizedBox(height: 20),
Text(
'Last Result:',
style: Theme.of(context).textTheme.titleMedium,
),
SizedBox(height: 8),
Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.grey[100],
borderRadius: BorderRadius.circular(8),
),
child: Text(
'Data captured (${_lastResult!.length} characters)',
style: TextStyle(fontFamily: 'monospace'),
),
),
],
],
),
),
);
}
Widget _buildOperationButton(
String label,
IconData icon,
VoidCallback onPressed,
) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: ElevatedButton.icon(
onPressed: _isProcessing ? null : onPressed,
icon: _isProcessing
? SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2),
)
: Icon(icon),
label: Text(label),
style: ElevatedButton.styleFrom(
padding: EdgeInsets.all(16),
textStyle: TextStyle(fontSize: 16),
),
),
);
}
}The main class providing camera functionality.
Captures a single image using the device camera.
static Future<String?> captureImage()Returns: Future<String?> - Base64 encoded image data or null if capture fails.
Throws: PlatformException if camera access is denied or operation fails.
Records a video using the device camera.
static Future<String?> recordVideo({Duration? maxDuration})Parameters:
maxDuration(optional): Maximum recording duration. If not provided, defaults to 10 seconds.
Returns: Future<String?> - Base64 encoded video data or null if recording fails.
Throws: PlatformException if camera access is denied or operation fails.
Example:
// Record a 15-second video
final video = await CameraServicePlugin.recordVideo(
maxDuration: Duration(seconds: 15),
);Records audio using the device microphone.
static Future<String?> recordAudio({Duration? maxDuration})Parameters:
maxDuration(optional): Maximum recording duration. If not provided, defaults to 30 seconds.
Returns: Future<String?> - Base64 encoded audio data or null if recording fails.
Throws: PlatformException if microphone access is denied or operation fails.
Example:
// Record a 30-second audio clip
final audio = await CameraServicePlugin.recordAudio(
maxDuration: Duration(seconds: 30),
);The plugin automatically handles permission requests for:
CAMERA- Required for image capture and video recordingRECORD_AUDIO- Required for audio recording and video with audio
No additional permission handling code is required in your Flutter app. The plugin will:
- Check if permissions are granted
- Request permissions if needed
- Show appropriate error messages if permissions are denied
The plugin provides comprehensive error handling:
try {
final result = await CameraServicePlugin.captureImage();
// Handle success
} on PlatformException catch (e) {
switch (e.code) {
case 'PERMISSION_DENIED':
// Handle permission denial
break;
case 'CAMERA_ERROR':
// Handle camera-specific errors
break;
default:
// Handle other errors
break;
}
}- CameraX Library: Uses Android's modern CameraX library for camera operations
- Automatic Lifecycle Management: Handles camera lifecycle automatically
- Performance Optimized: Efficient resource management and background processing
- Base64 Encoding: All media data is returned as Base64 for easy handling
Flutter App
↓
Method Channel
↓
CameraServicePlugin (Kotlin)
↓
CameraService (Java)
↓
CameraX Library
Q: Camera not working on Android
A: Ensure minimum SDK version is 21 and all required permissions are added to AndroidManifest.xml.
Q: App crashes when calling camera methods
A: Check that your app has the necessary permissions and the device has a camera.
Q: Base64 data seems corrupted
A: Ensure you're properly decoding the Base64 string and handling it as binary data.
Q: Build errors with Gradle
A: Make sure your compileSdkVersion is 34 or higher and you have the latest Android build tools.
If you encounter issues:
- Check the example app for reference implementation
- Ensure all setup steps are completed correctly
- Verify that your device/emulator has camera capabilities
- Check the Flutter console for detailed error messages
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.
See CHANGELOG.md for version history and updates.