Android Camera component

This commit is contained in:
Yedidya Kennard 2016-07-04 14:10:21 +03:00
parent bbb960b7ac
commit 6735b84d43
13 changed files with 363 additions and 15 deletions

View File

@ -1,3 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.wix.RNCameraKit">
<uses-permission android:name="android.permission.CAMERA" />
</manifest>

View File

@ -5,6 +5,10 @@ import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import com.wix.RNCameraKit.camera.CameraModule;
import com.wix.RNCameraKit.camera.CameraViewManager;
import com.wix.RNCameraKit.gallery.GalleryViewManager;
import com.wix.RNCameraKit.gallery.NativeGalleryModule;
import java.util.ArrayList;
import java.util.Collections;
@ -16,6 +20,7 @@ public class RNCameraKitPackage implements ReactPackage {
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
List<NativeModule> modules = new ArrayList<>();
modules.add(new NativeGalleryModule(reactContext));
modules.add(new CameraModule(reactContext));
return modules;
}
@ -28,6 +33,7 @@ public class RNCameraKitPackage implements ReactPackage {
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
List<ViewManager> viewManagers = new ArrayList<>();
viewManagers.add(new GalleryViewManager());
viewManagers.add(new CameraViewManager());
return viewManagers;
}

View File

@ -0,0 +1,104 @@
package com.wix.RNCameraKit.camera;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.hardware.Camera;
import android.os.AsyncTask;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* Created by yedidyak on 04/07/2016.
*/
public class CameraModule extends ReactContextBaseJavaModule {
public CameraModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "CameraModule";
}
@ReactMethod
public void hasFrontCamera(Promise promise) {
int numCameras = Camera.getNumberOfCameras();
for (int i=0; i<numCameras; i++) {
Camera.CameraInfo info = new Camera.CameraInfo();
Camera.getCameraInfo(i, info);
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
promise.resolve(true);
return;
}
}
promise.resolve(false);
}
@ReactMethod
public void hasFlashForCurrentCamera(Promise promise) {
Camera camera = CameraView.instance.getCamera();
promise.resolve(camera.getParameters().getSupportedFlashModes() != null);
}
@ReactMethod
public void changeCamera(Promise promise) {
promise.resolve(CameraView.instance.changeCamera());
}
@ReactMethod
public void setFlashMode(String mode, Promise promise) {
promise.resolve(CameraView.instance.setFlashMode(mode));
}
@ReactMethod
public void getFlashMode(Promise promise) {
Camera camera = CameraView.instance.getCamera();
promise.resolve(camera.getParameters().getFlashMode());
}
@ReactMethod void capture(boolean saveToCameraRoll, final Promise promise) {
Camera camera = CameraView.instance.getCamera();
camera.takePicture(null, null, new Camera.PictureCallback(){
@Override
public void onPictureTaken(byte[] data, Camera camera) {
new SaveImageTask(promise).execute(data);
}
});
}
private class SaveImageTask extends AsyncTask<byte[], Void, Void> {
private final Promise promise;
private SaveImageTask(Promise promise) {
this.promise = promise;
}
@Override
protected Void doInBackground(byte[]... data) {
Bitmap image = BitmapFactory.decodeByteArray(data[0], 0, data[0].length);
String fileUri = MediaStore.Images.Media.insertImage(getReactApplicationContext().getContentResolver(), image, System.currentTimeMillis() + "", "");
Log.d("CameraKit", "Saved to: " + fileUri);
if (fileUri == null) {
promise.reject("CameraKit", "Failed to save image to mediastore");
} else {
promise.resolve(fileUri);
}
return null;
}
}
}

View File

