Browse Source

Don't show camera options for a file upload that would result in nothing happening for the user.

On Android, if the application declares the camera permission, then even intents
that use the camera require permission to be granted. This is a problem for apps
that combine an in-app camera with a WebView that has file uploading and the user
has not given permission for the camera.

Note, this will not request permission for camera. This will simply prevent
showing the camera options that would be a no-op action for users. It does this
by checking if the camera permission is declared, and if so, checks that the
user has granted permission.

More information: https://blog.egorand.me/taking-photos-not-so-simply-how-i-got-bitten-by-action_image_capture/
Daniel Vicory 4 years ago
parent
commit
d497212b44

+ 25
- 5
android/src/main/java/com/reactnativecommunity/webview/RNCWebViewModule.java View File

@@ -32,6 +32,7 @@ import com.facebook.react.modules.core.PermissionListener;
32 32
 import java.io.File;
33 33
 import java.io.IOException;
34 34
 import java.util.ArrayList;
35
+import java.util.Arrays;
35 36
 
36 37
 import static android.app.Activity.RESULT_OK;
37 38
 
@@ -180,11 +181,13 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti
180 181
     filePathCallback = callback;
181 182
 
182 183
     ArrayList<Parcelable> extraIntents = new ArrayList<>();
183
-    if (acceptsImages(acceptTypes)) {
184
-      extraIntents.add(getPhotoIntent());
185
-    }
186
-    if (acceptsVideo(acceptTypes)) {
187
-      extraIntents.add(getVideoIntent());
184
+    if (! needsCameraPermission()) {
185
+      if (acceptsImages(acceptTypes)) {
186
+        extraIntents.add(getPhotoIntent());
187
+      }
188
+      if (acceptsVideo(acceptTypes)) {
189
+        extraIntents.add(getVideoIntent());
190
+      }
188 191
     }
189 192
 
190 193
     Intent fileSelectionIntent = getFileChooserIntent(acceptTypes, allowMultiple);
@@ -233,6 +236,23 @@ public class RNCWebViewModule extends ReactContextBaseJavaModule implements Acti
233 236
     return result;
234 237
   }
235 238
 
239
+  protected boolean needsCameraPermission() {
240
+    boolean needed = false;
241
+
242
+    PackageManager packageManager = getCurrentActivity().getPackageManager();
243
+    try {
244
+      String[] requestedPermissions = packageManager.getPackageInfo(getReactApplicationContext().getPackageName(), PackageManager.GET_PERMISSIONS).requestedPermissions;
245
+      if (Arrays.asList(requestedPermissions).contains(Manifest.permission.CAMERA)
246
+        && ContextCompat.checkSelfPermission(getCurrentActivity(), Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
247
+        needed = true;
248
+      }
249
+    } catch (PackageManager.NameNotFoundException e) {
250
+      needed = true;
251
+    }
252
+
253
+    return needed;
254
+  }
255
+
236 256
   private Intent getPhotoIntent() {
237 257
     Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
238 258
     outputFileUri = getOutputUri(MediaStore.ACTION_IMAGE_CAPTURE);