Skip to content

Commit

Permalink
fix(android): prevent app crash caused by NPE on intent data or media…
Browse files Browse the repository at this point in the history
…File (#232)

* 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)

* style(android): cleanup imports and remove unused method
* fix(android): prevent NPE with null checks on intent data and mediaFile
  • Loading branch information
ath0mas authored Aug 3, 2023
1 parent 306eb8b commit 69bb93d
Showing 1 changed file with 55 additions and 49 deletions.
104 changes: 55 additions & 49 deletions src/android/Capture.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,27 @@ 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;
import org.json.JSONObject;

import android.Manifest;
import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
Expand All @@ -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;

Expand Down Expand Up @@ -285,17 +283,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()
*/
Expand All @@ -318,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()
*/
Expand Down Expand Up @@ -399,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
Expand All @@ -412,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();

Expand All @@ -427,32 +433,28 @@ 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();
// Get the uri of the video clip
Uri data = intent.getData();
if (data == null) {
pendingRequests.resolveWithFailure(req, createErrorObject(CAPTURE_NO_MEDIA_FILES, "Error: data is null"));
return;
}

if( data == null){
File movie = new File(getTempDirectoryPath(), "Capture.avi");
data = Uri.fromFile(movie);
// 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;
}

// create a file object from the uri
if(data == null) {
pendingRequests.resolveWithFailure(req, createErrorObject(CAPTURE_NO_MEDIA_FILES, "Error: data is null"));
}
else {
req.results.put(createMediaFile(data));
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);
}
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);
}
}

Expand All @@ -465,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();
Expand Down

0 comments on commit 69bb93d

Please sign in to comment.