From cbab2281fc479c4e4083b009fe5c99a28d5eca38 Mon Sep 17 00:00:00 2001 From: Alexis THOMAS Date: Sat, 6 Nov 2021 01:33:50 +0100 Subject: [PATCH 1/3] fix(android): standard way to get video uri from intent see #210, and follow doc https://developer.android.com/training/camera/videobasics#TaskVideoView (removes partial changes done in #13 for old android and cordova versions) --- src/android/Capture.java | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/src/android/Capture.java b/src/android/Capture.java index f008eba9..c27eb4b2 100644 --- a/src/android/Capture.java +++ b/src/android/Capture.java @@ -285,17 +285,6 @@ private void captureAudio(Request req) { } } - private String getTempDirectoryPath() { - File cache = null; - - // Use internal storage - cache = cordova.getActivity().getCacheDir(); - - // Create the cache directory if it doesn't exist - cache.mkdirs(); - return cache.getAbsolutePath(); - } - /** * Sets up an intent to capture images. Result handled by onActivityResult() */ @@ -427,17 +416,8 @@ public void onImageActivityResult(Request req) { } public void onVideoActivityResult(Request req, Intent intent) { - Uri data = null; - - if (intent != null){ - // Get the uri of the video clip - data = intent.getData(); - } - - if( data == null){ - File movie = new File(getTempDirectoryPath(), "Capture.avi"); - data = Uri.fromFile(movie); - } + // Get the uri of the video clip + Uri data = intent.getData(); // create a file object from the uri if(data == null) { From da1557d08b164caef80772ca0d5b3ac4cd985076 Mon Sep 17 00:00:00 2001 From: Alexis THOMAS Date: Sat, 6 Nov 2021 01:39:26 +0100 Subject: [PATCH 2/3] style(android): cleanup imports and remove unused method --- src/android/Capture.java | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/android/Capture.java b/src/android/Capture.java index c27eb4b2..0edaa9b2 100644 --- a/src/android/Capture.java +++ b/src/android/Capture.java @@ -20,24 +20,19 @@ Licensed to the Apache Software Foundation (ASF) under one import java.io.File; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; -import android.content.ActivityNotFoundException; -import android.os.Build; -import android.os.Bundle; - -import org.apache.cordova.file.FileUtils; -import org.apache.cordova.file.LocalFilesystemURL; - import org.apache.cordova.CallbackContext; import org.apache.cordova.CordovaPlugin; import org.apache.cordova.LOG; import org.apache.cordova.PermissionHelper; import org.apache.cordova.PluginManager; +import org.apache.cordova.file.FileUtils; +import org.apache.cordova.file.LocalFilesystemURL; import org.apache.cordova.mediacapture.PendingRequests.Request; import org.json.JSONArray; import org.json.JSONException; @@ -45,6 +40,7 @@ Licensed to the Apache Software Foundation (ASF) under one import android.Manifest; import android.app.Activity; +import android.content.ActivityNotFoundException; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Intent; @@ -54,6 +50,8 @@ Licensed to the Apache Software Foundation (ASF) under one import android.graphics.BitmapFactory; import android.media.MediaPlayer; import android.net.Uri; +import android.os.Build; +import android.os.Bundle; import android.os.Environment; import android.provider.MediaStore; @@ -307,11 +305,6 @@ private void captureImage(Request req) { this.cordova.startActivityForResult((CordovaPlugin) this, intent, req.requestCode); } - private static void createWritableFile(File file) throws IOException { - file.createNewFile(); - file.setWritable(true, false); - } - /** * Sets up an intent to capture video. Result handled by onActivityResult() */ From 752872fa4e256d039eeea5ac4588cf049bec0fab Mon Sep 17 00:00:00 2001 From: Alexis THOMAS Date: Sat, 6 Nov 2021 01:43:18 +0100 Subject: [PATCH 3/3] fix(android): prevent NPE with null checks on intent data and mediaFile --- src/android/Capture.java | 65 ++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/src/android/Capture.java b/src/android/Capture.java index 0edaa9b2..43bcc57f 100644 --- a/src/android/Capture.java +++ b/src/android/Capture.java @@ -381,8 +381,19 @@ else if (resultCode == Activity.RESULT_CANCELED) { public void onAudioActivityResult(Request req, Intent intent) { // Get the uri of the audio clip Uri data = intent.getData(); - // create a file object from the uri - req.results.put(createMediaFile(data)); + if (data == null) { + pendingRequests.resolveWithFailure(req, createErrorObject(CAPTURE_NO_MEDIA_FILES, "Error: data is null")); + return; + } + + // Create a file object from the uri + JSONObject mediaFile = createMediaFile(data); + if (mediaFile == null) { + pendingRequests.resolveWithFailure(req, createErrorObject(CAPTURE_INTERNAL_ERR, "Error: no mediaFile created from " + data)); + return; + } + + req.results.put(mediaFile); if (req.results.length() >= req.limit) { // Send Uri back to JavaScript for listening to audio @@ -394,8 +405,21 @@ public void onAudioActivityResult(Request req, Intent intent) { } public void onImageActivityResult(Request req) { - // Add image to results - req.results.put(createMediaFile(imageUri)); + // Get the uri of the image + Uri data = imageUri; + if (data == null) { + pendingRequests.resolveWithFailure(req, createErrorObject(CAPTURE_NO_MEDIA_FILES, "Error: data is null")); + return; + } + + // Create a file object from the uri + JSONObject mediaFile = createMediaFile(data); + if (mediaFile == null) { + pendingRequests.resolveWithFailure(req, createErrorObject(CAPTURE_INTERNAL_ERR, "Error: no mediaFile created from " + data)); + return; + } + + req.results.put(mediaFile); checkForDuplicateImage(); @@ -411,21 +435,26 @@ public void onImageActivityResult(Request req) { public void onVideoActivityResult(Request req, Intent intent) { // Get the uri of the video clip Uri data = intent.getData(); - - // create a file object from the uri - if(data == null) { + if (data == null) { pendingRequests.resolveWithFailure(req, createErrorObject(CAPTURE_NO_MEDIA_FILES, "Error: data is null")); + return; } - else { - req.results.put(createMediaFile(data)); - if (req.results.length() >= req.limit) { - // Send Uri back to JavaScript for viewing video - pendingRequests.resolveWithSuccess(req); - } else { - // still need to capture more video clips - captureVideo(req); - } + // Create a file object from the uri + JSONObject mediaFile = createMediaFile(data); + if (mediaFile == null) { + pendingRequests.resolveWithFailure(req, createErrorObject(CAPTURE_INTERNAL_ERR, "Error: no mediaFile created from " + data)); + return; + } + + req.results.put(mediaFile); + + if (req.results.length() >= req.limit) { + // Send Uri back to JavaScript for viewing video + pendingRequests.resolveWithSuccess(req); + } else { + // still need to capture more video clips + captureVideo(req); } } @@ -438,6 +467,10 @@ public void onVideoActivityResult(Request req, Intent intent) { */ private JSONObject createMediaFile(Uri data) { File fp = webView.getResourceApi().mapUriToFile(data); + if (fp == null) { + return null; + } + JSONObject obj = new JSONObject(); Class webViewClass = webView.getClass();