1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-07-11 07:54:03 +02:00

Fix crash in settings activity with export location

The way this works will never be a fully working solution, because uris are
*not supposed* to be resolved to a filesystem path. So while this may work
right now, it will most probably fail in the future, with other content providers.

See e.g. https://github.com/iPaulPro/aFileChooser/issues where this code originally came from
(via Stackoverflow).

We won't crash anymore, but we won't support certain content providers. In the long run, we
should search for the proper solution.

Closes #982
This commit is contained in:
cpfeiffer 2018-02-11 14:32:21 +01:00
parent 8bd9cd6dff
commit 78b50e82fa
2 changed files with 50 additions and 26 deletions

View File

@ -377,7 +377,7 @@ public class SettingsActivity extends AbstractSettingsActivity {
}
/*
Either returns the file path of the selected document, or the display name
Either returns the file path of the selected document, or the display name, or an empty string
*/
private String getAutoExportLocationSummary() {
String autoExportLocation = GBApplication.getPrefs().getString(GBPrefs.AUTO_EXPORT_LOCATION, null);
@ -386,20 +386,16 @@ public class SettingsActivity extends AbstractSettingsActivity {
}
Uri uri = Uri.parse(autoExportLocation);
try {
String filePath = AndroidUtils.getFilePath(getApplicationContext(), uri);
if (filePath != null) {
return filePath;
return AndroidUtils.getFilePath(getApplicationContext(), uri);
} catch (IllegalArgumentException e) {
Cursor cursor = getContentResolver().query(
uri,
new String[] { DocumentsContract.Document.COLUMN_DISPLAY_NAME },
null, null, null, null
);
if (cursor != null && cursor.moveToFirst()) {
return cursor.getString(cursor.getColumnIndex(DocumentsContract.Document.COLUMN_DISPLAY_NAME));
}
} catch (URISyntaxException e) {
return "";
}
Cursor cursor = getContentResolver().query(
uri,
new String[] { DocumentsContract.Document.COLUMN_DISPLAY_NAME },
null, null, null, null
);
if (cursor != null && cursor.moveToFirst()) {
return cursor.getString(cursor.getColumnIndex(DocumentsContract.Document.COLUMN_DISPLAY_NAME));
}
return "";
}

View File

@ -30,7 +30,10 @@ import android.os.ParcelUuid;
import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import java.net.URISyntaxException;
import java.util.Locale;
@ -121,6 +124,28 @@ public class AndroidUtils {
+ Integer.toHexString(Color.blue(color));
}
/**
* As seen on stackoverflow https://stackoverflow.com/a/36714242/1207186
* Try to find the file path of a document uri
* @param context the application context
* @param uri the Uri for which the path should be resolved
* @return the path corresponding to the Uri as a String
* @throws IllegalArgumentException on any problem decoding the uri to a path
*/
public static @NonNull String getFilePath(@NonNull Context context, @NonNull Uri uri) throws IllegalArgumentException {
try {
String path = internalGetFilePath(context, uri);
if (TextUtils.isEmpty(path)) {
throw new IllegalArgumentException("Unable to decode the given uri to a file path: " + uri);
}
return path;
} catch (IllegalArgumentException ex) {
throw ex;
} catch (Exception ex) {
throw new IllegalArgumentException("Unable to decode the given uri to a file path: " + uri, ex);
}
}
/**
* As seen on stackoverflow https://stackoverflow.com/a/36714242/1207186
* Try to find the file path of a document uri
@ -129,9 +154,10 @@ public class AndroidUtils {
* @return the path corresponding to the Uri as a String
* @throws URISyntaxException
*/
public static String getFilePath(Context context, Uri uri) throws URISyntaxException {
private static @Nullable String internalGetFilePath(@NonNull Context context, @NonNull Uri uri) throws URISyntaxException {
String selection = null;
String[] selectionArgs = null;
// Uri is different in versions after KITKAT (Android 4.4), we need to
if (Build.VERSION.SDK_INT >= 19 && DocumentsContract.isDocumentUri(context.getApplicationContext(), uri)) {
if ("com.android.externalstorage.documents".equals(uri.getAuthority())) {
@ -140,8 +166,13 @@ public class AndroidUtils {
return Environment.getExternalStorageDirectory() + "/" + split[1];
} else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())) {
final String id = DocumentsContract.getDocumentId(uri);
uri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
if (!TextUtils.isEmpty(id)) {
if (id.startsWith("raw:")) {
return id.replaceFirst("raw:", "");
}
uri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
}
} else if ("com.android.providers.media.documents".equals(uri.getAuthority())) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
@ -164,18 +195,15 @@ public class AndroidUtils {
MediaStore.Images.Media.DATA
};
Cursor cursor = null;
try {
cursor = context.getContentResolver()
.query(uri, projection, selection, selectionArgs, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
if (cursor.moveToFirst()) {
return cursor.getString(column_index);
}
} catch (Exception e) {
cursor = context.getContentResolver()
.query(uri, projection, selection, selectionArgs, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
if (cursor.moveToFirst()) {
return cursor.getString(column_index);
}
} else if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
return null;
throw new IllegalArgumentException("Unable to decode the given uri to a file path: " + uri);
}
}