@ -0,0 +1,178 @@
package com.wix.RNCameraKit.camera;
import android.app.Activity;
import android.hardware.Camera;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import com.facebook.react.uimanager.ThemedReactContext;
import java.io.IOException;
import java.util.List;
/**
* Created by yedidyak on 04/07/2016.
*/
public class CameraView extends SurfaceView implements SurfaceHolder.Callback {
private ThemedReactContext context;
private Camera camera;
private String flashMode = Camera.Parameters.FLASH_MODE_AUTO;
public static CameraView instance;
private int currentCamera = 0;
private Camera.Size optimalSize;
private Camera.Size optimalPictureSize;
public CameraView(ThemedReactContext context) {
super(context);
instance = this;
this.context = context;
this.getHolder().addCallback(this);
this.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
CameraView.this.camera.autoFocus(new Camera.AutoFocusCallback() {
@Override
public void onAutoFocus(boolean success, Camera camera) {
}
});
}
});
}
public boolean changeCamera() {
if (Camera.getNumberOfCameras() == 1) {
return false;
}
currentCamera++;
currentCamera = currentCamera % Camera.getNumberOfCameras();
camera.release();
initCamera();
return true;
}
private void initCamera() {
this.camera = Camera.open(currentCamera);
try {
camera.setPreviewDisplay(this.getHolder());
updateCameraSize();
camera.startPreview();
setCameraDisplayOrientation(((Activity)context.getBaseContext()), 0, camera);
} catch (IOException e) {
}
}
private void updateCameraSize() {
List<Camera.Size> supportedPreviewSizes = camera.getParameters().getSupportedPreviewSizes();
List<Camera.Size> supportedPictureSizes = camera.getParameters().getSupportedPictureSizes();
optimalSize = getOptimalPreviewSize(supportedPreviewSizes, getWidth(), getHeight());
optimalPictureSize = getOptimalPreviewSize(supportedPictureSizes, getWidth(), getHeight());
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(optimalSize.width, optimalSize.height);
parameters.setPictureSize(optimalPictureSize.width, optimalPictureSize.height);
parameters.setFlashMode(flashMode);
camera.setParameters(parameters);
camera.startPreview();
}
public static void setCameraDisplayOrientation(Activity activity, int cameraId, android.hardware.Camera camera) {
android.hardware.Camera.CameraInfo info =
new android.hardware.Camera.CameraInfo();
android.hardware.Camera.getCameraInfo(cameraId, info);
int rotation = activity.getWindowManager().getDefaultDisplay()
.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0:
degrees = 0;
break;
case Surface.ROTATION_90:
degrees = 90;
break;
case Surface.ROTATION_180:
degrees = 180;
break;
case Surface.ROTATION_270:
degrees = 270;
break;
}
int result;
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
camera.setDisplayOrientation(result);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
initCamera();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
updateCameraSize();
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.release();
}
public Camera getCamera() {
return camera;
}
private static Camera.Size getOptimalPreviewSize(List<Camera.Size> sizes, int w, int h) {
final double ASPECT_TOLERANCE = 0.1;
double targetRatio=(double)h / w;
if (sizes == null) return null;
Camera.Size optimalSize = null;
double minDiff = Double.MAX_VALUE;
int targetHeight = h;
for (Camera.Size size : sizes) {
double ratio = (double) size.width / size.height;
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE) continue;
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
if (optimalSize == null) {
minDiff = Double.MAX_VALUE;
for (Camera.Size size : sizes) {
if (Math.abs(size.height - targetHeight) < minDiff) {
optimalSize = size;
minDiff = Math.abs(size.height - targetHeight);
}
}
}
return optimalSize;
}
public boolean setFlashMode(String mode) {
Camera.Parameters parameters = camera.getParameters();
if(parameters.getSupportedFlashModes().contains(mode)) {
flashMode = mode;
parameters.setFlashMode(flashMode);
camera.setParameters(parameters);
camera.startPreview();
return true;
} else {
return false;
}
}
}

View File

@ -0,0 +1,21 @@
package com.wix.RNCameraKit.camera;
import com.facebook.react.uimanager.SimpleViewManager;
import com.facebook.react.uimanager.ThemedReactContext;
/**
* Created by yedidyak on 04/07/2016.
*/
public class CameraViewManager extends SimpleViewManager<CameraView> {
@Override
public String getName() {
return "CameraView";
}
@Override
protected CameraView createViewInstance(ThemedReactContext reactContext) {
return new CameraView(reactContext);
}
}

View File

@ -1,7 +1,6 @@
package com.wix.RNCameraKit;
package com.wix.RNCameraKit.gallery;
import android.app.Activity;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Color;

View File

@ -1,4 +1,4 @@
package com.wix.RNCameraKit;
package com.wix.RNCameraKit.gallery;
import android.content.Context;
import android.graphics.Rect;

View File

@ -1,4 +1,4 @@
package com.wix.RNCameraKit;
package com.wix.RNCameraKit.gallery;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.uimanager.SimpleViewManager;

View File

@ -1,4 +1,4 @@
package com.wix.RNCameraKit;
package com.wix.RNCameraKit.gallery;
import android.database.Cursor;
import android.graphics.Bitmap;
@ -12,6 +12,7 @@ import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableArray;
import com.facebook.react.bridge.WritableMap;
import com.wix.RNCameraKit.Utils;
import java.util.Collection;
import java.util.HashMap;

View File

@ -1,4 +1,4 @@
package com.wix.RNCameraKit;
package com.wix.RNCameraKit.gallery;
import android.content.Context;
import android.graphics.Bitmap;

View File

@ -1,10 +1,10 @@
import CameraKitGallery from './src/CameraKitGallery';
//import CameraKitCamera from './src/CameraKitCamera';
import CameraKitCamera from './src/CameraKitCamera';
import CameraKitGalleryView from './src/CameraKitGalleryView';
export {
CameraKitGallery,
//CameraKitCamera,
CameraKitCamera,
CameraKitGalleryView
};

View File

@ -0,0 +1,42 @@
import React, {Component} from 'react';
import {
requireNativeComponent,
NativeModules
} from 'react-native';
const NativeCamera = requireNativeComponent('CameraView', null);
const NativeCameraModule = NativeModules.CameraModule;
export default class CameraKitCamera extends React.Component {
render() {
return <NativeCamera {...this.props}/>
}
async logData() {
console.log('front Camera?', await NativeCameraModule.hasFrontCamera());
console.log('hasFlash?', await NativeCameraModule.hasFlashForCurrentCamera());
console.log('flashMode?', await NativeCameraModule.getFlashMode());
}
//static async checkDeviceAuthorizarionStatus() {
// const deviceAutorizationStatus = await NativeCameraAction.checkDeviceAuthorizationStatus();
//
// return deviceAutorizationStatus;
//}
//
async capture(saveToCameraRoll = true) {
const imageTmpPath = await NativeCameraModule.capture(saveToCameraRoll);
return imageTmpPath;
}
async changeCamera() {
const success = await NativeCameraModule.changeCamera();
return success;
}
//
async setFlashMode(flashMode = 'auto') {
const success = await NativeCameraModule.setFlashMode(flashMode);
return success;
}
}

View File

@ -7,12 +7,6 @@ async function getAlbumsWithThumbnails() {
return albums;
}
async function getPhotosForAlbum(albumName, numberOfPhotos) {
}
export default {
getAlbumsWithThumbnails,
getPhotosForAlbum
getAlbumsWithThumbnails
}