package com.imagechooser; import android.app.Activity; import android.content.Intent; import android.database.Cursor; import android.graphics.BitmapFactory; import android.net.Uri; import android.provider.MediaStore; import android.provider.OpenableColumns; import android.support.annotation.Nullable; import android.support.v4.content.CursorLoader; import com.facebook.react.bridge.ActivityEventListener; import com.facebook.react.bridge.Arguments; 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 com.facebook.react.bridge.WritableMap; import java.io.File; public class ImageChooserModule extends ReactContextBaseJavaModule implements ActivityEventListener { private static final int PICK_IMAGE = 3500; private static final String ERR_PICKER_CANCELLED = "ERR_PICKER_CANCELLED"; private static final String ERR_FAILED_TO_PICK = "ERR_FAILED_TO_PICK"; private Promise mPickerPromise; public ImageChooserModule(ReactApplicationContext reactContext) { super(reactContext); reactContext.addActivityEventListener(this); } @Override public String getName() { return "ImageChooserModule"; } private void resolvePromise(WritableMap map) { if (mPickerPromise != null) { mPickerPromise.resolve(map); mPickerPromise = null; } } private void rejectPromise(String code, String reason) { if (mPickerPromise != null) { mPickerPromise.reject(code, reason); mPickerPromise = null; } } private void rejectPromise(Exception reason) { if (mPickerPromise != null) { mPickerPromise.reject(reason); mPickerPromise = null; } } @Nullable private String getPathFromUri(Uri contentUri) { if (contentUri.getScheme().equals("file")) { return contentUri.getPath(); } String[] projection = {MediaStore.Images.Media.DATA}; CursorLoader loader = new CursorLoader(getReactApplicationContext(), contentUri, projection, null, null, null); Cursor cursor = loader.loadInBackground(); try { int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); cursor.moveToFirst(); return cursor.getString(column_index); } catch (RuntimeException e) { return null; } finally { cursor.close(); } } private String getNameFromUri(Uri contentUri) { if (contentUri.getScheme().equals("file")) { return contentUri.getLastPathSegment(); } String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME}; Cursor metaCursor = getReactApplicationContext().getContentResolver().query(contentUri, projection, null, null, null); if (metaCursor != null) { try { if (metaCursor.moveToFirst()) { return metaCursor.getString(0); } } finally { metaCursor.close(); } } return contentUri.getLastPathSegment(); } private long getSizeFromUri(Uri contentUri) { if (contentUri.getScheme().equals("file")) { return new File(contentUri.getPath()).length(); } Cursor cursor = getReactApplicationContext().getContentResolver().query(contentUri, null, null, null, null); if (cursor != null) { cursor.moveToFirst(); long size = cursor.getLong(cursor.getColumnIndex(OpenableColumns.SIZE)); cursor.close(); return size; } return 0; } @Nullable private WritableMap getImageData(@Nullable Uri uri) { if (uri == null) { return null; } BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; String path = getPathFromUri(uri); if (path != null) { BitmapFactory.decodeFile(path, options); WritableMap map = Arguments.createMap(); map.putInt("height", options.outHeight); map.putInt("width", options.outWidth); map.putDouble("size", getSizeFromUri(uri)); map.putString("name", getNameFromUri(uri)); map.putString("uri", uri.toString()); return map; } else { return null; } } @ReactMethod public void pickImage(final Promise promise) { Activity currentActivity = getCurrentActivity(); if (currentActivity != null) { mPickerPromise = promise; } else { promise.reject("Activity doesn't exist"); return; } try { final Intent galleryIntent = new Intent(Intent.ACTION_PICK); galleryIntent.setType("image/*"); final Intent chooserIntent = Intent.createChooser(galleryIntent, "Pick an image"); currentActivity.startActivityForResult(chooserIntent, PICK_IMAGE); } catch (Exception e) { promise.reject(e); } } @Override public void onNewIntent(final Intent Intent) { } @Override public void onActivityResult(final Activity activity, final int requestCode, final int resultCode, final Intent intent) { if (requestCode == PICK_IMAGE) { if (mPickerPromise != null) { if (resultCode == Activity.RESULT_CANCELED) { rejectPromise(ERR_PICKER_CANCELLED, "Image picker was cancelled"); } else if (resultCode == Activity.RESULT_OK) { try { Uri uri = intent.getData(); WritableMap map = getImageData(uri); if (map != null) { resolvePromise(map); } else { rejectPromise(ERR_FAILED_TO_PICK, "Failed to pick image: " + uri); } } catch (Exception e) { rejectPromise(e); } } } } } }