mirror of
https://github.com/status-im/react-native-camera.git
synced 2026-08-31 05:31:07 +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:
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user