diff --git a/android/src/main/java/com/reactnative/picker/PickerModule.java b/android/src/main/java/com/reactnative/picker/PickerModule.java index efefe09..07cc533 100644 --- a/android/src/main/java/com/reactnative/picker/PickerModule.java +++ b/android/src/main/java/com/reactnative/picker/PickerModule.java @@ -12,6 +12,8 @@ import android.os.Build; import android.provider.DocumentsContract; import android.provider.MediaStore; import android.util.Base64; +import android.Manifest; +import android.os.Environment; import com.facebook.react.bridge.ActivityEventListener; import com.facebook.react.bridge.Promise; @@ -23,6 +25,9 @@ import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableNativeArray; import com.facebook.react.bridge.WritableNativeMap; +import android.support.v4.app.ActivityCompat; +import android.content.pm.PackageManager; + import com.yalantis.ucrop.UCrop; import java.io.File; @@ -40,13 +45,17 @@ import java.io.IOException; public class PickerModule extends ReactContextBaseJavaModule implements ActivityEventListener { private static final int IMAGE_PICKER_REQUEST = 1; + private static final int CAMERA_PICKER_REQUEST = 2; private static final String E_ACTIVITY_DOES_NOT_EXIST = "E_ACTIVITY_DOES_NOT_EXIST"; private static final String E_PICKER_CANCELLED_KEY = "picker_cancel"; private static final String E_PICKER_CANCELLED_MSG = "User cancelled image selection"; private static final String E_FAILED_TO_SHOW_PICKER = "E_FAILED_TO_SHOW_PICKER"; + private static final String E_FAILED_TO_OPEN_CAMERA = "E_FALIED_TO_OPEN_CAMERA"; private static final String E_NO_IMAGE_DATA_FOUND = "E_NO_IMAGE_DATA_FOUND"; + private static final String E_CAMERA_IS_NOT_AVAILABLE = "E_CAMERA_IS_NOT_AVAILABLE"; + private static final String E_CANNOT_LAUNCH_CAMERA = "CANNOT_LAUNCH_CAMERA"; private Promise mPickerPromise; private Activity activity; @@ -56,10 +65,14 @@ public class PickerModule extends ReactContextBaseJavaModule implements Activity private boolean includeBase64 = false; private int width = 100; private int height = 100; + private Boolean tmpImage; + private final ReactApplicationContext mReactContext; + private Uri mCameraCaptureURI; public PickerModule(ReactApplicationContext reactContext) { super(reactContext); reactContext.addActivityEventListener(this); + mReactContext = reactContext; } @Override @@ -67,6 +80,54 @@ public class PickerModule extends ReactContextBaseJavaModule implements Activity return "ImageCropPicker"; } + @ReactMethod + public void openCamera(final ReadableMap options, final Promise promise) { + int requestCode = CAMERA_PICKER_REQUEST; + Intent cameraIntent; + + if (!isCameraAvailable()) { + promise.reject(E_CAMERA_IS_NOT_AVAILABLE, "Camera not available"); + return; + } + + activity = getCurrentActivity(); + + if (activity == null) { + promise.reject(E_ACTIVITY_DOES_NOT_EXIST, "Activity doesn't exist"); + return; + } + + if (!permissionsCheck(activity)) { + return; + } + + multiple = options.hasKey("multiple") && options.getBoolean("multiple"); + width = options.hasKey("width") ? options.getInt("width") : width; + height = options.hasKey("height") ? options.getInt("height") : height; + cropping = options.hasKey("cropping") ? options.getBoolean("cropping") : cropping; + + mPickerPromise = promise; + + try { + cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + tmpImage = true; + // we create a tmp file to save the result + File imageFile = createNewFile(true); + mCameraCaptureURI = Uri.fromFile(imageFile); + + cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, mCameraCaptureURI); + if (cameraIntent.resolveActivity(mReactContext.getPackageManager()) == null) { + promise.reject(E_CANNOT_LAUNCH_CAMERA, "Cannot launch camera"); + return; + } + activity.startActivityForResult(cameraIntent, requestCode); + } catch (Exception e) { + mPickerPromise.reject(E_FAILED_TO_OPEN_CAMERA, e); + mPickerPromise = null; + } + + } + @ReactMethod public void openPicker(final ReadableMap options, final Promise promise) { activity = getCurrentActivity(); @@ -198,6 +259,29 @@ public class PickerModule extends ReactContextBaseJavaModule implements Activity } } } + } else if (requestCode == CAMERA_PICKER_REQUEST) { + if (mPickerPromise != null) { + if (resultCode == Activity.RESULT_CANCELED) { + mPickerPromise.reject(E_PICKER_CANCELLED_KEY, E_PICKER_CANCELLED_MSG); + } else if (resultCode == Activity.RESULT_OK && mCameraCaptureURI != null) { + Uri uri = mCameraCaptureURI; + + if (cropping) { + UCrop.Options options = new UCrop.Options(); + options.setCompressionFormat(Bitmap.CompressFormat.JPEG); + + + UCrop.of(uri, Uri.fromFile(new File(activity.getCacheDir(), UUID.randomUUID().toString() + ".jpg"))) + .withMaxResultSize(width, height) + .withAspectRatio(width, height) + .withOptions(options) + .start(activity); + } else { + mPickerPromise.resolve(getImage(uri, true)); + mPickerPromise = null; + } + } + } } else if (requestCode == UCrop.REQUEST_CROP) { if (data != null) { final Uri resultUri = UCrop.getOutput(data); @@ -217,4 +301,42 @@ public class PickerModule extends ReactContextBaseJavaModule implements Activity @Override public void onNewIntent(Intent intent) { } + + private boolean permissionsCheck(Activity activity) { + int writePermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE); + int cameraPermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.CAMERA); + if (writePermission != PackageManager.PERMISSION_GRANTED || cameraPermission != PackageManager.PERMISSION_GRANTED) { + String[] PERMISSIONS = { + Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.CAMERA + }; + ActivityCompat.requestPermissions(activity, PERMISSIONS, 1); + return false; + } + return true; + } + + private boolean isCameraAvailable() { + return mReactContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA) + || mReactContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY); + } + + private File createNewFile(final boolean forcePictureDirectory) { + String filename = "image-" + UUID.randomUUID().toString() + ".jpg"; + if (tmpImage && forcePictureDirectory != true) { + return new File(mReactContext.getCacheDir(), filename); + } else { + File path = Environment.getExternalStoragePublicDirectory( + Environment.DIRECTORY_PICTURES); + File f = new File(path, filename); + + try { + path.mkdirs(); + f.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + return f; + } + } }