blob: e7036e7090c1c468834bf7055b3ee0e7daac7968 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package io.flutter.plugins.camerax;
import android.content.Context;
import androidx.annotation.NonNull;
import androidx.camera.core.Camera;
import androidx.camera.core.CameraInfo;
import androidx.camera.core.CameraSelector;
import androidx.camera.core.UseCase;
import androidx.camera.lifecycle.ProcessCameraProvider;
import androidx.core.content.ContextCompat;
import androidx.lifecycle.LifecycleOwner;
import com.google.common.util.concurrent.ListenableFuture;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugins.camerax.GeneratedCameraXLibrary.ProcessCameraProviderHostApi;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
public class ProcessCameraProviderHostApiImpl implements ProcessCameraProviderHostApi {
private final BinaryMessenger binaryMessenger;
private final InstanceManager instanceManager;
private Context context;
private LifecycleOwner lifecycleOwner;
public ProcessCameraProviderHostApiImpl(
BinaryMessenger binaryMessenger, InstanceManager instanceManager, Context context) {
this.binaryMessenger = binaryMessenger;
this.instanceManager = instanceManager;
this.context = context;
}
public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
this.lifecycleOwner = lifecycleOwner;
}
/**
* Sets the context that the {@code ProcessCameraProvider} will use to attach the lifecycle of the
* camera to.
*
* <p>If using the camera plugin in an add-to-app context, ensure that a new instance of the
* {@code ProcessCameraProvider} is fetched via {@code #getInstance} anytime the context changes.
*/
public void setContext(Context context) {
this.context = context;
}
/**
* Returns the instance of the {@code ProcessCameraProvider} to manage the lifecycle of the camera
* for the current {@code Context}.
*/
@Override
public void getInstance(GeneratedCameraXLibrary.Result<Long> result) {
ListenableFuture<ProcessCameraProvider> processCameraProviderFuture =
ProcessCameraProvider.getInstance(context);
processCameraProviderFuture.addListener(
() -> {
try {
// Camera provider is now guaranteed to be available.
ProcessCameraProvider processCameraProvider = processCameraProviderFuture.get();
final ProcessCameraProviderFlutterApiImpl flutterApi =
new ProcessCameraProviderFlutterApiImpl(binaryMessenger, instanceManager);
if (!instanceManager.containsInstance(processCameraProvider)) {
flutterApi.create(processCameraProvider, reply -> {});
}
result.success(instanceManager.getIdentifierForStrongReference(processCameraProvider));
} catch (Exception e) {
result.error(e);
}
},
ContextCompat.getMainExecutor(context));
}
/** Returns cameras available to the {@code ProcessCameraProvider}. */
@Override
public List<Long> getAvailableCameraInfos(@NonNull Long identifier) {
ProcessCameraProvider processCameraProvider =
(ProcessCameraProvider) Objects.requireNonNull(instanceManager.getInstance(identifier));
List<CameraInfo> availableCameras = processCameraProvider.getAvailableCameraInfos();
List<Long> availableCamerasIds = new ArrayList<Long>();
final CameraInfoFlutterApiImpl cameraInfoFlutterApi =
new CameraInfoFlutterApiImpl(binaryMessenger, instanceManager);
for (CameraInfo cameraInfo : availableCameras) {
if (!instanceManager.containsInstance(cameraInfo)) {
cameraInfoFlutterApi.create(cameraInfo, result -> {});
}
availableCamerasIds.add(instanceManager.getIdentifierForStrongReference(cameraInfo));
}
return availableCamerasIds;
}
/**
* Binds specified {@code UseCase}s to the lifecycle of the {@code LifecycleOwner} that
* corresponds to this instance and returns the instance of the {@code Camera} whose lifecycle
* that {@code LifecycleOwner} reflects.
*/
@Override
public Long bindToLifecycle(
@NonNull Long identifier,
@NonNull Long cameraSelectorIdentifier,
@NonNull List<Long> useCaseIds) {
ProcessCameraProvider processCameraProvider =
(ProcessCameraProvider) Objects.requireNonNull(instanceManager.getInstance(identifier));
CameraSelector cameraSelector =
(CameraSelector)
Objects.requireNonNull(instanceManager.getInstance(cameraSelectorIdentifier));
UseCase[] useCases = new UseCase[useCaseIds.size()];
for (int i = 0; i < useCaseIds.size(); i++) {
useCases[i] =
(UseCase)
Objects.requireNonNull(
instanceManager.getInstance(((Number) useCaseIds.get(i)).longValue()));
}
Camera camera =
processCameraProvider.bindToLifecycle(
(LifecycleOwner) lifecycleOwner, cameraSelector, useCases);
final CameraFlutterApiImpl cameraFlutterApi =
new CameraFlutterApiImpl(binaryMessenger, instanceManager);
if (!instanceManager.containsInstance(camera)) {
cameraFlutterApi.create(camera, result -> {});
}
return instanceManager.getIdentifierForStrongReference(camera);
}
@Override
public void unbind(@NonNull Long identifier, @NonNull List<Long> useCaseIds) {
ProcessCameraProvider processCameraProvider =
(ProcessCameraProvider) Objects.requireNonNull(instanceManager.getInstance(identifier));
UseCase[] useCases = new UseCase[useCaseIds.size()];
for (int i = 0; i < useCaseIds.size(); i++) {
useCases[i] =
(UseCase)
Objects.requireNonNull(
instanceManager.getInstance(((Number) useCaseIds.get(i)).longValue()));
}
processCameraProvider.unbind(useCases);
}
@Override
public void unbindAll(@NonNull Long identifier) {
ProcessCameraProvider processCameraProvider =
(ProcessCameraProvider) Objects.requireNonNull(instanceManager.getInstance(identifier));
processCameraProvider.unbindAll();
}
}