blob: 132075555f266d0c2d4a97267093eeccaaaaf2d0 [file] [log] [blame]
package io.flutter.plugins.camera;
import android.app.Activity;
import android.hardware.camera2.CameraAccessException;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugins.camera.CameraPermissions.PermissionsRegistry;
import io.flutter.view.TextureRegistry;
final class MethodCallHandlerImpl implements MethodChannel.MethodCallHandler {
private final Activity activity;
private final BinaryMessenger messenger;
private final CameraPermissions cameraPermissions;
private final PermissionsRegistry permissionsRegistry;
private final TextureRegistry textureRegistry;
private final MethodChannel methodChannel;
private final EventChannel imageStreamChannel;
private @Nullable Camera camera;
MethodCallHandlerImpl(
Activity activity,
BinaryMessenger messenger,
CameraPermissions cameraPermissions,
PermissionsRegistry permissionsAdder,
TextureRegistry textureRegistry) {
this.activity = activity;
this.messenger = messenger;
this.cameraPermissions = cameraPermissions;
this.permissionsRegistry = permissionsAdder;
this.textureRegistry = textureRegistry;
methodChannel = new MethodChannel(messenger, "plugins.flutter.io/camera");
imageStreamChannel = new EventChannel(messenger, "plugins.flutter.io/camera/imageStream");
methodChannel.setMethodCallHandler(this);
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull final Result result) {
switch (call.method) {
case "availableCameras":
try {
result.success(CameraUtils.getAvailableCameras(activity));
} catch (Exception e) {
handleException(e, result);
}
break;
case "initialize":
{
if (camera != null) {
camera.close();
}
cameraPermissions.requestPermissions(
activity,
permissionsRegistry,
call.argument("enableAudio"),
(String errCode, String errDesc) -> {
if (errCode == null) {
try {
instantiateCamera(call, result);
} catch (Exception e) {
handleException(e, result);
}
} else {
result.error(errCode, errDesc, null);
}
});
break;
}
case "takePicture":
{
camera.takePicture(call.argument("path"), result);
break;
}
case "prepareForVideoRecording":
{
// This optimization is not required for Android.
result.success(null);
break;
}
case "startVideoRecording":
{
camera.startVideoRecording(call.argument("filePath"), result);
break;
}
case "stopVideoRecording":
{
camera.stopVideoRecording(result);
break;
}
case "pauseVideoRecording":
{
camera.pauseVideoRecording(result);
break;
}
case "resumeVideoRecording":
{
camera.resumeVideoRecording(result);
break;
}
case "startImageStream":
{
try {
camera.startPreviewWithImageStream(imageStreamChannel);
result.success(null);
} catch (Exception e) {
handleException(e, result);
}
break;
}
case "stopImageStream":
{
try {
camera.startPreview();
result.success(null);
} catch (Exception e) {
handleException(e, result);
}
break;
}
case "dispose":
{
if (camera != null) {
camera.dispose();
}
result.success(null);
break;
}
default:
result.notImplemented();
break;
}
}
void stopListening() {
methodChannel.setMethodCallHandler(null);
}
private void instantiateCamera(MethodCall call, Result result) throws CameraAccessException {
String cameraName = call.argument("cameraName");
String resolutionPreset = call.argument("resolutionPreset");
boolean enableAudio = call.argument("enableAudio");
TextureRegistry.SurfaceTextureEntry flutterSurfaceTexture =
textureRegistry.createSurfaceTexture();
DartMessenger dartMessenger = new DartMessenger(messenger, flutterSurfaceTexture.id());
camera =
new Camera(
activity,
flutterSurfaceTexture,
dartMessenger,
cameraName,
resolutionPreset,
enableAudio);
camera.open(result);
}
// We move catching CameraAccessException out of onMethodCall because it causes a crash
// on plugin registration for sdks incompatible with Camera2 (< 21). We want this plugin to
// to be able to compile with <21 sdks for apps that want the camera and support earlier version.
@SuppressWarnings("ConstantConditions")
private void handleException(Exception exception, Result result) {
if (exception instanceof CameraAccessException) {
result.error("CameraAccess", exception.getMessage(), null);
return;
}
// CameraAccessException can not be cast to a RuntimeException.
throw (RuntimeException) exception;
}
}