diff --git a/packages/camera/CHANGELOG.md b/packages/camera/CHANGELOG.md
index 71f7240a0016..f3c200c35524 100644
--- a/packages/camera/CHANGELOG.md
+++ b/packages/camera/CHANGELOG.md
@@ -1,3 +1,22 @@
+## 0.2.0
+
+* Added support for video recording.
+* Changed the example app to add video recording.
+
+A lot of **breaking changes** in this version:
+
+Getter changes:
+ - Removed `isStarted`
+ - Renamed `initialized` to `isInitialized`
+ - Added `isRecordingVideo`
+
+Method changes:
+ - Renamed `capture` to `takePicture`
+ - Removed `start` (the preview starts automatically when `initialize` is called)
+ - Added `startVideoRecording(String filePath)`
+ - Removed `stop` (the preview stops automatically when `dispose` is called)
+ - Added `stopVideoRecording`
+
## 0.1.2
* Fix Dart 2 runtime errors.
diff --git a/packages/camera/README.md b/packages/camera/README.md
index a6b62df2d686..2e224df6e2d8 100644
--- a/packages/camera/README.md
+++ b/packages/camera/README.md
@@ -15,13 +15,18 @@ First, add `camera` as a [dependency in your pubspec.yaml file](https://flutter.
### iOS
-Add a row to the `ios/Runner/Info.plist` of your app with the key `Privacy - Camera Usage Description` and a usage description.
+Add two rows to the `ios/Runner/Info.plist`:
+
+* one with the key `Privacy - Camera Usage Description` and a usage description.
+* and one with the key `Privacy - Microphone Usage Description` and a usage description.
Or in text format add the key:
```xml
NSCameraUsageDescription
Can I use the camera please?
+NSMicrophoneUsageDescription
+Can I use the mic please?
```
### Android
diff --git a/packages/camera/android/src/main/AndroidManifest.xml b/packages/camera/android/src/main/AndroidManifest.xml
index 449d282b9476..d80d364b4237 100644
--- a/packages/camera/android/src/main/AndroidManifest.xml
+++ b/packages/camera/android/src/main/AndroidManifest.xml
@@ -1,4 +1,5 @@
+
diff --git a/packages/camera/android/src/main/java/io/flutter/plugins/camera/CameraPlugin.java b/packages/camera/android/src/main/java/io/flutter/plugins/camera/CameraPlugin.java
index 472884dcd6af..1d4bedefbbf4 100644
--- a/packages/camera/android/src/main/java/io/flutter/plugins/camera/CameraPlugin.java
+++ b/packages/camera/android/src/main/java/io/flutter/plugins/camera/CameraPlugin.java
@@ -1,7 +1,6 @@
package io.flutter.plugins.camera;
import android.Manifest;
-import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.Application;
import android.content.Context;
@@ -19,9 +18,11 @@
import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageReader;
+import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.Surface;
@@ -47,33 +48,34 @@
public class CameraPlugin implements MethodCallHandler {
- private static final int cameraRequestId = 513469796;
- private static final SparseIntArray ORIENTATIONS = new SparseIntArray();
- private static CameraManager cameraManager;
-
- @SuppressLint("UseSparseArrays")
- private static Map cams = new HashMap<>();
-
- static {
- ORIENTATIONS.append(Surface.ROTATION_0, 0);
- ORIENTATIONS.append(Surface.ROTATION_90, 90);
- ORIENTATIONS.append(Surface.ROTATION_180, 180);
- ORIENTATIONS.append(Surface.ROTATION_270, 270);
- }
+ private static final int CAMERA_REQUEST_ID = 513469796;
+ private static final String TAG = "CameraPlugin";
+ private static final SparseIntArray ORIENTATIONS =
+ new SparseIntArray() {
+ {
+ append(Surface.ROTATION_0, 0);
+ append(Surface.ROTATION_90, 90);
+ append(Surface.ROTATION_180, 180);
+ append(Surface.ROTATION_270, 270);
+ }
+ };
+ private static CameraManager cameraManager;
private final FlutterView view;
+ private Camera camera;
private Activity activity;
private Registrar registrar;
- // The code to run after requesting the permission.
+ // The code to run after requesting camera permissions.
private Runnable cameraPermissionContinuation;
+ private boolean requestingPermission;
private CameraPlugin(Registrar registrar, FlutterView view, Activity activity) {
this.registrar = registrar;
-
- registrar.addRequestPermissionsResultListener(new CameraRequestPermissionsListener());
this.view = view;
this.activity = activity;
+ registrar.addRequestPermissionsResultListener(new CameraRequestPermissionsListener());
+
activity
.getApplication()
.registerActivityLifecycleCallbacks(
@@ -86,9 +88,13 @@ public void onActivityStarted(Activity activity) {}
@Override
public void onActivityResumed(Activity activity) {
+ if (requestingPermission) {
+ requestingPermission = false;
+ return;
+ }
if (activity == CameraPlugin.this.activity) {
- for (Cam cam : cams.values()) {
- cam.resume();
+ if (camera != null) {
+ camera.open(null);
}
}
}
@@ -96,8 +102,8 @@ public void onActivityResumed(Activity activity) {
@Override
public void onActivityPaused(Activity activity) {
if (activity == CameraPlugin.this.activity) {
- for (Cam cam : cams.values()) {
- cam.pause();
+ if (camera != null) {
+ camera.close();
}
}
}
@@ -105,7 +111,9 @@ public void onActivityPaused(Activity activity) {
@Override
public void onActivityStopped(Activity activity) {
if (activity == CameraPlugin.this.activity) {
- disposeAllCams();
+ if (camera != null) {
+ camera.close();
+ }
}
}
@@ -120,59 +128,23 @@ public void onActivityDestroyed(Activity activity) {}
public static void registerWith(Registrar registrar) {
final MethodChannel channel =
new MethodChannel(registrar.messenger(), "plugins.flutter.io/camera");
+
cameraManager = (CameraManager) registrar.activity().getSystemService(Context.CAMERA_SERVICE);
channel.setMethodCallHandler(
new CameraPlugin(registrar, registrar.view(), registrar.activity()));
}
- private Size getBestPreviewSize(
- StreamConfigurationMap streamConfigurationMap, Size minPreviewSize, Size captureSize) {
- Size[] sizes = streamConfigurationMap.getOutputSizes(SurfaceTexture.class);
- List goodEnough = new ArrayList<>();
- for (Size s : sizes) {
- if (s.getHeight() * captureSize.getWidth() == s.getWidth() * captureSize.getHeight()
- && minPreviewSize.getWidth() < s.getWidth()
- && minPreviewSize.getHeight() < s.getHeight()) {
- goodEnough.add(s);
- }
- }
- if (goodEnough.isEmpty()) {
- return sizes[0];
- }
- return Collections.min(goodEnough, new CompareSizesByArea());
- }
-
- private Size getBestCaptureSize(StreamConfigurationMap streamConfigurationMap) {
- // For still image captures, we use the largest available size.
- return Collections.max(
- Arrays.asList(streamConfigurationMap.getOutputSizes(ImageFormat.JPEG)),
- new CompareSizesByArea());
- }
-
- private long textureIdOfCall(MethodCall call) {
- return ((Number) call.argument("textureId")).longValue();
- }
-
- private Cam getCamOfCall(MethodCall call) {
- return cams.get(textureIdOfCall(call));
- }
-
- private void disposeAllCams() {
- for (Cam cam : cams.values()) {
- cam.dispose();
- }
- cams.clear();
- }
-
@Override
public void onMethodCall(MethodCall call, final Result result) {
switch (call.method) {
case "init":
- disposeAllCams();
+ if (camera != null) {
+ camera.close();
+ }
result.success(null);
break;
- case "list":
+ case "availableCameras":
try {
String[] cameraNames = cameraManager.getCameraIdList();
List