@connectedbits/react-native-image-picker 2.4.16-rc3 → 2.4.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,3 @@
1
- buildscript {
2
- repositories {
3
- google()
4
- jcenter()
5
- }
6
-
7
- dependencies {
8
- classpath 'com.android.tools.build:gradle:3.4.1'
9
- }
10
- }
11
-
12
1
  def getExtOrDefault(name) {
13
2
  return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties['ReactNativeImagePicker_' + name]
14
3
  }
@@ -20,6 +9,10 @@ def getExtOrIntegerDefault(name) {
20
9
  apply plugin: 'com.android.library'
21
10
 
22
11
  android {
12
+ // AGP 7.3+ wants the namespace here rather than in the manifest
13
+ if (project.android.hasProperty("namespace")) {
14
+ namespace "com.imagepicker"
15
+ }
23
16
  compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
24
17
  buildToolsVersion getExtOrDefault('buildToolsVersion')
25
18
 
@@ -47,11 +40,13 @@ repositories {
47
40
  url "$projectDir/../node_modules/jsc-android/dist"
48
41
  }
49
42
  google()
50
- jcenter()
43
+ mavenCentral()
51
44
  }
52
45
 
53
46
  dependencies {
54
47
  api "com.facebook.react:react-native:+" // From node_modules
48
+ // System Photo Picker contract (PickVisualMedia + PickVisualMediaRequest.Builder)
49
+ implementation "androidx.activity:activity:1.8.0"
55
50
 
56
51
  testImplementation('org.robolectric:robolectric:4.3.1') {
57
52
  // https://github.com/robolectric/robolectric/issues/5245
@@ -3,6 +3,10 @@
3
3
  xmlns:android="http://schemas.android.com/apk/res/android"
4
4
  package="com.imagepicker"
5
5
  >
6
+ <!-- Lets us read EXIF GPS from photos picked via the system Photo Picker when the provider allows it.
7
+ No storage permission is needed: the library uses the Photo Picker and captures go to app storage. -->
8
+ <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
9
+
6
10
  <application>
7
11
  <provider
8
12
  android:name="com.imagepicker.FileProvider"
@@ -6,7 +6,6 @@ import android.content.ActivityNotFoundException;
6
6
  import android.content.Context;
7
7
  import android.content.DialogInterface;
8
8
  import android.content.Intent;
9
- import android.content.pm.ResolveInfo;
10
9
  import android.graphics.Bitmap;
11
10
  import android.graphics.BitmapFactory;
12
11
  import android.net.Uri;
@@ -14,7 +13,10 @@ import android.os.Build;
14
13
  import android.os.Handler;
15
14
  import android.provider.MediaStore;
16
15
  import android.provider.Settings;
16
+ import androidx.activity.result.PickVisualMediaRequest;
17
+ import androidx.activity.result.contract.ActivityResultContracts;
17
18
  import androidx.annotation.NonNull;
19
+ import androidx.annotation.Nullable;
18
20
  import androidx.annotation.StyleRes;
19
21
  import androidx.core.app.ActivityCompat;
20
22
  import androidx.appcompat.app.AlertDialog;
@@ -47,7 +49,6 @@ import java.io.IOException;
47
49
  import java.io.InputStream;
48
50
  import java.io.UnsupportedEncodingException;
49
51
  import java.lang.ref.WeakReference;
50
- import java.util.List;
51
52
 
52
53
  import com.facebook.react.modules.core.PermissionListener;
53
54
  import com.facebook.react.modules.core.PermissionAwareActivity;
@@ -69,6 +70,8 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
69
70
  public static final int REQUEST_LAUNCH_VIDEO_LIBRARY = 13003;
70
71
  public static final int REQUEST_LAUNCH_VIDEO_CAPTURE = 13004;
71
72
  public static final int REQUEST_PERMISSIONS_FOR_CAMERA = 14001;
73
+ // The system Photo Picker needs no storage permission. We only (opportunistically) ask for
74
+ // ACCESS_MEDIA_LOCATION so that EXIF GPS can be read when the provider is willing to hand it back.
72
75
  public static final int REQUEST_PERMISSIONS_FOR_LIBRARY = 14002;
73
76
 
74
77
  private final ReactApplicationContext reactContext;
@@ -91,6 +94,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
91
94
  private int videoDurationLimit = 0;
92
95
 
93
96
  private ResponseHelper responseHelper = new ResponseHelper();
97
+ private boolean mediaLocationRequested = false;
94
98
  private PermissionListener listener = new PermissionListener()
95
99
  {
96
100
  public boolean onRequestPermissionsResult(final int requestCode,
@@ -109,24 +113,26 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
109
113
  return false;
110
114
  }
111
115
 
112
- if (!permissionsGranted)
113
- {
114
- responseHelper.invokeError(permissionRequestCallback, "Permissions weren't granted");
115
- return false;
116
- }
117
-
118
116
  switch (requestCode)
119
117
  {
120
118
  case REQUEST_PERMISSIONS_FOR_CAMERA:
119
+ if (!permissionsGranted)
120
+ {
121
+ responseHelper.invokeError(permissionRequestCallback, "Permissions weren't granted");
122
+ callback = null;
123
+ return false;
124
+ }
121
125
  launchCamera(options, permissionRequestCallback);
122
- break;
126
+ return true;
123
127
 
124
128
  case REQUEST_PERMISSIONS_FOR_LIBRARY:
129
+ // Open the picker whether or not media location was granted; without it we simply
130
+ // won't get EXIF GPS back.
131
+ mediaLocationRequested = true;
125
132
  launchImageLibrary(options, permissionRequestCallback);
126
- break;
127
-
133
+ return true;
128
134
  }
129
- return true;
135
+ return false;
130
136
  }
131
137
  };
132
138
 
@@ -153,7 +159,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
153
159
  @ReactMethod
154
160
  public void showImagePicker(final ReadableMap options, final Callback callback) {
155
161
  final ImagePickerModule self = this;
156
- final Activity currentActivity = getCurrentActivity();
162
+ final Activity currentActivity = getReactApplicationContext().getCurrentActivity();
157
163
  Handler handler = new Handler(this.reactContext.getMainLooper());
158
164
  this.callback = callback;
159
165
  this.options = options;
@@ -242,7 +248,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
242
248
  return;
243
249
  }
244
250
 
245
- final Activity currentActivity = getCurrentActivity();
251
+ final Activity currentActivity = getReactApplicationContext().getCurrentActivity();
246
252
  if (currentActivity == null)
247
253
  {
248
254
  responseHelper.invokeError(callback, "can't find current Activity");
@@ -296,16 +302,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
296
302
  cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, cameraCaptureURI);
297
303
  }
298
304
 
299
- // Workaround for Android bug.
300
- // grantUriPermission also needed for KITKAT,
301
- // see https://code.google.com/p/android/issues/detail?id=76683
302
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
303
- List<ResolveInfo> resInfoList = self.getContext().getPackageManager().queryIntentActivities(cameraIntent, PackageManager.MATCH_DEFAULT_ONLY);
304
- for (ResolveInfo resolveInfo : resInfoList) {
305
- String packageName = resolveInfo.activityInfo.packageName;
306
- self.getContext().grantUriPermission(packageName, cameraCaptureURI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
307
- }
308
- }
305
+ cameraIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
309
306
 
310
307
  try
311
308
  {
@@ -330,7 +327,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
330
327
  {
331
328
  permissionRequestCallback = callback;
332
329
 
333
- final Activity currentActivity = getCurrentActivity();
330
+ final Activity currentActivity = getReactApplicationContext().getCurrentActivity();
334
331
  if (currentActivity == null) {
335
332
  responseHelper.invokeError(callback, "can't find current Activity");
336
333
  return;
@@ -343,47 +340,40 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
343
340
  handler.post(new Runnable() {
344
341
  @Override
345
342
  public void run(){
346
- if (!permissionsCheck(currentActivity, callback, REQUEST_PERMISSIONS_FOR_LIBRARY))
343
+ if (shouldRequestMediaLocation(currentActivity))
347
344
  {
345
+ requestPermissions(currentActivity, new String[]{Manifest.permission.ACCESS_MEDIA_LOCATION}, REQUEST_PERMISSIONS_FOR_LIBRARY);
348
346
  return;
349
347
  }
348
+ mediaLocationRequested = false;
350
349
 
351
350
  parseOptions(options);
352
351
 
353
- int requestCode;
354
- Intent libraryIntent;
352
+ // System Photo Picker (Android 13+, or back-ported via Google Play services). androidx falls
353
+ // back to ACTION_OPEN_DOCUMENT on devices where neither is available.
354
+ final ActivityResultContracts.PickVisualMedia.VisualMediaType mediaType;
355
355
  if (pickVideo)
356
356
  {
357
- requestCode = REQUEST_LAUNCH_VIDEO_LIBRARY;
358
- libraryIntent = new Intent(Intent.ACTION_GET_CONTENT);
359
- libraryIntent.setType("video/*");
360
- libraryIntent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
361
- libraryIntent.putExtra(Intent.CATEGORY_OPENABLE, true);
357
+ mediaType = ActivityResultContracts.PickVisualMedia.VideoOnly.INSTANCE;
358
+ }
359
+ else if (pickBoth)
360
+ {
361
+ mediaType = ActivityResultContracts.PickVisualMedia.ImageAndVideo.INSTANCE;
362
362
  }
363
363
  else
364
364
  {
365
- requestCode = REQUEST_LAUNCH_IMAGE_LIBRARY;
366
- libraryIntent = new Intent(Intent.ACTION_GET_CONTENT);
367
- libraryIntent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
368
- libraryIntent.putExtra(Intent.CATEGORY_OPENABLE, true);
369
-
370
- if (pickBoth)
371
- {
372
- libraryIntent.setType("image/* video/*");
373
- } else {
374
- libraryIntent.setType("image/*");
375
- }
365
+ mediaType = ActivityResultContracts.PickVisualMedia.ImageOnly.INSTANCE;
376
366
  }
367
+ final PickVisualMediaRequest request = new PickVisualMediaRequest.Builder()
368
+ .setMediaType(mediaType)
369
+ .build();
370
+ final Intent libraryIntent = new ActivityResultContracts.PickVisualMedia()
371
+ .createIntent(currentActivity, request);
372
+ final int requestCode = pickVideo ? REQUEST_LAUNCH_VIDEO_LIBRARY : REQUEST_LAUNCH_IMAGE_LIBRARY;
377
373
 
378
374
  try
379
375
  {
380
- String chooseWhichLibraryTitle = null;
381
- if (ReadableMapUtils.hasAndNotEmptyString(options, "chooseWhichLibraryTitle"))
382
- {
383
- chooseWhichLibraryTitle = options.getString("chooseWhichLibraryTitle");
384
- }
385
-
386
- currentActivity.startActivityForResult(Intent.createChooser(libraryIntent, chooseWhichLibraryTitle), requestCode);
376
+ currentActivity.startActivityForResult(libraryIntent, requestCode);
387
377
  }
388
378
  catch (ActivityNotFoundException e)
389
379
  {
@@ -394,6 +384,20 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
394
384
  });
395
385
  }
396
386
 
387
+ /**
388
+ * Ask for ACCESS_MEDIA_LOCATION once per library launch when it isn't granted yet. If the user has
389
+ * already denied it permanently the request returns immediately without UI.
390
+ */
391
+ private boolean shouldRequestMediaLocation(@NonNull final Activity activity)
392
+ {
393
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || mediaLocationRequested)
394
+ {
395
+ return false;
396
+ }
397
+ return ActivityCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_MEDIA_LOCATION)
398
+ != PackageManager.PERMISSION_GRANTED;
399
+ }
400
+
397
401
  @Override
398
402
  public void onActivityResult(Activity activity, final int requestCode, final int resultCode, final Intent data) {
399
403
  final ImagePickerModule self = this;
@@ -417,6 +421,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
417
421
  }
418
422
 
419
423
  Uri uri = null;
424
+ boolean fromLibrary = false;
420
425
  switch (requestCode)
421
426
  {
422
427
  case REQUEST_LAUNCH_IMAGE_CAPTURE:
@@ -424,35 +429,44 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
424
429
  break;
425
430
 
426
431
  case REQUEST_LAUNCH_IMAGE_LIBRARY:
427
- uri = data.getData();
428
- if(uri == null){
429
- responseHelper.putString("error", "Could not read photo");
432
+ uri = data != null ? data.getData() : null;
433
+ if (uri == null) {
434
+ responseHelper.invokeError(callback, "Could not read photo");
435
+ callback = null;
436
+ return;
437
+ }
438
+ // mediaType "mixed" can hand back a video from the image request code.
439
+ final String mimeType = self.getContext().getContentResolver().getType(uri);
440
+ if (mimeType != null && mimeType.startsWith("video/")) {
441
+ responseHelper.putString("uri", uri.toString());
430
442
  responseHelper.invokeResponse(callback);
431
443
  callback = null;
432
444
  return;
433
445
  }
446
+ fromLibrary = true;
434
447
  break;
435
448
 
436
449
  case REQUEST_LAUNCH_VIDEO_LIBRARY:
437
- responseHelper.putString("uri", data.getData().toString());
438
- responseHelper.invokeResponse(callback);
439
- callback = null;
440
- return;
441
-
442
450
  case REQUEST_LAUNCH_VIDEO_CAPTURE:
451
+ if (data == null || data.getData() == null) {
452
+ responseHelper.invokeError(callback, "Could not read video");
453
+ callback = null;
454
+ return;
455
+ }
443
456
  responseHelper.putString("uri", data.getData().toString());
444
457
  responseHelper.invokeResponse(callback);
445
458
  callback = null;
446
459
  return;
447
460
  }
448
461
 
462
+ // EXIF (location/timestamp/orientation). For library picks, ask for the unredacted original
463
+ // so GPS survives when ACCESS_MEDIA_LOCATION is granted and the provider honours it.
449
464
  ReadExifResult result = null;
450
- try {
451
- InputStream imageInputStream = self.getContext().getContentResolver().openInputStream(uri);
452
- if(imageInputStream != null){
465
+ try (InputStream imageInputStream = openExifInputStream(uri, fromLibrary)) {
466
+ if (imageInputStream != null) {
453
467
  result = readExifInterface(imageInputStream, responseHelper);
454
468
  }
455
- } catch(IOException ex){
469
+ } catch (IOException ex) {
456
470
  responseHelper.invokeError(callback, ex.getMessage());
457
471
  callback = null;
458
472
  return;
@@ -471,31 +485,26 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
471
485
 
472
486
  BitmapFactory.Options options = new BitmapFactory.Options();
473
487
  options.inJustDecodeBounds = true;
474
- Bitmap imageBitmap = null;
475
- try {
476
- InputStream imageInputStream = self.getContext().getContentResolver().openInputStream(uri);
477
- imageBitmap = BitmapFactory.decodeStream(imageInputStream, null, options);
478
- } catch(FileNotFoundException ex){
488
+ try (InputStream imageInputStream = self.getContext().getContentResolver().openInputStream(uri)) {
489
+ BitmapFactory.decodeStream(imageInputStream, null, options);
490
+ } catch (IOException ex) {
479
491
  responseHelper.invokeError(callback, "Could not find file");
480
492
  callback = null;
481
493
  return;
482
494
  }
483
495
 
484
-
485
496
  int initialWidth = options.outWidth;
486
497
  int initialHeight = options.outHeight;
487
498
 
488
-
489
499
  // don't create a new file if contraint are respected
490
500
  if (imageConfig.useOriginal(initialWidth, initialHeight, result.currentRotation))
491
501
  {
492
502
  responseHelper.putInt("width", initialWidth);
493
503
  responseHelper.putInt("height", initialHeight);
494
504
 
495
- try {
496
- InputStream imageInputStream = self.getContext().getContentResolver().openInputStream(uri);
505
+ try (InputStream imageInputStream = self.getContext().getContentResolver().openInputStream(uri)) {
497
506
  updatedResultResponse(imageInputStream);
498
- } catch(FileNotFoundException ex){
507
+ } catch (IOException ex) {
499
508
  responseHelper.invokeError(callback, "Could not find file");
500
509
  callback = null;
501
510
  return;
@@ -505,10 +514,9 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
505
514
  {
506
515
  Bitmap resizedImage = null;
507
516
  ImageConfig rotatedImageConfig = imageConfig.withRotation(result.currentRotation);
508
- try {
509
- InputStream imageInputStream = self.getContext().getContentResolver().openInputStream(uri);
517
+ try (InputStream imageInputStream = self.getContext().getContentResolver().openInputStream(uri)) {
510
518
  resizedImage = getResizedImage(imageInputStream, rotatedImageConfig, initialWidth, initialHeight);
511
- } catch(FileNotFoundException ex){
519
+ } catch (IOException ex) {
512
520
  responseHelper.invokeError(callback, "Could not find file");
513
521
  callback = null;
514
522
  return;
@@ -528,14 +536,8 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
528
536
  ByteArrayInputStream bs = new ByteArrayInputStream(bitmapdata);
529
537
  updatedResultResponse(bs);
530
538
  resizedImage.recycle();
531
- resizedImage = null;
532
539
  }
533
540
  }
534
- if(imageBitmap != null){
535
- imageBitmap.recycle();
536
- imageBitmap = null;
537
- }
538
-
539
541
 
540
542
  responseHelper.invokeResponse(callback);
541
543
  self.callback = null;
@@ -544,6 +546,28 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
544
546
  });
545
547
  }
546
548
 
549
+ /**
550
+ * Open a stream for EXIF parsing. On Android 10+ location tags are redacted unless we hold
551
+ * ACCESS_MEDIA_LOCATION and ask for the original via MediaStore.setRequireOriginal. Providers that
552
+ * don't support that (e.g. some Photo Picker configurations) throw, in which case we fall back to the
553
+ * plain (redacted) stream.
554
+ */
555
+ private @Nullable InputStream openExifInputStream(@NonNull final Uri uri, final boolean fromLibrary) throws FileNotFoundException
556
+ {
557
+ if (fromLibrary && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
558
+ {
559
+ try
560
+ {
561
+ return getContext().getContentResolver().openInputStream(MediaStore.setRequireOriginal(uri));
562
+ }
563
+ catch (UnsupportedOperationException | SecurityException | IllegalArgumentException | FileNotFoundException e)
564
+ {
565
+ // fall through to the plain uri
566
+ }
567
+ }
568
+ return getContext().getContentResolver().openInputStream(uri);
569
+ }
570
+
547
571
  public void invokeCustomButton(@NonNull final String action)
548
572
  {
549
573
  responseHelper.invokeCustomButton(this.callback, action);
@@ -564,7 +588,7 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
564
588
 
565
589
  public @NonNull Activity getActivity()
566
590
  {
567
- return getCurrentActivity();
591
+ return getReactApplicationContext().getCurrentActivity();
568
592
  }
569
593
 
570
594
 
@@ -584,130 +608,89 @@ public class ImagePickerModule extends ReactContextBaseJavaModule
584
608
  @NonNull final Callback callback,
585
609
  @NonNull final int requestCode)
586
610
  {
587
- int writePermission = 0;
588
- int libraryPermission = 0;
589
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
590
- writePermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);
591
- libraryPermission = writePermission;
592
- } else {
593
- writePermission = PackageManager.PERMISSION_GRANTED;
594
- libraryPermission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.READ_MEDIA_IMAGES);
595
- }
596
-
597
- final int cameraPermission = ActivityCompat
598
- .checkSelfPermission(activity, Manifest.permission.CAMERA);
599
-
600
- boolean permissionsGranted = false;
601
-
602
- switch (requestCode) {
603
- case REQUEST_PERMISSIONS_FOR_LIBRARY:
604
- permissionsGranted = libraryPermission == PackageManager.PERMISSION_GRANTED;
605
- break;
606
- case REQUEST_PERMISSIONS_FOR_CAMERA:
607
- permissionsGranted = cameraPermission == PackageManager.PERMISSION_GRANTED && writePermission == PackageManager.PERMISSION_GRANTED;
608
- break;
611
+ // Only the camera needs a runtime permission. Captures are written to app-specific storage
612
+ // (getExternalFilesDir) and the library uses the system Photo Picker, so no storage permission
613
+ // is required on any supported API level.
614
+ final boolean permissionsGranted = ActivityCompat
615
+ .checkSelfPermission(activity, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
616
+ if (permissionsGranted)
617
+ {
618
+ return true;
609
619
  }
610
620
 
611
- if (!permissionsGranted)
621
+ if (ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA))
612
622
  {
613
- Boolean dontAskAgain = false;
614
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
615
- dontAskAgain = ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE) && ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA);
616
- } else {
617
- dontAskAgain = ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.READ_MEDIA_IMAGES) && ActivityCompat.shouldShowRequestPermissionRationale(activity, Manifest.permission.CAMERA);
618
- }
619
-
620
- if (dontAskAgain)
621
- {
622
- final AlertDialog dialog = PermissionUtils
623
- .explainingDialog(this, options, new PermissionUtils.OnExplainingPermissionCallback()
623
+ final AlertDialog dialog = PermissionUtils
624
+ .explainingDialog(this, options, new PermissionUtils.OnExplainingPermissionCallback()
625
+ {
626
+ @Override
627
+ public void onCancel(WeakReference<ImagePickerModule> moduleInstance,
628
+ DialogInterface dialogInterface)
624
629
  {
625
- @Override
626
- public void onCancel(WeakReference<ImagePickerModule> moduleInstance,
627
- DialogInterface dialogInterface)
630
+ final ImagePickerModule module = moduleInstance.get();
631
+ if (module == null)
628
632
  {
629
- final ImagePickerModule module = moduleInstance.get();
630
- if (module == null)
631
- {
632
- return;
633
- }
634
- module.doOnCancel();
633
+ return;
635
634
  }
635
+ module.doOnCancel();
636
+ }
636
637
 
637
- @Override
638
- public void onReTry(WeakReference<ImagePickerModule> moduleInstance,
639
- DialogInterface dialogInterface)
638
+ @Override
639
+ public void onReTry(WeakReference<ImagePickerModule> moduleInstance,
640
+ DialogInterface dialogInterface)
641
+ {
642
+ final ImagePickerModule module = moduleInstance.get();
643
+ if (module == null)
640
644
  {
641
- final ImagePickerModule module = moduleInstance.get();
642
- if (module == null)
643
- {
644
- return;
645
- }
646
- Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
647
- Uri uri = Uri.fromParts("package", module.getContext().getPackageName(), null);
648
- intent.setData(uri);
649
- final Activity innerActivity = module.getActivity();
650
- if (innerActivity == null)
651
- {
652
- return;
653
- }
654
- innerActivity.startActivityForResult(intent, 1);
645
+ return;
655
646
  }
656
- });
657
- if (dialog != null) {
658
- dialog.show();
659
- }
660
- return false;
647
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
648
+ Uri uri = Uri.fromParts("package", module.getContext().getPackageName(), null);
649
+ intent.setData(uri);
650
+ final Activity innerActivity = module.getActivity();
651
+ if (innerActivity == null)
652
+ {
653
+ return;
654
+ }
655
+ innerActivity.startActivityForResult(intent, 1);
656
+ }
657
+ });
658
+ if (dialog != null) {
659
+ dialog.show();
661
660
  }
662
- else
663
- {
664
- String[] PERMISSIONS;
665
- switch (requestCode) {
666
- case REQUEST_PERMISSIONS_FOR_LIBRARY:
667
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
668
- PERMISSIONS = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
669
- } else {
670
- PERMISSIONS = new String[]{Manifest.permission.READ_MEDIA_IMAGES};
671
- }
672
- break;
673
- case REQUEST_PERMISSIONS_FOR_CAMERA:
674
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
675
- PERMISSIONS = new String[]{Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE};
676
- } else {
677
- PERMISSIONS = new String[]{Manifest.permission.CAMERA};
678
- }
679
- break;
680
- default:
681
- PERMISSIONS = new String[]{};
682
- break;
683
- }
661
+ return false;
662
+ }
684
663
 
685
- if (activity instanceof ReactActivity)
686
- {
687
- ((ReactActivity) activity).requestPermissions(PERMISSIONS, requestCode, listener);
688
- }
689
- else if (activity instanceof PermissionAwareActivity) {
690
- ((PermissionAwareActivity) activity).requestPermissions(PERMISSIONS, requestCode, listener);
691
- }
692
- else if (activity instanceof OnImagePickerPermissionsCallback)
693
- {
694
- ((OnImagePickerPermissionsCallback) activity).setPermissionListener(listener);
695
- ActivityCompat.requestPermissions(activity, PERMISSIONS, requestCode);
696
- }
697
- else
698
- {
699
- final String errorDescription = new StringBuilder(activity.getClass().getSimpleName())
700
- .append(" must implement ")
701
- .append(OnImagePickerPermissionsCallback.class.getSimpleName())
702
- .append(" or ")
703
- .append(PermissionAwareActivity.class.getSimpleName())
704
- .toString();
705
- throw new UnsupportedOperationException(errorDescription);
706
- }
707
- return false;
708
- }
664
+ requestPermissions(activity, new String[]{Manifest.permission.CAMERA}, requestCode);
665
+ return false;
666
+ }
667
+
668
+ private void requestPermissions(@NonNull final Activity activity,
669
+ @NonNull final String[] permissions,
670
+ final int requestCode)
671
+ {
672
+ if (activity instanceof ReactActivity)
673
+ {
674
+ ((ReactActivity) activity).requestPermissions(permissions, requestCode, listener);
675
+ }
676
+ else if (activity instanceof PermissionAwareActivity) {
677
+ ((PermissionAwareActivity) activity).requestPermissions(permissions, requestCode, listener);
678
+ }
679
+ else if (activity instanceof OnImagePickerPermissionsCallback)
680
+ {
681
+ ((OnImagePickerPermissionsCallback) activity).setPermissionListener(listener);
682
+ ActivityCompat.requestPermissions(activity, permissions, requestCode);
683
+ }
684
+ else
685
+ {
686
+ final String errorDescription = new StringBuilder(activity.getClass().getSimpleName())
687
+ .append(" must implement ")
688
+ .append(OnImagePickerPermissionsCallback.class.getSimpleName())
689
+ .append(" or ")
690
+ .append(PermissionAwareActivity.class.getSimpleName())
691
+ .toString();
692
+ throw new UnsupportedOperationException(errorDescription);
709
693
  }
710
- return true;
711
694
  }
712
695
 
713
696
  private boolean isCameraAvailable() {
@@ -6,6 +6,6 @@ typedef NS_ENUM(NSInteger, RNImagePickerTarget) {
6
6
  RNImagePickerTargetLibrarySingleImage,
7
7
  };
8
8
 
9
- @interface ImagePickerManager : NSObject <RCTBridgeModule, UINavigationControllerDelegate, UIActionSheetDelegate, UIImagePickerControllerDelegate>
9
+ @interface ImagePickerManager : NSObject <RCTBridgeModule, UINavigationControllerDelegate, UIImagePickerControllerDelegate>
10
10
 
11
11
  @end