Reputation: 33
I opted to use Flutter MethodChannel to access the phone camera since the Flutter camera plugin seems to be limited for our use case.
Consider the code snippets below:
Flutter/Dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:permission_handler/permission_handler.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Native Camera Test',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'Native Camera Test'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
static const platform = MethodChannel('samples.flutter.dev/camera');
Future<void> openCamera() async {
// Check and request camera permission
bool isCameraGranted = await _requestPermission(Permission.camera);
if (isCameraGranted) {
try {
final String imagePath = await platform.invokeMethod('openCamera');
print('Image Path: $imagePath');
} on PlatformException catch (e) {
print("Failed to open camera: '${e.message}'.");
}
} else {
print('Permission denied');
}
}
Future<bool> _requestPermission(Permission permission) async {
// Check if the permission is already granted
if (await permission.isGranted) {
return true;
}
// Request permission if not already granted
var status = await permission.request();
return status == PermissionStatus.granted;
}
Future<void> imagePath(String imagePath) async {
print("Hit from Kotlin");
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
Native/Kotlin
package com.example.nativecameratest
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.os.Environment
import android.provider.MediaStore
import android.util.Log
import androidx.core.content.FileProvider
import io.flutter.embedding.android.FlutterActivity
import io.flutter.plugin.common.MethodChannel
import java.io.File
import java.io.IOException
import java.util.*
import io.flutter.embedding.engine.FlutterEngine
import androidx.annotation.NonNull
class MainActivity: FlutterActivity(){
private val CHANNEL = "samples.flutter.dev/camera"
private val REQUEST_IMAGE_CAPTURE = 1
private lateinit var currentPhotoPath: String
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Set up the method channel on the binaryMessenger
MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
if (call.method == "openCamera") {
dispatchTakePictureIntent(result)
} else {
result.notImplemented()
}
}
}
private fun dispatchTakePictureIntent(result: MethodChannel.Result) {
val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
if (takePictureIntent.resolveActivity(packageManager) != null) {
val photoFile: File? = try {
createImageFile()
} catch (ex: IOException) {
result.error("FILE_CREATION_FAILED", "Error occurred while creating the file", null)
null
}
if (photoFile != null) {
val photoURI = FileProvider.getUriForFile(this, "com.example.nativecameratest.fileprovider", photoFile)
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI)
startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE)
}
}
}
private fun createImageFile(): File {
val storageDir: File? = getExternalFilesDir(Environment.DIRECTORY_PICTURES)
return File.createTempFile(
"JPEG_${System.currentTimeMillis()}_", /* prefix */
".jpg", /* suffix */
storageDir /* directory */
).apply {
// Save a file path for use with ACTION_VIEW intents
currentPhotoPath = absolutePath
Log.d("MainActivity", "Image file created at: $currentPhotoPath")
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {
// Return the file path to Flutter
MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, CHANNEL).invokeMethod("imagePath", currentPhotoPath)
}
}
}
The camera opens as shown on the image below:
So here is what I intend to achieve:
Ability to take multiple photos before closing camera (Similar to when taking photos with WhatsApp) Which can be achieved if can be able access the full camera. If No.1 is not possible how can I go about it?
Send photos (paths of the photos) back to Flutter/Dart
Upvotes: 1
Views: 159