mirror of
https://github.com/status-im/react-native-camera-kit.git
synced 2025-02-28 15:40:47 +00:00
Android Camera component
This commit is contained in:
parent
bbb960b7ac
commit
6735b84d43
@ -1,3 +1,6 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.wix.RNCameraKit">
|
package="com.wix.RNCameraKit">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.CAMERA" />
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
@ -5,6 +5,10 @@ import com.facebook.react.bridge.JavaScriptModule;
|
|||||||
import com.facebook.react.bridge.NativeModule;
|
import com.facebook.react.bridge.NativeModule;
|
||||||
import com.facebook.react.bridge.ReactApplicationContext;
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
import com.facebook.react.uimanager.ViewManager;
|
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.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -16,6 +20,7 @@ public class RNCameraKitPackage implements ReactPackage {
|
|||||||
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
|
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
|
||||||
List<NativeModule> modules = new ArrayList<>();
|
List<NativeModule> modules = new ArrayList<>();
|
||||||
modules.add(new NativeGalleryModule(reactContext));
|
modules.add(new NativeGalleryModule(reactContext));
|
||||||
|
modules.add(new CameraModule(reactContext));
|
||||||
return modules;
|
return modules;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -28,6 +33,7 @@ public class RNCameraKitPackage implements ReactPackage {
|
|||||||
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
||||||
List<ViewManager> viewManagers = new ArrayList<>();
|
List<ViewManager> viewManagers = new ArrayList<>();
|
||||||
viewManagers.add(new GalleryViewManager());
|
viewManagers.add(new GalleryViewManager());
|
||||||
|
viewManagers.add(new CameraViewManager());
|
||||||
return viewManagers;
|
return viewManagers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
178
android/src/main/java/com/wix/RNCameraKit/camera/CameraView.java
Normal file
178
android/src/main/java/com/wix/RNCameraKit/camera/CameraView.java
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package com.wix.RNCameraKit;
|
package com.wix.RNCameraKit.gallery;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
@ -1,4 +1,4 @@
|
|||||||
package com.wix.RNCameraKit;
|
package com.wix.RNCameraKit.gallery;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
@ -1,4 +1,4 @@
|
|||||||
package com.wix.RNCameraKit;
|
package com.wix.RNCameraKit.gallery;
|
||||||
|
|
||||||
import com.facebook.react.bridge.ReadableArray;
|
import com.facebook.react.bridge.ReadableArray;
|
||||||
import com.facebook.react.uimanager.SimpleViewManager;
|
import com.facebook.react.uimanager.SimpleViewManager;
|
@ -1,4 +1,4 @@
|
|||||||
package com.wix.RNCameraKit;
|
package com.wix.RNCameraKit.gallery;
|
||||||
|
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Bitmap;
|
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.ReactMethod;
|
||||||
import com.facebook.react.bridge.WritableArray;
|
import com.facebook.react.bridge.WritableArray;
|
||||||
import com.facebook.react.bridge.WritableMap;
|
import com.facebook.react.bridge.WritableMap;
|
||||||
|
import com.wix.RNCameraKit.Utils;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
@ -1,4 +1,4 @@
|
|||||||
package com.wix.RNCameraKit;
|
package com.wix.RNCameraKit.gallery;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
@ -1,10 +1,10 @@
|
|||||||
import CameraKitGallery from './src/CameraKitGallery';
|
import CameraKitGallery from './src/CameraKitGallery';
|
||||||
//import CameraKitCamera from './src/CameraKitCamera';
|
import CameraKitCamera from './src/CameraKitCamera';
|
||||||
import CameraKitGalleryView from './src/CameraKitGalleryView';
|
import CameraKitGalleryView from './src/CameraKitGalleryView';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
CameraKitGallery,
|
CameraKitGallery,
|
||||||
//CameraKitCamera,
|
CameraKitCamera,
|
||||||
CameraKitGalleryView
|
CameraKitGalleryView
|
||||||
};
|
};
|
||||||
|
|
||||||
|
42
src/CameraKitCamera.android.js
Normal file
42
src/CameraKitCamera.android.js
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -7,12 +7,6 @@ async function getAlbumsWithThumbnails() {
|
|||||||
return albums;
|
return albums;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async function getPhotosForAlbum(albumName, numberOfPhotos) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
getAlbumsWithThumbnails,
|
getAlbumsWithThumbnails
|
||||||
getPhotosForAlbum
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user