зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1499618 Crash in java.lang.IllegalArgumentException: at android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java) r=JanH
Added fallback for the cases where trying to obtain a file absolute path from external storage was throwing an exception. Differential Revision: https://phabricator.services.mozilla.com/D9248 --HG-- extra : rebase_source : 7f6386e0dd47e503c412e6e9b552e8bf935851c9 extra : source : 3ad6353532ad19cc566c6f44bb47eb514987cc99
This commit is contained in:
Родитель
a4008cfe9a
Коммит
6e2e2a7b48
|
@ -41,7 +41,7 @@ import java.util.Locale;
|
|||
|
||||
import static org.mozilla.gecko.Tabs.INTENT_EXTRA_SESSION_UUID;
|
||||
import static org.mozilla.gecko.Tabs.INTENT_EXTRA_TAB_ID;
|
||||
import static org.mozilla.gecko.util.FileUtils.getFilePathFromUri;
|
||||
import static org.mozilla.gecko.util.FileUtils.resolveContentUri;
|
||||
|
||||
public final class IntentHelper implements BundleEventListener {
|
||||
|
||||
|
@ -512,8 +512,11 @@ public final class IntentHelper implements BundleEventListener {
|
|||
}
|
||||
|
||||
if (FileUtils.isContentUri(uri)) {
|
||||
errorResponse.putString("uri", getFilePathFromUri(getContext(), intent.getData()));
|
||||
errorResponse.putBoolean("isFallback", true);
|
||||
final String contentUri = resolveContentUri(getContext(), intent.getData());
|
||||
if (!TextUtils.isEmpty(contentUri)) {
|
||||
errorResponse.putString("uri", contentUri);
|
||||
errorResponse.putBoolean("isFallback", true);
|
||||
}
|
||||
callback.sendError(errorResponse);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -24,8 +24,11 @@ import android.os.Build;
|
|||
import android.os.Environment;
|
||||
import android.provider.DocumentsContract;
|
||||
import android.provider.MediaStore;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Based on https://github.com/iPaulPro/aFileChooser/blob/48d65e6649d4201407702b0390326ec9d5c9d17c/aFileChooser/src/com/ipaulpro/afilechooser/utils/FileUtils.java
|
||||
*/
|
||||
|
@ -42,7 +45,7 @@ public class ContentUriUtils {
|
|||
* @param uri The Uri to query.
|
||||
* @author paulburke
|
||||
*/
|
||||
public static String getPath(final Context context, final Uri uri) {
|
||||
public static @Nullable String getOriginalFilePathFromUri(final Context context, final Uri uri) throws IllegalArgumentException {
|
||||
|
||||
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
|
||||
|
||||
|
@ -118,6 +121,30 @@ public class ContentUriUtils {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves file contents via getContentResolver().openInputStream() and stores them in a
|
||||
* temporary file.
|
||||
*
|
||||
* @return The path of the temporary file, or <code>null</code> if there was an error
|
||||
* retrieving the file.
|
||||
*/
|
||||
public static @Nullable String getTempFilePathFromContentUri(Context context, Uri contentUri) {
|
||||
//copy file and send new file path
|
||||
final String fileName = FileUtils.getFileNameFromContentUri(context, contentUri);
|
||||
final File folder = new File(context.getCacheDir(), FileUtils.CONTENT_TEMP_DIRECTORY);
|
||||
boolean success = true;
|
||||
if (!folder.exists()) {
|
||||
success = folder.mkdirs();
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(fileName) && success) {
|
||||
File copyFile = new File(folder.getPath(), fileName);
|
||||
FileUtils.copy(context, contentUri, copyFile);
|
||||
return copyFile.getAbsolutePath();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the value of the data column for this Uri. This is useful for
|
||||
* MediaStore Uris, and other file-based ContentProviders.
|
||||
|
@ -130,24 +157,19 @@ public class ContentUriUtils {
|
|||
* @author paulburke
|
||||
*/
|
||||
private static String getDataColumn(Context context, Uri uri, String selection,
|
||||
String[] selectionArgs) {
|
||||
String[] selectionArgs) throws IllegalArgumentException {
|
||||
|
||||
Cursor cursor = null;
|
||||
final String column = "_data";
|
||||
final String[] projection = {
|
||||
column
|
||||
};
|
||||
|
||||
try {
|
||||
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
|
||||
null);
|
||||
try (Cursor cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
|
||||
null)) {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
final int column_index = cursor.getColumnIndexOrThrow(column);
|
||||
return cursor.getString(column_index);
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null)
|
||||
cursor.close();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,12 @@
|
|||
|
||||
package org.mozilla.gecko.util;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.MediaStore;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -29,13 +33,15 @@ import org.json.JSONException;
|
|||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.annotation.RobocopTarget;
|
||||
|
||||
import static org.mozilla.gecko.util.ContentUriUtils.getPath;
|
||||
import static org.mozilla.gecko.util.ContentUriUtils.getOriginalFilePathFromUri;
|
||||
import static org.mozilla.gecko.util.ContentUriUtils.getTempFilePathFromContentUri;
|
||||
|
||||
public class FileUtils {
|
||||
private static final String LOGTAG = "GeckoFileUtils";
|
||||
private static final String FILE_SCHEME = "file";
|
||||
private static final String CONTENT_SCHEME = "content";
|
||||
private static final String FILE_ABSOLUTE_URI = FILE_SCHEME + "://%s";
|
||||
public static final String CONTENT_TEMP_DIRECTORY = "contentUri";
|
||||
|
||||
/*
|
||||
* A basic Filter for checking a filename and age.
|
||||
|
@ -287,8 +293,43 @@ public class FileUtils {
|
|||
return result;
|
||||
}
|
||||
|
||||
public static String getFilePathFromUri(final Context context, final Uri uri) {
|
||||
return String.format(FILE_ABSOLUTE_URI, getPath(context, uri));
|
||||
public static String resolveContentUri(final Context context, final Uri uri) {
|
||||
String path;
|
||||
try {
|
||||
path = getOriginalFilePathFromUri(context, uri);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
// We cannot always successfully guess the original path of the file behind the
|
||||
// content:// URI, so we need a fallback. This will break local subresources and
|
||||
// relative links, but unfortunately there's nothing else we can do
|
||||
// (see https://issuetracker.google.com/issues/77406791).
|
||||
path = getTempFilePathFromContentUri(context, uri);
|
||||
}
|
||||
return !TextUtils.isEmpty(path) ? String.format(FILE_ABSOLUTE_URI, path) : path;
|
||||
}
|
||||
|
||||
public static String getFileNameFromContentUri(Context context, Uri uri) {
|
||||
final ContentResolver cr = context.getContentResolver();
|
||||
final String[] projection = {MediaStore.MediaColumns.DISPLAY_NAME};
|
||||
String fileName = null;
|
||||
|
||||
try (Cursor metaCursor = cr.query(uri, projection, null, null, null);) {
|
||||
if (metaCursor.moveToFirst()) {
|
||||
fileName = metaCursor.getString(0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return fileName;
|
||||
}
|
||||
|
||||
public static void copy(Context context, Uri srcUri, File dstFile) {
|
||||
try (InputStream inputStream = context.getContentResolver().openInputStream(srcUri);
|
||||
OutputStream outputStream = new FileOutputStream(dstFile)) {
|
||||
IOUtils.copy(inputStream, outputStream);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isContentUri(Uri uri) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче