mirror of
https://github.com/status-im/react-native-camera.git
synced 2025-02-23 17:28:08 +00:00
Android support.
Working: set aspect, select camera type, set flash/torch mode, take picture and save it to the file system, mediaroll as data. Not working: Video capture, set orientation. Known problem: Front camera pictures are not oriented correctly.
This commit is contained in:
parent
8e1ae7c9a4
commit
844d6aaf65
34
android/build.gradle
Executable file
34
android/build.gradle
Executable file
@ -0,0 +1,34 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:1.2.3'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 23
|
||||||
|
buildToolsVersion "23.0.1"
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 16
|
||||||
|
targetSdkVersion 22
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
}
|
||||||
|
lintOptions {
|
||||||
|
abortOnError false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile "com.facebook.react:react-native:0.17.+"
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.lwansbrough.ReactCamera">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.lwansbrough.RCTCamera">
|
||||||
<uses-permission android:name="android.permission.CAMERA" />
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
<uses-feature android:name="android.hardware.camera" />
|
<uses-feature android:name="android.hardware.camera" />
|
||||||
<uses-feature android:name="android.hardware.camera.autofocus" />
|
<uses-feature android:name="android.hardware.camera.autofocus" />
|
201
android/src/main/java/com/lwansbrough/RCTCamera/RCTCamera.java
Normal file
201
android/src/main/java/com/lwansbrough/RCTCamera/RCTCamera.java
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
/**
|
||||||
|
* Created by Fabrice Armisen (farmisen@gmail.com) on 1/4/16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.lwansbrough.RCTCamera;
|
||||||
|
|
||||||
|
import android.hardware.Camera;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class RCTCamera {
|
||||||
|
|
||||||
|
private static final RCTCamera ourInstance = new RCTCamera();
|
||||||
|
private final HashMap<Integer, CameraInfoWrapper> _cameraInfos;
|
||||||
|
private final HashMap<Integer, Integer> _cameraTypeToIndex;
|
||||||
|
private final Map<Number, Camera> _cameras;
|
||||||
|
private int _orientation = -1;
|
||||||
|
private int _actualDeviceOrientation = 0;
|
||||||
|
|
||||||
|
public static RCTCamera getInstance() {
|
||||||
|
return ourInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Camera acquireCameraInstance(int type) {
|
||||||
|
if (null == _cameras.get(type) && null != _cameraTypeToIndex.get(type)) {
|
||||||
|
try {
|
||||||
|
Camera camera = Camera.open(_cameraTypeToIndex.get(type));
|
||||||
|
_cameras.put(type, camera);
|
||||||
|
adjustPreviewLayout(type);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.console().printf("acquireCameraInstance: %s", e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _cameras.get(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void releaseCameraInstance(int type) {
|
||||||
|
if (null != _cameras.get(type)) {
|
||||||
|
_cameras.get(type).release();
|
||||||
|
_cameras.remove(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPreviewWidth(int type) {
|
||||||
|
CameraInfoWrapper cameraInfo = _cameraInfos.get(type);
|
||||||
|
if (null == cameraInfo) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return cameraInfo.previewWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPreviewHeight(int type) {
|
||||||
|
CameraInfoWrapper cameraInfo = _cameraInfos.get(type);
|
||||||
|
if (null == cameraInfo) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return cameraInfo.previewHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrientation(int orientation) {
|
||||||
|
if (_orientation == orientation) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_orientation = orientation;
|
||||||
|
adjustPreviewLayout(RCTCameraModule.RCT_CAMERA_TYPE_FRONT);
|
||||||
|
adjustPreviewLayout(RCTCameraModule.RCT_CAMERA_TYPE_BACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActualDeviceOrientation(int actualDeviceOrientation) {
|
||||||
|
_actualDeviceOrientation = actualDeviceOrientation;
|
||||||
|
adjustPreviewLayout(RCTCameraModule.RCT_CAMERA_TYPE_FRONT);
|
||||||
|
adjustPreviewLayout(RCTCameraModule.RCT_CAMERA_TYPE_BACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTorchMode(int cameraType, int torchMode) {
|
||||||
|
Camera camera = _cameras.get(cameraType);
|
||||||
|
if (null == camera) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Camera.Parameters parameters = camera.getParameters();
|
||||||
|
String value = parameters.getFlashMode();
|
||||||
|
switch (torchMode) {
|
||||||
|
case RCTCameraModule.RCT_CAMERA_TORCH_MODE_ON:
|
||||||
|
value = Camera.Parameters.FLASH_MODE_TORCH;
|
||||||
|
break;
|
||||||
|
case RCTCameraModule.RCT_CAMERA_TORCH_MODE_OFF:
|
||||||
|
value = Camera.Parameters.FLASH_MODE_OFF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> flashModes = parameters.getSupportedFlashModes();
|
||||||
|
if (flashModes != null && flashModes.contains(value)) {
|
||||||
|
parameters.setFlashMode(value);
|
||||||
|
camera.setParameters(parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFlashMode(int cameraType, int flashMode) {
|
||||||
|
Camera camera = _cameras.get(cameraType);
|
||||||
|
if (null == camera) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Camera.Parameters parameters = camera.getParameters();
|
||||||
|
String value = parameters.getFlashMode();
|
||||||
|
switch (flashMode) {
|
||||||
|
case RCTCameraModule.RCT_CAMERA_FLASH_MODE_AUTO:
|
||||||
|
value = Camera.Parameters.FLASH_MODE_AUTO;
|
||||||
|
break;
|
||||||
|
case RCTCameraModule.RCT_CAMERA_FLASH_MODE_ON:
|
||||||
|
value = Camera.Parameters.FLASH_MODE_ON;
|
||||||
|
break;
|
||||||
|
case RCTCameraModule.RCT_CAMERA_FLASH_MODE_OFF:
|
||||||
|
value = Camera.Parameters.FLASH_MODE_OFF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
List<String> flashModes = parameters.getSupportedFlashModes();
|
||||||
|
if (flashModes != null && flashModes.contains(value)) {
|
||||||
|
parameters.setFlashMode(value);
|
||||||
|
camera.setParameters(parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void adjustPreviewLayout(int type) {
|
||||||
|
Camera camera = _cameras.get(type);
|
||||||
|
if (null == camera) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CameraInfoWrapper cameraInfo = _cameraInfos.get(type);
|
||||||
|
int rotation = cameraInfo.info.orientation;
|
||||||
|
if (cameraInfo.info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
|
||||||
|
rotation = (720 - rotation - _actualDeviceOrientation * 90) % 360;
|
||||||
|
} else {
|
||||||
|
rotation = (rotation - _actualDeviceOrientation * 90 + 360) % 360;
|
||||||
|
}
|
||||||
|
cameraInfo.rotation = rotation;
|
||||||
|
// TODO: take in account the _orientation prop
|
||||||
|
|
||||||
|
camera.setDisplayOrientation(cameraInfo.rotation);
|
||||||
|
|
||||||
|
Camera.Parameters parameters = camera.getParameters();
|
||||||
|
parameters.setRotation(cameraInfo.rotation);
|
||||||
|
|
||||||
|
// set preview size
|
||||||
|
int width = parameters.getSupportedPreviewSizes().get(0).width;
|
||||||
|
int height = parameters.getSupportedPreviewSizes().get(0).height;
|
||||||
|
|
||||||
|
parameters.setPreviewSize(width, height);
|
||||||
|
try {
|
||||||
|
camera.setParameters(parameters);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cameraInfo.rotation == 0 || cameraInfo.rotation == 180) {
|
||||||
|
cameraInfo.previewWidth = width;
|
||||||
|
cameraInfo.previewHeight = height;
|
||||||
|
} else {
|
||||||
|
cameraInfo.previewWidth = height;
|
||||||
|
cameraInfo.previewHeight = width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private RCTCamera() {
|
||||||
|
_cameras = new HashMap<>();
|
||||||
|
_cameraInfos = new HashMap<>();
|
||||||
|
_cameraTypeToIndex = new HashMap<>();
|
||||||
|
|
||||||
|
// map camera types to camera indexes and collect cameras properties
|
||||||
|
for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
|
||||||
|
Camera.CameraInfo info = new Camera.CameraInfo();
|
||||||
|
Camera.getCameraInfo(i, info);
|
||||||
|
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT && _cameraInfos.get(RCTCameraModule.RCT_CAMERA_TYPE_FRONT) == null) {
|
||||||
|
_cameraInfos.put(RCTCameraModule.RCT_CAMERA_TYPE_FRONT, new CameraInfoWrapper(info));
|
||||||
|
_cameraTypeToIndex.put(RCTCameraModule.RCT_CAMERA_TYPE_FRONT, i);
|
||||||
|
acquireCameraInstance(RCTCameraModule.RCT_CAMERA_TYPE_FRONT);
|
||||||
|
releaseCameraInstance(RCTCameraModule.RCT_CAMERA_TYPE_FRONT);
|
||||||
|
} else if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK && _cameraInfos.get(RCTCameraModule.RCT_CAMERA_TYPE_BACK) == null) {
|
||||||
|
_cameraInfos.put(RCTCameraModule.RCT_CAMERA_TYPE_BACK, new CameraInfoWrapper(info));
|
||||||
|
_cameraTypeToIndex.put(RCTCameraModule.RCT_CAMERA_TYPE_BACK, i);
|
||||||
|
acquireCameraInstance(RCTCameraModule.RCT_CAMERA_TYPE_BACK);
|
||||||
|
releaseCameraInstance(RCTCameraModule.RCT_CAMERA_TYPE_BACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CameraInfoWrapper {
|
||||||
|
public final Camera.CameraInfo info;
|
||||||
|
public int rotation = 0;
|
||||||
|
public int previewWidth = -1;
|
||||||
|
public int previewHeight = -1;
|
||||||
|
|
||||||
|
public CameraInfoWrapper(Camera.CameraInfo info) {
|
||||||
|
this.info = info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,229 @@
|
|||||||
|
/**
|
||||||
|
* Created by Fabrice Armisen (farmisen@gmail.com) on 1/4/16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.lwansbrough.RCTCamera;
|
||||||
|
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.BitmapFactory;
|
||||||
|
import android.hardware.Camera;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.provider.MediaStore;
|
||||||
|
import android.util.Base64;
|
||||||
|
import android.util.Log;
|
||||||
|
import com.facebook.react.bridge.*;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.*;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class RCTCameraModule extends ReactContextBaseJavaModule {
|
||||||
|
private static final String TAG = "RCTCameraModule";
|
||||||
|
|
||||||
|
public static final int RCT_CAMERA_ASPECT_FILL = 0;
|
||||||
|
public static final int RCT_CAMERA_ASPECT_FIT = 1;
|
||||||
|
public static final int RCT_CAMERA_ASPECT_STRETCH = 2;
|
||||||
|
public static final int RCT_CAMERA_CAPTURE_MODE_STILL = 0;
|
||||||
|
public static final int RCT_CAMERA_CAPTURE_MODE_VIDEO = 1;
|
||||||
|
public static final int RCT_CAMERA_CAPTURE_TARGET_MEMORY = 0;
|
||||||
|
public static final int RCT_CAMERA_CAPTURE_TARGET_DISK = 1;
|
||||||
|
public static final int RCT_CAMERA_CAPTURE_TARGET_CAMERA_ROLL = 2;
|
||||||
|
public static final int RCT_CAMERA_ORIENTATION_AUTO = 0;
|
||||||
|
public static final int RCT_CAMERA_ORIENTATION_LANDSCAPE_LEFT = 1;
|
||||||
|
public static final int RCT_CAMERA_ORIENTATION_LANDSCAPE_RIGHT = 2;
|
||||||
|
public static final int RCT_CAMERA_ORIENTATION_PORTRAIT = 3;
|
||||||
|
public static final int RCT_CAMERA_ORIENTATION_PORTRAIT_UPSIDE_DOWN = 4;
|
||||||
|
public static final int RCT_CAMERA_TYPE_FRONT = 1;
|
||||||
|
public static final int RCT_CAMERA_TYPE_BACK = 2;
|
||||||
|
public static final int RCT_CAMERA_FLASH_MODE_OFF = 0;
|
||||||
|
public static final int RCT_CAMERA_FLASH_MODE_ON = 1;
|
||||||
|
public static final int RCT_CAMERA_FLASH_MODE_AUTO = 2;
|
||||||
|
public static final int RCT_CAMERA_TORCH_MODE_OFF = 0;
|
||||||
|
public static final int RCT_CAMERA_TORCH_MODE_ON = 1;
|
||||||
|
public static final int RCT_CAMERA_TORCH_MODE_AUTO = 2;
|
||||||
|
public static final int MEDIA_TYPE_IMAGE = 1;
|
||||||
|
public static final int MEDIA_TYPE_VIDEO = 2;
|
||||||
|
|
||||||
|
private final ReactApplicationContext _reactContext;
|
||||||
|
|
||||||
|
public RCTCameraModule(ReactApplicationContext reactContext) {
|
||||||
|
super(reactContext);
|
||||||
|
_reactContext = reactContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "RCTCameraModule";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> getConstants() {
|
||||||
|
return Collections.unmodifiableMap(new HashMap<String, Object>() {
|
||||||
|
{
|
||||||
|
put("Aspect", getAspectConstants());
|
||||||
|
put("Type", getTypeConstants());
|
||||||
|
put("CaptureMode", getCaptureModeConstants());
|
||||||
|
put("CaptureTarget", getCaptureTargetConstants());
|
||||||
|
put("Orientation", getOrientationConstants());
|
||||||
|
put("FlashMode", getFlashModeConstants());
|
||||||
|
put("TorchMode", getTorchModeConstants());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> getAspectConstants() {
|
||||||
|
return Collections.unmodifiableMap(new HashMap<String, Object>() {
|
||||||
|
{
|
||||||
|
put("stretch", RCT_CAMERA_ASPECT_STRETCH);
|
||||||
|
put("fit", RCT_CAMERA_ASPECT_FIT);
|
||||||
|
put("fill", RCT_CAMERA_ASPECT_FILL);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> getTypeConstants() {
|
||||||
|
return Collections.unmodifiableMap(new HashMap<String, Object>() {
|
||||||
|
{
|
||||||
|
put("front", RCT_CAMERA_TYPE_FRONT);
|
||||||
|
put("back", RCT_CAMERA_TYPE_BACK);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> getCaptureModeConstants() {
|
||||||
|
return Collections.unmodifiableMap(new HashMap<String, Object>() {
|
||||||
|
{
|
||||||
|
put("still", RCT_CAMERA_CAPTURE_MODE_STILL);
|
||||||
|
put("video", RCT_CAMERA_CAPTURE_MODE_VIDEO);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> getCaptureTargetConstants() {
|
||||||
|
return Collections.unmodifiableMap(new HashMap<String, Object>() {
|
||||||
|
{
|
||||||
|
put("memory", RCT_CAMERA_CAPTURE_TARGET_MEMORY);
|
||||||
|
put("disk", RCT_CAMERA_CAPTURE_TARGET_DISK);
|
||||||
|
put("cameraRoll", RCT_CAMERA_CAPTURE_TARGET_CAMERA_ROLL);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> getOrientationConstants() {
|
||||||
|
return Collections.unmodifiableMap(new HashMap<String, Object>() {
|
||||||
|
{
|
||||||
|
put("auto", RCT_CAMERA_ORIENTATION_AUTO);
|
||||||
|
put("landscapeLeft", RCT_CAMERA_ORIENTATION_LANDSCAPE_LEFT);
|
||||||
|
put("landscapeRight", RCT_CAMERA_ORIENTATION_LANDSCAPE_RIGHT);
|
||||||
|
put("portrait", RCT_CAMERA_ORIENTATION_PORTRAIT);
|
||||||
|
put("portraitUpsideDown", RCT_CAMERA_ORIENTATION_PORTRAIT_UPSIDE_DOWN);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> getFlashModeConstants() {
|
||||||
|
return Collections.unmodifiableMap(new HashMap<String, Object>() {
|
||||||
|
{
|
||||||
|
put("off", RCT_CAMERA_FLASH_MODE_OFF);
|
||||||
|
put("on", RCT_CAMERA_FLASH_MODE_ON);
|
||||||
|
put("auto", RCT_CAMERA_FLASH_MODE_AUTO);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, Object> getTorchModeConstants() {
|
||||||
|
return Collections.unmodifiableMap(new HashMap<String, Object>() {
|
||||||
|
{
|
||||||
|
put("off", RCT_CAMERA_TORCH_MODE_OFF);
|
||||||
|
put("on", RCT_CAMERA_TORCH_MODE_ON);
|
||||||
|
put("auto", RCT_CAMERA_TORCH_MODE_AUTO);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void capture(final ReadableMap options, final Callback callback) {
|
||||||
|
Camera camera = RCTCamera.getInstance().acquireCameraInstance(options.getInt("type"));
|
||||||
|
if (null == camera) {
|
||||||
|
callback.invoke("No camera found.", null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
camera.takePicture(null, null, new Camera.PictureCallback() {
|
||||||
|
@Override
|
||||||
|
public void onPictureTaken(byte[] data, Camera camera) {
|
||||||
|
switch (options.getInt("target")) {
|
||||||
|
case RCT_CAMERA_CAPTURE_TARGET_MEMORY:
|
||||||
|
String encoded = Base64.encodeToString(data, Base64.DEFAULT);
|
||||||
|
callback.invoke(null, encoded);
|
||||||
|
break;
|
||||||
|
case RCT_CAMERA_CAPTURE_TARGET_CAMERA_ROLL:
|
||||||
|
BitmapFactory.Options bitmapOptions = new BitmapFactory.Options();
|
||||||
|
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length, bitmapOptions);
|
||||||
|
String url = MediaStore.Images.Media.insertImage(
|
||||||
|
_reactContext.getContentResolver(),
|
||||||
|
bitmap, options.getString("title"),
|
||||||
|
options.getString("description"));
|
||||||
|
callback.invoke(null, url);
|
||||||
|
break;
|
||||||
|
case RCT_CAMERA_CAPTURE_TARGET_DISK:
|
||||||
|
File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE);
|
||||||
|
if (pictureFile == null) {
|
||||||
|
callback.invoke("Error creating media file.", null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
FileOutputStream fos = new FileOutputStream(pictureFile);
|
||||||
|
fos.write(data);
|
||||||
|
fos.close();
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
callback.invoke("File not found: " + e.getMessage(), null);
|
||||||
|
} catch (IOException e) {
|
||||||
|
callback.invoke("Error accessing file: " + e.getMessage(), null);
|
||||||
|
}
|
||||||
|
callback.invoke(null, Uri.fromFile(pictureFile).toString());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void stopCapture(final ReadableMap options, final Callback callback) {
|
||||||
|
// TODO: implement video capture
|
||||||
|
}
|
||||||
|
|
||||||
|
private File getOutputMediaFile(int type) {
|
||||||
|
File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(
|
||||||
|
Environment.DIRECTORY_PICTURES), "RCTCameraModule");
|
||||||
|
|
||||||
|
// Create the storage directory if it does not exist
|
||||||
|
if (!mediaStorageDir.exists()) {
|
||||||
|
if (!mediaStorageDir.mkdirs()) {
|
||||||
|
Log.e(TAG, "failed to create directory:" + mediaStorageDir.getAbsolutePath());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a media file name
|
||||||
|
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
|
||||||
|
File mediaFile;
|
||||||
|
if (type == MEDIA_TYPE_IMAGE) {
|
||||||
|
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
|
||||||
|
"IMG_" + timeStamp + ".jpg");
|
||||||
|
} else if (type == MEDIA_TYPE_VIDEO) {
|
||||||
|
mediaFile = new File(mediaStorageDir.getPath() + File.separator +
|
||||||
|
"VID_" + timeStamp + ".mp4");
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Unsupported media type:" + type);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return mediaFile;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,31 @@
|
|||||||
|
package com.lwansbrough.RCTCamera;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.facebook.react.ReactPackage;
|
||||||
|
import com.facebook.react.bridge.NativeModule;
|
||||||
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
|
import com.facebook.react.uimanager.ViewManager;
|
||||||
|
import com.facebook.react.bridge.JavaScriptModule;
|
||||||
|
|
||||||
|
public class RCTCameraPackage implements ReactPackage {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<NativeModule> createNativeModules(ReactApplicationContext reactApplicationContext) {
|
||||||
|
return Collections.<NativeModule>singletonList(new RCTCameraModule(reactApplicationContext));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Class<? extends JavaScriptModule>> createJSModules() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ViewManager> createViewManagers(ReactApplicationContext reactApplicationContext) {
|
||||||
|
//noinspection ArraysAsListWithZeroOrOneArgument
|
||||||
|
return Collections.<ViewManager>singletonList(new RCTCameraViewManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,149 @@
|
|||||||
|
/**
|
||||||
|
* Created by Fabrice Armisen (farmisen@gmail.com) on 1/3/16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.lwansbrough.RCTCamera;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.*;
|
||||||
|
import android.hardware.SensorManager;
|
||||||
|
import android.view.OrientationEventListener;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
public class RCTCameraView extends ViewGroup {
|
||||||
|
private final OrientationEventListener _orientationListener;
|
||||||
|
private final Context _context;
|
||||||
|
private RCTCameraViewFinder _viewFinder = null;
|
||||||
|
private int _actualDeviceOrientation = -1;
|
||||||
|
private int _aspect = RCTCameraModule.RCT_CAMERA_ASPECT_FIT;
|
||||||
|
private int _torchMode = -1;
|
||||||
|
private int _flashMode = -1;
|
||||||
|
|
||||||
|
public RCTCameraView(Context context) {
|
||||||
|
super(context);
|
||||||
|
this._context = context;
|
||||||
|
setActualDeviceOrientation(context);
|
||||||
|
|
||||||
|
_orientationListener = new OrientationEventListener(context, SensorManager.SENSOR_DELAY_NORMAL) {
|
||||||
|
@Override
|
||||||
|
public void onOrientationChanged(int orientation) {
|
||||||
|
if (setActualDeviceOrientation(_context)) {
|
||||||
|
layoutViewFinder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_orientationListener.canDetectOrientation()) {
|
||||||
|
_orientationListener.enable();
|
||||||
|
} else {
|
||||||
|
_orientationListener.disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||||
|
layoutViewFinder(left, top, right, bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAspect(int aspect) {
|
||||||
|
this._aspect = aspect;
|
||||||
|
layoutViewFinder();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCameraType(final int type) {
|
||||||
|
if (null != this._viewFinder) {
|
||||||
|
this._viewFinder.setCameraType(type);
|
||||||
|
} else {
|
||||||
|
_viewFinder = new RCTCameraViewFinder(_context, type);
|
||||||
|
if (-1 != this._flashMode) {
|
||||||
|
_viewFinder.setFlashMode(this._flashMode);
|
||||||
|
}
|
||||||
|
if (-1 != this._torchMode) {
|
||||||
|
_viewFinder.setFlashMode(this._torchMode);
|
||||||
|
}
|
||||||
|
addView(_viewFinder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTorchMode(int torchMode) {
|
||||||
|
this._torchMode = torchMode;
|
||||||
|
if (this._viewFinder != null) {
|
||||||
|
this._viewFinder.setTorchMode(torchMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFlashMode(int flashMode) {
|
||||||
|
this._flashMode = flashMode;
|
||||||
|
if (this._viewFinder != null) {
|
||||||
|
this._viewFinder.setFlashMode(flashMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrientation(int orientation) {
|
||||||
|
RCTCamera.getInstance().setOrientation(orientation);
|
||||||
|
if (this._viewFinder != null) {
|
||||||
|
layoutViewFinder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean setActualDeviceOrientation(Context context) {
|
||||||
|
int actualDeviceOrientation = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getOrientation();
|
||||||
|
if (_actualDeviceOrientation != actualDeviceOrientation) {
|
||||||
|
_actualDeviceOrientation = actualDeviceOrientation;
|
||||||
|
RCTCamera.getInstance().setActualDeviceOrientation(_actualDeviceOrientation);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void layoutViewFinder() {
|
||||||
|
layoutViewFinder(this.getLeft(), this.getTop(), this.getRight(), this.getBottom());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void layoutViewFinder(int left, int top, int right, int bottom) {
|
||||||
|
if (null == _viewFinder) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
float width = right - left;
|
||||||
|
float height = bottom - top;
|
||||||
|
int viewfinderWidth;
|
||||||
|
int viewfinderHeight;
|
||||||
|
double ratio;
|
||||||
|
switch (this._aspect) {
|
||||||
|
case RCTCameraModule.RCT_CAMERA_ASPECT_FIT:
|
||||||
|
ratio = this._viewFinder.getRatio();
|
||||||
|
if (ratio * height > width) {
|
||||||
|
viewfinderHeight = (int) (width / ratio);
|
||||||
|
viewfinderWidth = (int) width;
|
||||||
|
} else {
|
||||||
|
viewfinderWidth = (int) (ratio * height);
|
||||||
|
viewfinderHeight = (int) height;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case RCTCameraModule.RCT_CAMERA_ASPECT_FILL:
|
||||||
|
ratio = this._viewFinder.getRatio();
|
||||||
|
if (ratio * height < width) {
|
||||||
|
viewfinderHeight = (int) (width / ratio);
|
||||||
|
viewfinderWidth = (int) width;
|
||||||
|
} else {
|
||||||
|
viewfinderWidth = (int) (ratio * height);
|
||||||
|
viewfinderHeight = (int) height;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
viewfinderWidth = (int) width;
|
||||||
|
viewfinderHeight = (int) height;
|
||||||
|
}
|
||||||
|
|
||||||
|
int viewFinderPaddingX = (int) ((width - viewfinderWidth) / 2);
|
||||||
|
int viewFinderPaddingY = (int) ((height - viewfinderHeight) / 2);
|
||||||
|
|
||||||
|
this._viewFinder.layout(viewFinderPaddingX, viewFinderPaddingY, viewFinderPaddingX + viewfinderWidth, viewFinderPaddingY + viewfinderHeight);
|
||||||
|
this.postInvalidate(this.getLeft(), this.getTop(), this.getRight(), this.getBottom());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,125 @@
|
|||||||
|
/**
|
||||||
|
* Created by Fabrice Armisen (farmisen@gmail.com) on 1/3/16.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.lwansbrough.RCTCamera;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.SurfaceTexture;
|
||||||
|
import android.hardware.Camera;
|
||||||
|
import android.view.TextureView;
|
||||||
|
|
||||||
|
|
||||||
|
class RCTCameraViewFinder extends TextureView implements TextureView.SurfaceTextureListener {
|
||||||
|
private int _cameraType;
|
||||||
|
private SurfaceTexture _surfaceTexture;
|
||||||
|
private boolean _isStarting;
|
||||||
|
private boolean _isStopping;
|
||||||
|
private Camera _camera;
|
||||||
|
|
||||||
|
public RCTCameraViewFinder(Context context, int type) {
|
||||||
|
super(context);
|
||||||
|
this.setSurfaceTextureListener(this);
|
||||||
|
this._cameraType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
|
||||||
|
_surfaceTexture = surface;
|
||||||
|
startCamera();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
|
||||||
|
_surfaceTexture = null;
|
||||||
|
stopCamera();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRatio() {
|
||||||
|
int width = RCTCamera.getInstance().getPreviewWidth(this._cameraType);
|
||||||
|
int height = RCTCamera.getInstance().getPreviewHeight(this._cameraType);
|
||||||
|
return ((float) width) / ((float) height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCameraType(final int type) {
|
||||||
|
if (this._cameraType == type) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
stopPreview();
|
||||||
|
_cameraType = type;
|
||||||
|
startPreview();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTorchMode(int torchMode) {
|
||||||
|
RCTCamera.getInstance().setTorchMode(_cameraType, torchMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFlashMode(int flashMode) {
|
||||||
|
RCTCamera.getInstance().setTorchMode(_cameraType, flashMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startPreview() {
|
||||||
|
if (_surfaceTexture != null) {
|
||||||
|
startCamera();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void stopPreview() {
|
||||||
|
if (_camera != null) {
|
||||||
|
stopCamera();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized private void startCamera() {
|
||||||
|
if (!_isStarting) {
|
||||||
|
_isStarting = true;
|
||||||
|
try {
|
||||||
|
_camera = RCTCamera.getInstance().acquireCameraInstance(_cameraType);
|
||||||
|
_camera.setPreviewTexture(_surfaceTexture);
|
||||||
|
_camera.startPreview();
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
stopCamera();
|
||||||
|
} finally {
|
||||||
|
_isStarting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized private void stopCamera() {
|
||||||
|
if (!_isStopping) {
|
||||||
|
_isStopping = true;
|
||||||
|
try {
|
||||||
|
if (_camera != null) {
|
||||||
|
_camera.stopPreview();
|
||||||
|
RCTCamera.getInstance().releaseCameraInstance(_cameraType);
|
||||||
|
_camera = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
_isStopping = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
|||||||
|
package com.lwansbrough.RCTCamera;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import com.facebook.react.uimanager.*;
|
||||||
|
|
||||||
|
public class RCTCameraViewManager extends SimpleViewManager<RCTCameraView> {
|
||||||
|
private static final String REACT_CLASS = "RCTCameraView";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return REACT_CLASS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RCTCameraView createViewInstance(ThemedReactContext context) {
|
||||||
|
return new RCTCameraView(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = "aspect")
|
||||||
|
public void setAspect(RCTCameraView view, int aspect) {
|
||||||
|
view.setAspect(aspect);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = "captureMode")
|
||||||
|
public void setCaptureMode(RCTCameraView view, int captureMode) {
|
||||||
|
// TODO - implement video mode
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = "captureTarget")
|
||||||
|
public void setCaptureTarget(RCTCameraView view, int captureTarget) {
|
||||||
|
// No reason to handle this props value here since it's passed again to the RCTCameraModule capture method
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = "type")
|
||||||
|
public void setType(RCTCameraView view, int type) {
|
||||||
|
view.setCameraType(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = "torchMode")
|
||||||
|
public void setTorchMode(RCTCameraView view, int torchMode) {
|
||||||
|
view.setTorchMode(torchMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = "flashMode")
|
||||||
|
public void setFlashMode(RCTCameraView view, int flashMode) {
|
||||||
|
view.setFlashMode(flashMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = "orientation")
|
||||||
|
public void setOrientation(RCTCameraView view, int orientation) {
|
||||||
|
view.setOrientation(orientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactProp(name = "captureAudio")
|
||||||
|
public void setCaptureAudio(RCTCameraView view, boolean captureAudio) {
|
||||||
|
// TODO - implement video mode
|
||||||
|
}
|
||||||
|
}
|
@ -1,23 +0,0 @@
|
|||||||
package com.lwansbrough.RCTCamera;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.facebook.react.ReactPackage;
|
|
||||||
import com.facebook.react.bridge.NativeModule;
|
|
||||||
import com.facebook.react.bridge.ReactApplicationContext;
|
|
||||||
import com.facebook.react.uimanager.ViewManager;
|
|
||||||
import com.facebook.react.bridge.JavaScriptModule;
|
|
||||||
|
|
||||||
public class ReactCamera implements ReactPackage {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
|
||||||
return Arrays.<ViewManager>asList(
|
|
||||||
new ReactCameraManager()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
package com.lwansbrough.RCTCamera;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.facebook.react.ReactPackage;
|
|
||||||
import com.facebook.react.bridge.NativeModule;
|
|
||||||
import com.facebook.react.bridge.ReactApplicationContext;
|
|
||||||
import com.facebook.react.uimanager.ViewManager;
|
|
||||||
import com.facebook.react.bridge.JavaScriptModule;
|
|
||||||
|
|
||||||
public class ReactCameraManager extends SimpleViewManager<ReactCameraView> {
|
|
||||||
|
|
||||||
public static final String REACT_CLASS = "RCTCamera";
|
|
||||||
|
|
||||||
@UIProp(UIProp.Type.STRING)
|
|
||||||
public static final String PROP_SRC = "src";
|
|
||||||
@UIProp(UIProp.Type.NUMBER)
|
|
||||||
public static final String PROP_BORDER_RADIUS = "borderRadius";
|
|
||||||
@UIProp(UIProp.Type.STRING)
|
|
||||||
public static final String PROP_RESIZE_MODE = ViewProps.RESIZE_MODE;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return REACT_CLASS;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReactCameraView createViewInstance(ThemedReactContext context) {
|
|
||||||
return new ReactCameraView(context, Fresco.newDraweeControllerBuilder(), mCallerContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void updateView(final ReactImageView view, final CatalystStylesDiffMap props) {
|
|
||||||
super.updateView(view, props);
|
|
||||||
|
|
||||||
if (props.hasKey(PROP_RESIZE_MODE)) {
|
|
||||||
view.setScaleType(
|
|
||||||
ImageResizeMode.toScaleType(props.getString(PROP_RESIZE_MODE)));
|
|
||||||
}
|
|
||||||
if (props.hasKey(PROP_SRC)) {
|
|
||||||
view.setSource(props.getString(PROP_SRC));
|
|
||||||
}
|
|
||||||
if (props.hasKey(PROP_BORDER_RADIUS)) {
|
|
||||||
view.setBorderRadius(props.getFloat(PROP_BORDER_RADIUS, 0.0f));
|
|
||||||
}
|
|
||||||
view.maybeUpdateView();
|
|
||||||
}
|
|
||||||
}
|
|
213
index.android.js
213
index.android.js
@ -1,12 +1,207 @@
|
|||||||
var { requireNativeComponent, PropTypes } = require('react-native');
|
var React = require('react-native');
|
||||||
|
var { View, StyleSheet, requireNativeComponent, PropTypes, NativeModules, DeviceEventEmitter } = React;
|
||||||
|
|
||||||
var iface = {
|
var CAMERA_REF = 'camera';
|
||||||
name: 'ImageView',
|
|
||||||
propTypes: {
|
var constants = {
|
||||||
src: PropTypes.string,
|
Aspect: NativeModules.CameraModule.Aspect,
|
||||||
borderRadius: PropTypes.number,
|
BarCodeType: NativeModules.CameraModule.BarCodeType,
|
||||||
resizeMode: PropTypes.oneOf(['cover', 'contain', 'stretch']),
|
Type: NativeModules.CameraModule.Type,
|
||||||
},
|
CaptureMode: NativeModules.CameraModule.CaptureMode,
|
||||||
|
CaptureTarget: NativeModules.CameraModule.CaptureTarget,
|
||||||
|
Orientation: NativeModules.CameraModule.Orientation,
|
||||||
|
FlashMode: NativeModules.CameraModule.FlashMode,
|
||||||
|
TorchMode: NativeModules.CameraModule.TorchMode
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = requireNativeComponent('RCTCamera', iface);
|
var Camera = React.createClass({
|
||||||
|
propTypes: {
|
||||||
|
aspect: PropTypes.oneOfType([
|
||||||
|
PropTypes.string,
|
||||||
|
PropTypes.number
|
||||||
|
]),
|
||||||
|
captureAudio: PropTypes.bool,
|
||||||
|
captureMode: PropTypes.oneOfType([
|
||||||
|
PropTypes.string,
|
||||||
|
PropTypes.number
|
||||||
|
]),
|
||||||
|
captureTarget: PropTypes.oneOfType([
|
||||||
|
PropTypes.string,
|
||||||
|
PropTypes.number
|
||||||
|
]),
|
||||||
|
type: PropTypes.oneOfType([
|
||||||
|
PropTypes.string,
|
||||||
|
PropTypes.number
|
||||||
|
]),
|
||||||
|
orientation: PropTypes.oneOfType([
|
||||||
|
PropTypes.string,
|
||||||
|
PropTypes.number
|
||||||
|
]),
|
||||||
|
flashMode: PropTypes.oneOfType([
|
||||||
|
PropTypes.string,
|
||||||
|
PropTypes.number
|
||||||
|
]),
|
||||||
|
torchMode: PropTypes.oneOfType([
|
||||||
|
PropTypes.string,
|
||||||
|
PropTypes.number
|
||||||
|
]),
|
||||||
|
defaultOnFocusComponent: PropTypes.bool,
|
||||||
|
onFocusChanged: PropTypes.func,
|
||||||
|
onZoomChanged: PropTypes.func,
|
||||||
|
...View.propTypes
|
||||||
|
},
|
||||||
|
|
||||||
|
setNativeProps(props) {
|
||||||
|
this.refs[CAMERA_REF].setNativeProps(props);
|
||||||
|
},
|
||||||
|
|
||||||
|
getDefaultProps() {
|
||||||
|
return {
|
||||||
|
aspect: constants.Aspect.fill,
|
||||||
|
type: constants.Type.back,
|
||||||
|
orientation: constants.Orientation.auto,
|
||||||
|
captureAudio: true,
|
||||||
|
captureMode: constants.CaptureMode.still,
|
||||||
|
captureTarget: constants.CaptureTarget.cameraRoll,
|
||||||
|
flashMode: constants.FlashMode.off,
|
||||||
|
torchMode: constants.TorchMode.off
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
isAuthorized: false,
|
||||||
|
isRecording: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
componentWillMount() {
|
||||||
|
//// TODO: handle properly Android 6 new permissions style
|
||||||
|
this.state.isAuthorized = true;
|
||||||
|
this.setState(this.state);
|
||||||
|
this.cameraBarCodeReadListener = DeviceEventEmitter.addListener('CameraBarCodeRead', this._onBarCodeRead);
|
||||||
|
},
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
this.cameraBarCodeReadListener.remove();
|
||||||
|
|
||||||
|
if (this.state.isRecording) {
|
||||||
|
this.stopCapture();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
var style = [styles.base, this.props.style];
|
||||||
|
|
||||||
|
var aspect = this.props.aspect,
|
||||||
|
type = this.props.type,
|
||||||
|
orientation = this.props.orientation,
|
||||||
|
flashMode = this.props.flashMode,
|
||||||
|
torchMode = this.props.torchMode;
|
||||||
|
|
||||||
|
var legacyProps = {
|
||||||
|
aspect: {
|
||||||
|
Fill: 'fill',
|
||||||
|
Fit: 'fit',
|
||||||
|
Stretch: 'stretch'
|
||||||
|
},
|
||||||
|
orientation: {
|
||||||
|
LandscapeLeft: 'landscapeLeft',
|
||||||
|
LandscapeRight: 'landscapeRight',
|
||||||
|
Portrait: 'portrait',
|
||||||
|
PortraitUpsideDown: 'portraitUpsideDown'
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
Front: 'front',
|
||||||
|
Back: 'back'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof aspect === 'string') {
|
||||||
|
aspect = constants.Aspect[aspect];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof flashMode === 'string') {
|
||||||
|
flashMode = constants.FlashMode[flashMode];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof orientation === 'string') {
|
||||||
|
orientation = constants.Orientation[orientation];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof torchMode === 'string') {
|
||||||
|
torchMode = constants.TorchMode[torchMode];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof type === 'string') {
|
||||||
|
type = constants.Type[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
var nativeProps = Object.assign({}, this.props, {
|
||||||
|
style,
|
||||||
|
aspect: aspect,
|
||||||
|
type: type,
|
||||||
|
orientation: orientation,
|
||||||
|
flashMode: flashMode,
|
||||||
|
torchMode: torchMode
|
||||||
|
});
|
||||||
|
|
||||||
|
return <RCTCameraView ref={CAMERA_REF} {... nativeProps} />;
|
||||||
|
},
|
||||||
|
|
||||||
|
_onBarCodeRead(e) {
|
||||||
|
this.props.onBarCodeRead && this.props.onBarCodeRead(e);
|
||||||
|
},
|
||||||
|
|
||||||
|
capture(options, cb) {
|
||||||
|
|
||||||
|
if (arguments.length == 1) {
|
||||||
|
cb = options;
|
||||||
|
options = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
options = Object.assign({}, {
|
||||||
|
audio: this.props.captureAudio,
|
||||||
|
mode: this.props.captureMode,
|
||||||
|
target: this.props.captureTarget,
|
||||||
|
type: this.props.type
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
if (typeof options.mode === 'string') {
|
||||||
|
options.mode = constants.CaptureMode[options.mode];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.mode === constants.CaptureMode.video) {
|
||||||
|
options.totalSeconds = (options.totalSeconds > -1 ? options.totalSeconds : -1);
|
||||||
|
options.preferredTimeScale = options.preferredTimeScale || 30;
|
||||||
|
this.setState({isRecording: true});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof options.target === 'string') {
|
||||||
|
options.target = constants.CaptureTarget[options.target];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof options.type === 'string') {
|
||||||
|
options.type = constants.Type[options.type];
|
||||||
|
}
|
||||||
|
|
||||||
|
NativeModules.CameraModule.capture(options, cb);
|
||||||
|
},
|
||||||
|
|
||||||
|
stopCapture() {
|
||||||
|
if (this.state.isRecording) {
|
||||||
|
NativeModules.CameraManager.stopCapture();
|
||||||
|
this.setState({ isRecording: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var RCTCameraView = requireNativeComponent('RCTCameraView', Camera);
|
||||||
|
|
||||||
|
var styles = StyleSheet.create({
|
||||||
|
base: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
Camera.constants = constants;
|
||||||
|
module.exports = Camera;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user