1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-07-11 16:04:05 +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() { private String getAutoExportLocationSummary() {
String autoExportLocation = GBApplication.getPrefs().getString(GBPrefs.AUTO_EXPORT_LOCATION, null); String autoExportLocation = GBApplication.getPrefs().getString(GBPrefs.AUTO_EXPORT_LOCATION, null);
@ -386,20 +386,16 @@ public class SettingsActivity extends AbstractSettingsActivity {
} }
Uri uri = Uri.parse(autoExportLocation); Uri uri = Uri.parse(autoExportLocation);
try { try {
String filePath = AndroidUtils.getFilePath(getApplicationContext(), uri); return AndroidUtils.getFilePath(getApplicationContext(), uri);
if (filePath != null) { } catch (IllegalArgumentException e) {
return filePath; 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 ""; return "";
} }

View File

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