Fix Option to capture and share video (#2225)

This commit is contained in:
Elias Nahum
2018-10-05 17:46:47 -03:00
parent faa3a55b3d
commit b3ec19fe17
8 changed files with 37 additions and 753 deletions

View File

@@ -61,9 +61,6 @@ clean: ## Cleans dependencies, previous builds and temp files
@echo Cleanup finished
post-install:
@# Need to copy custom ImagePickerModule.java that implements correct permission checks for android
@rm node_modules/react-native-image-picker/android/src/main/java/com/imagepicker/ImagePickerModule.java
@cp ./native_modules/ImagePickerModule.java node_modules/react-native-image-picker/android/src/main/java/com/imagepicker
@# Need to copy custom RNDocumentPicker.m that implements direct access to the document picker in iOS
@cp ./native_modules/RNDocumentPicker.m node_modules/react-native-document-picker/ios/RNDocumentPicker/RNDocumentPicker.m

View File

@@ -42,11 +42,17 @@ export default class AttachmentButton extends PureComponent {
intl: intlShape.isRequired,
};
attachFileFromCamera = async () => {
attachPhotoFromCamera = () => {
return this.attachFileFromCamera('photo');
};
attachFileFromCamera = async (mediaType) => {
const {formatMessage} = this.context.intl;
const options = {
quality: 1.0,
quality: 1,
videoQuality: 'high',
noData: true,
mediaType,
storageOptions: {
cameraRoll: true,
waitUntilSaved: true,
@@ -84,7 +90,7 @@ export default class AttachmentButton extends PureComponent {
attachFileFromLibrary = () => {
const {formatMessage} = this.context.intl;
const options = {
quality: 1.0,
quality: 1,
noData: true,
permissionDenied: {
title: formatMessage({
@@ -116,10 +122,14 @@ export default class AttachmentButton extends PureComponent {
});
};
attachVideoFromCamera = () => {
return this.attachFileFromCamera('video');
};
attachVideoFromLibraryAndroid = () => {
const {formatMessage} = this.context.intl;
const options = {
quality: 1.0,
videoQuality: 'high',
mediaType: 'video',
noData: true,
permissionDenied: {
@@ -313,12 +323,19 @@ export default class AttachmentButton extends PureComponent {
this.props.blurTextBox();
const options = {
items: [{
action: () => this.handleFileAttachmentOption(this.attachFileFromCamera),
action: () => this.handleFileAttachmentOption(this.attachPhotoFromCamera),
text: {
id: t('mobile.file_upload.camera'),
defaultMessage: 'Take Photo or Video',
id: t('mobile.file_upload.camera_photo'),
defaultMessage: 'Take Photo',
},
icon: 'camera',
}, {
action: () => this.handleFileAttachmentOption(this.attachVideoFromCamera),
text: {
id: t('mobile.file_upload.camera_video'),
defaultMessage: 'Take Video',
},
icon: 'video-camera',
}, {
action: () => this.handleFileAttachmentOption(this.attachFileFromLibrary),
text: {

View File

@@ -235,7 +235,8 @@
"mobile.failed_network_action.shortDescription": "Make sure you have an active connection and try again.",
"mobile.failed_network_action.title": "No internet connection",
"mobile.file_upload.browse": "Browse Files",
"mobile.file_upload.camera": "Take Photo or Video",
"mobile.file_upload.camera_photo": "Take Photo",
"mobile.file_upload.camera_video": "Take Video",
"mobile.file_upload.library": "Photo Library",
"mobile.file_upload.max_warning": "Uploads limited to 5 files maximum.",
"mobile.file_upload.video": "Video Library",

View File

@@ -5,6 +5,7 @@
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; };
00C302E71ABCBA2D00DB3ED1 /* libRCTGeolocation.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302BA1ABCB90400DB3ED1 /* libRCTGeolocation.a */; };
@@ -1043,7 +1044,6 @@
EE3EE4548D3F4A49B1274722 /* libRNLocalAuth.a */,
17A75F5A3D0D4A4A995DCD76 /* libRNPasscodeStatus.a */,
77810F0A063349439B0D8B6B /* libJailMonkey.a */,
0C0C75A424714EAC8E876A8F /* libFastImage.a */,
4B19E38FBCB94C57BB03B8E6 /* libRNFetchBlob.a */,
4A22BC320BA04E18A7F2A4E6 /* libReactNativeExceptionHandler.a */,
2AE23B96BF7545B9A77C0C87 /* libRNSentry.a */,
@@ -2376,9 +2376,7 @@
INFOPLIST_FILE = MattermostTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",
@@ -2405,9 +2403,7 @@
INFOPLIST_FILE = MattermostTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
);
LIBRARY_SEARCH_PATHS = "$(inherited)";
OTHER_LDFLAGS = (
"$(inherited)",
"-ObjC",

View File

@@ -62,10 +62,12 @@
<string>Share contacts in your Mattermost instance</string>
<key>NSCameraUsageDescription</key>
<string>Take a Photo or Video and upload it to your mattermost instance</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Send your current location to your Mattermost instance</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Send your current location to your Mattermost instance</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Send your current location to your Mattermost instance</string>
<key>NSMicrophoneUsageDescription</key>
<string>Capture audio when recording a video to share to your Mattermost instance</string>
<key>NSMotionUsageDescription</key>
<string>Share your route in your Mattermost instance</string>
<key>NSPhotoLibraryUsageDescription</key>

View File

@@ -1,729 +0,0 @@
package com.imagepicker;
import android.Manifest;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.provider.Settings;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StyleRes;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils;
import android.util.Base64;
import android.util.Patterns;
import android.webkit.MimeTypeMap;
import android.content.pm.PackageManager;
import com.facebook.react.ReactActivity;
import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.imagepicker.media.ImageConfig;
import com.imagepicker.permissions.PermissionUtils;
import com.imagepicker.permissions.OnImagePickerPermissionsCallback;
import com.imagepicker.utils.MediaUtils.ReadExifResult;
import com.imagepicker.utils.RealPathUtil;
import com.imagepicker.utils.UI;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.util.List;
import com.facebook.react.modules.core.PermissionListener;
import com.facebook.react.modules.core.PermissionAwareActivity;
import static com.imagepicker.utils.MediaUtils.*;
import static com.imagepicker.utils.MediaUtils.createNewFile;
import static com.imagepicker.utils.MediaUtils.getResizedImage;
public class ImagePickerModule extends ReactContextBaseJavaModule
implements ActivityEventListener
{
public static final int REQUEST_LAUNCH_IMAGE_CAPTURE = 13001;
public static final int REQUEST_LAUNCH_IMAGE_LIBRARY = 13002;
public static final int REQUEST_LAUNCH_VIDEO_LIBRARY = 13003;
public static final int REQUEST_LAUNCH_VIDEO_CAPTURE = 13004;
public static final int REQUEST_PERMISSIONS_FOR_CAMERA = 14001;
public static final int REQUEST_PERMISSIONS_FOR_LIBRARY = 14002;
private final ReactApplicationContext reactContext;
private final int dialogThemeId;
protected Callback callback;
private ReadableMap options;
protected Uri cameraCaptureURI;
private Boolean noData = false;
private Boolean pickVideo = false;
private ImageConfig imageConfig = new ImageConfig(null, null, 0, 0, 100, 0, false);
@Deprecated
private int videoQuality = 1;
@Deprecated
private int videoDurationLimit = 0;
private ResponseHelper responseHelper = new ResponseHelper();
private PermissionListener listener = new PermissionListener()
{
public boolean onRequestPermissionsResult(final int requestCode,
@NonNull final String[] permissions,
@NonNull final int[] grantResults)
{
boolean permissionsGranted = true;
for (int i = 0; i < permissions.length; i++)
{
final boolean granted = grantResults[i] == PackageManager.PERMISSION_GRANTED;
permissionsGranted = permissionsGranted && granted;
}
if (callback == null || options == null)
{
return false;
}
if (!permissionsGranted)
{
responseHelper.invokeError(callback, "Permissions weren't granted");
return false;
}
switch (requestCode)
{
case REQUEST_PERMISSIONS_FOR_CAMERA:
launchCamera(options, callback);
break;
case REQUEST_PERMISSIONS_FOR_LIBRARY:
launchImageLibrary(options, callback);
break;
}
return true;
}
};
public ImagePickerModule(ReactApplicationContext reactContext,
@StyleRes final int dialogThemeId)
{
super(reactContext);
this.dialogThemeId = dialogThemeId;
this.reactContext = reactContext;
this.reactContext.addActivityEventListener(this);
}
@Override
public String getName() {
return "ImagePickerManager";
}
@ReactMethod
public void showImagePicker(final ReadableMap options, final Callback callback) {
Activity currentActivity = getCurrentActivity();
if (currentActivity == null)
{
responseHelper.invokeError(callback, "can't find current Activity");
return;
}
this.callback = callback;
this.options = options;
imageConfig = new ImageConfig(null, null, 0, 0, 100, 0, false);
final AlertDialog dialog = UI.chooseDialog(this, options, new UI.OnAction()
{
@Override
public void onTakePhoto(@NonNull final ImagePickerModule module)
{
if (module == null)
{
return;
}
module.launchCamera();
}
@Override
public void onUseLibrary(@NonNull final ImagePickerModule module)
{
if (module == null)
{
return;
}
module.launchImageLibrary();
}
@Override
public void onCancel(@NonNull final ImagePickerModule module)
{
if (module == null)
{
return;
}
module.doOnCancel();
}
@Override
public void onCustomButton(@NonNull final ImagePickerModule module,
@NonNull final String action)
{
if (module == null)
{
return;
}
module.invokeCustomButton(action);
}
});
dialog.show();
}
public void doOnCancel()
{
if (this.callback != null) {
responseHelper.invokeCancel(this.callback);
}
}
public void launchCamera()
{
this.launchCamera(this.options, this.callback);
}
// NOTE: Currently not reentrant / doesn't support concurrent requests
@ReactMethod
public void launchCamera(final ReadableMap options, final Callback callback)
{
if (!isCameraAvailable())
{
responseHelper.invokeError(callback, "Camera not available");
return;
}
final Activity currentActivity = getCurrentActivity();
if (currentActivity == null)
{
responseHelper.invokeError(callback, "can't find current Activity");
return;
}
this.callback = callback;
this.options = options;
if (!permissionsCheck(currentActivity, callback, REQUEST_PERMISSIONS_FOR_CAMERA))
{
return;
}
parseOptions(this.options);
int requestCode;
Intent cameraIntent;
if (pickVideo)
{
requestCode = REQUEST_LAUNCH_VIDEO_CAPTURE;
cameraIntent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, videoQuality);
if (videoDurationLimit > 0)
{
cameraIntent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, videoDurationLimit);
}
}
else
{
requestCode = REQUEST_LAUNCH_IMAGE_CAPTURE;
cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
final File original = createNewFile(reactContext, this.options, false);
imageConfig = imageConfig.withOriginalFile(original);
if (imageConfig.original != null) {
cameraCaptureURI = RealPathUtil.compatUriFromFile(reactContext, imageConfig.original);
}else {
responseHelper.invokeError(callback, "Couldn't get file path for photo");
return;
}
if (cameraCaptureURI == null)
{
responseHelper.invokeError(callback, "Couldn't get file path for photo");
return;
}
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, cameraCaptureURI);
}
if (cameraIntent.resolveActivity(reactContext.getPackageManager()) == null)
{
responseHelper.invokeError(callback, "Cannot launch camera");
return;
}
// Workaround for Android bug.
// grantUriPermission also needed for KITKAT,
// see https://code.google.com/p/android/issues/detail?id=76683
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
List<ResolveInfo> resInfoList = reactContext.getPackageManager().queryIntentActivities(cameraIntent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolveInfo : resInfoList) {
String packageName = resolveInfo.activityInfo.packageName;
reactContext.grantUriPermission(packageName, cameraCaptureURI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
}
try
{
currentActivity.startActivityForResult(cameraIntent, requestCode);
}
catch (ActivityNotFoundException e)
{
e.printStackTrace();
responseHelper.invokeError(callback, "Cannot launch camera");
}
}
public void launchImageLibrary()
{
this.launchImageLibrary(this.options, this.callback);
}
// NOTE: Currently not reentrant / doesn't support concurrent requests
@ReactMethod
public void launchImageLibrary(final ReadableMap options, final Callback callback)
{
final Activity currentActivity = getCurrentActivity();
if (currentActivity == null) {
responseHelper.invokeError(callback, "can't find current Activity");
return;
}
this.options = options;
this.callback = callback;
if (!permissionsCheck(currentActivity, callback, REQUEST_PERMISSIONS_FOR_LIBRARY))
{
return;
}
parseOptions(this.options);
int requestCode;
Intent libraryIntent;
if (pickVideo)
{
requestCode = REQUEST_LAUNCH_VIDEO_LIBRARY;
libraryIntent = new Intent(Intent.ACTION_PICK);
libraryIntent.setType("video/*");
}
else
{
requestCode = REQUEST_LAUNCH_IMAGE_LIBRARY;
libraryIntent = new Intent(Intent.ACTION_PICK,
MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
}
if (libraryIntent.resolveActivity(reactContext.getPackageManager()) == null)
{
responseHelper.invokeError(callback, "Cannot launch photo library");
return;
}
try
{
currentActivity.startActivityForResult(libraryIntent, requestCode);
}
catch (ActivityNotFoundException e)
{
e.printStackTrace();
responseHelper.invokeError(callback, "Cannot launch photo library");
}
}
@Override
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
//robustness code
if (passResult(requestCode))
{
return;
}
responseHelper.cleanResponse();
// user cancel
if (resultCode != Activity.RESULT_OK)
{
removeUselessFiles(requestCode, imageConfig);
responseHelper.invokeCancel(callback);
callback = null;
return;
}
Uri uri = null;
switch (requestCode)
{
case REQUEST_LAUNCH_IMAGE_CAPTURE:
uri = cameraCaptureURI;
break;
case REQUEST_LAUNCH_IMAGE_LIBRARY:
uri = data.getData();
String realPath = getRealPathFromURI(uri);
final boolean isUrl = !TextUtils.isEmpty(realPath) &&
Patterns.WEB_URL.matcher(realPath).matches();
if (realPath == null || isUrl)
{
try
{
File file = createFileFromURI(uri);
realPath = file.getAbsolutePath();
uri = Uri.fromFile(file);
}
catch (Exception e)
{
// image not in cache
responseHelper.putString("error", "Could not read photo");
responseHelper.putString("uri", uri.toString());
responseHelper.invokeResponse(callback);
callback = null;
return;
}
}
imageConfig = imageConfig.withOriginalFile(new File(realPath));
break;
case REQUEST_LAUNCH_VIDEO_LIBRARY:
responseHelper.putString("uri", data.getData().toString());
responseHelper.putString("path", getRealPathFromURI(data.getData()));
responseHelper.invokeResponse(callback);
callback = null;
return;
case REQUEST_LAUNCH_VIDEO_CAPTURE:
final String path = getRealPathFromURI(data.getData());
responseHelper.putString("uri", data.getData().toString());
responseHelper.putString("path", path);
fileScan(reactContext, path);
responseHelper.invokeResponse(callback);
callback = null;
return;
}
final ReadExifResult result = readExifInterface(responseHelper, imageConfig);
if (result.error != null)
{
removeUselessFiles(requestCode, imageConfig);
responseHelper.invokeError(callback, result.error.getMessage());
callback = null;
return;
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(imageConfig.original.getAbsolutePath(), options);
int initialWidth = options.outWidth;
int initialHeight = options.outHeight;
updatedResultResponse(uri, imageConfig.original.getAbsolutePath());
// don't create a new file if contraint are respected
if (imageConfig.useOriginal(initialWidth, initialHeight, result.currentRotation))
{
responseHelper.putInt("width", initialWidth);
responseHelper.putInt("height", initialHeight);
fileScan(reactContext, imageConfig.original.getAbsolutePath());
}
else
{
imageConfig = getResizedImage(reactContext, this.options, imageConfig, initialWidth, initialHeight, requestCode);
if (imageConfig.resized == null)
{
removeUselessFiles(requestCode, imageConfig);
responseHelper.putString("error", "Can't resize the image");
}
else
{
uri = Uri.fromFile(imageConfig.resized);
BitmapFactory.decodeFile(imageConfig.resized.getAbsolutePath(), options);
responseHelper.putInt("width", options.outWidth);
responseHelper.putInt("height", options.outHeight);
updatedResultResponse(uri, imageConfig.resized.getAbsolutePath());
fileScan(reactContext, imageConfig.resized.getAbsolutePath());
}
}
if (imageConfig.saveToCameraRoll && requestCode == REQUEST_LAUNCH_IMAGE_CAPTURE)
{
final RolloutPhotoResult rolloutResult = rolloutPhotoFromCamera(imageConfig);
if (rolloutResult.error == null)
{
imageConfig = rolloutResult.imageConfig;
uri = Uri.fromFile(imageConfig.getActualFile());
updatedResultResponse(uri, imageConfig.getActualFile().getAbsolutePath());
}
else
{
removeUselessFiles(requestCode, imageConfig);
final String errorMessage = new StringBuilder("Error moving image to camera roll: ")
.append(rolloutResult.error.getMessage()).toString();
responseHelper.putString("error", errorMessage);
return;
}
}
responseHelper.invokeResponse(callback);
callback = null;
this.options = null;
}
public void invokeCustomButton(@NonNull final String action)
{
responseHelper.invokeCustomButton(this.callback, action);
}
@Override
public void onNewIntent(Intent intent) { }
public Context getContext()
{
return getReactApplicationContext();
}
public @StyleRes int getDialogThemeId()
{
return this.dialogThemeId;
}
public @NonNull Activity getActivity()
{
return getCurrentActivity();
}
private boolean passResult(int requestCode)
{
return callback == null || (cameraCaptureURI == null && requestCode == REQUEST_LAUNCH_IMAGE_CAPTURE)
|| (requestCode != REQUEST_LAUNCH_IMAGE_CAPTURE && requestCode != REQUEST_LAUNCH_IMAGE_LIBRARY
&& requestCode != REQUEST_LAUNCH_VIDEO_LIBRARY && requestCode != REQUEST_LAUNCH_VIDEO_CAPTURE);
}
private void updatedResultResponse(@Nullable final Uri uri,
@NonNull final String path)
{
responseHelper.putString("uri", uri.toString());
responseHelper.putString("path", path);
if (!noData) {
responseHelper.putString("data", getBase64StringFromFile(path));
}
putExtraFileInfo(path, responseHelper);
}
private boolean permissionsCheck(@NonNull final Activity activity,
@NonNull final Callback callback,
@NonNull final int requestCode)
{
final int writePermission = ActivityCompat
.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
final int cameraPermission = ActivityCompat
.checkSelfPermission(activity, Manifest.permission.CAMERA);
final boolean permissionsGrated = writePermission == PackageManager.PERMISSION_GRANTED &&
cameraPermission == PackageManager.PERMISSION_GRANTED;
if (!permissionsGrated)
{
final Boolean dontAskAgain = ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) && ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA);
if (dontAskAgain)
{
final AlertDialog dialog = PermissionUtils
.explainingDialog(this, options, new PermissionUtils.OnExplainingPermissionCallback()
{
@Override
public void onCancel(WeakReference<ImagePickerModule> moduleInstance,
DialogInterface dialogInterface)
{
final ImagePickerModule module = moduleInstance.get();
if (module == null)
{
return;
}
module.doOnCancel();
}
@Override
public void onReTry(WeakReference<ImagePickerModule> moduleInstance,
DialogInterface dialogInterface)
{
final ImagePickerModule module = moduleInstance.get();
if (module == null)
{
return;
}
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", module.getContext().getPackageName(), null);
intent.setData(uri);
final Activity innerActivity = module.getActivity();
if (innerActivity == null)
{
return;
}
innerActivity.startActivityForResult(intent, 1);
}
});
if (dialog != null) {
dialog.show();
}
return false;
}
else
{
String[] PERMISSIONS = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA};
if (activity instanceof ReactActivity)
{
((ReactActivity) activity).requestPermissions(PERMISSIONS, requestCode, listener);
}
else if (activity instanceof OnImagePickerPermissionsCallback)
{
((OnImagePickerPermissionsCallback) activity).setPermissionListener(listener);
ActivityCompat.requestPermissions(activity, PERMISSIONS, requestCode);
}
else if (activity instanceof PermissionAwareActivity) {
((PermissionAwareActivity) activity).requestPermissions(PERMISSIONS, requestCode, listener);
}
else
{
final String errorDescription = new StringBuilder(activity.getClass().getSimpleName())
.append(" must implement ")
.append(OnImagePickerPermissionsCallback.class.getSimpleName())
.append(PermissionAwareActivity.class.getSimpleName())
.toString();
throw new UnsupportedOperationException(errorDescription);
}
return false;
}
}
return true;
}
private boolean isCameraAvailable() {
return reactContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)
|| reactContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY);
}
private @NonNull String getRealPathFromURI(@NonNull final Uri uri) {
return RealPathUtil.getRealPathFromURI(reactContext, uri);
}
/**
* Create a file from uri to allow image picking of image in disk cache
* (Exemple: facebook image, google image etc..)
*
* @doc =>
* https://github.com/nostra13/Android-Universal-Image-Loader#load--display-task-flow
*
* @param uri
* @return File
* @throws Exception
*/
private File createFileFromURI(Uri uri) throws Exception {
File file = new File(reactContext.getExternalCacheDir(), "photo-" + uri.getLastPathSegment());
InputStream input = reactContext.getContentResolver().openInputStream(uri);
OutputStream output = new FileOutputStream(file);
try {
byte[] buffer = new byte[4 * 1024];
int read;
while ((read = input.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
output.flush();
} finally {
output.close();
input.close();
}
return file;
}
private String getBase64StringFromFile(String absoluteFilePath) {
InputStream inputStream = null;
try {
inputStream = new FileInputStream(new File(absoluteFilePath));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
byte[] bytes;
byte[] buffer = new byte[8192];
int bytesRead;
ByteArrayOutputStream output = new ByteArrayOutputStream();
try {
while ((bytesRead = inputStream.read(buffer)) != -1) {
output.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
}
bytes = output.toByteArray();
return Base64.encodeToString(bytes, Base64.NO_WRAP);
}
private void putExtraFileInfo(@NonNull final String path,
@NonNull final ResponseHelper responseHelper)
{
// size && filename
try {
File f = new File(path);
responseHelper.putDouble("fileSize", f.length());
responseHelper.putString("fileName", f.getName());
} catch (Exception e) {
e.printStackTrace();
}
// type
String extension = MimeTypeMap.getFileExtensionFromUrl(path);
if (extension != null) {
responseHelper.putString("type", MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension));
}
}
private void parseOptions(final ReadableMap options) {
noData = false;
if (options.hasKey("noData")) {
noData = options.getBoolean("noData");
}
imageConfig = imageConfig.updateFromOptions(options);
pickVideo = false;
if (options.hasKey("mediaType") && options.getString("mediaType").equals("video")) {
pickVideo = true;
}
videoQuality = 1;
if (options.hasKey("videoQuality") && options.getString("videoQuality").equals("low")) {
videoQuality = 0;
}
videoDurationLimit = 0;
if (options.hasKey("durationLimit")) {
videoDurationLimit = options.getInt("durationLimit");
}
}
}

6
package-lock.json generated
View File

@@ -12754,9 +12754,9 @@
}
},
"react-native-image-picker": {
"version": "0.26.10",
"resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-0.26.10.tgz",
"integrity": "sha512-z6gAbru2E6SyGWm4ZTbiM9hPHZ5Tsl9kXGfRxW6YQXf9us7zybKoS7dKE1fQPsssv/OSvpPDKannJNncE+ATRA=="
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/react-native-image-picker/-/react-native-image-picker-0.27.0.tgz",
"integrity": "sha512-x4UDEs1XvfO+wXx41CZcZ4eVB+zj0vZuIl14ExO00WhyRf2NUXd4BG1uJzajOiyYQ+eRJQgv2PaNUamN6JqXZg=="
},
"react-native-iphone-x-helper": {
"version": "1.1.0",

View File

@@ -36,7 +36,7 @@
"react-native-drawer-layout": "2.0.0",
"react-native-exception-handler": "2.9.0",
"react-native-image-gallery": "github:enahum/react-native-image-gallery#a98b1051e94f5a394541ca1ff9b15e2c9ffed84f",
"react-native-image-picker": "0.26.10",
"react-native-image-picker": "0.27.0",
"react-native-keyboard-aware-scroll-view": "0.7.2",
"react-native-keychain": "3.0.0",
"react-native-linear-gradient": "2.4.2",