diff --git a/CHANGELOG.md b/CHANGELOG.md index 526c48bab..7ebe616ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Wikimedia Commons for Android +## v1.6 +- Bugfix for invalid images + ## v1.5 - Caches area and associated categories - Increased search radius for nearby categories diff --git a/commons/AndroidManifest.xml b/commons/AndroidManifest.xml index de1e407dc..9ee639ad6 100644 --- a/commons/AndroidManifest.xml +++ b/commons/AndroidManifest.xml @@ -1,11 +1,11 @@ + android:versionCode="22" + android:versionName="1.6" > + android:targetSdkVersion="23" /> diff --git a/commons/src/main/java/fr/free/nrw/commons/upload/FilePathConverter.java b/commons/src/main/java/fr/free/nrw/commons/upload/FilePathConverter.java deleted file mode 100644 index 9267bf9f8..000000000 --- a/commons/src/main/java/fr/free/nrw/commons/upload/FilePathConverter.java +++ /dev/null @@ -1,56 +0,0 @@ -package fr.free.nrw.commons.upload; - - -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.provider.DocumentsContract; -import android.provider.MediaStore; -import android.util.Log; - -public class FilePathConverter { - - private Uri uri; - private Context context; - - public FilePathConverter(Context context, Uri uri) { - this.context = context; - this.uri = uri; - } - - /** - * Gets file path of image from its Uri - * May return null - */ - public String getFilePath(){ - - String filePath =""; - - try { - // Will return "image:x*" - String wholeID = DocumentsContract.getDocumentId(uri); - - // Split at colon, use second item in the array - String id = wholeID.split(":")[1]; - String[] column = {MediaStore.Images.Media.DATA}; - - // where id is equal to - String sel = MediaStore.Images.Media._ID + "=?"; - Cursor cursor = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - column, sel, new String[]{id}, null); - - int columnIndex = cursor.getColumnIndex(column[0]); - - if (cursor.moveToFirst()) { - filePath = cursor.getString(columnIndex); - } - cursor.close(); - - Log.d("Image", "File path: " + filePath); - return filePath; - } catch (IllegalArgumentException e) { - Log.w("Image", e); - return null; - } - } -} diff --git a/commons/src/main/java/fr/free/nrw/commons/upload/FileUtils.java b/commons/src/main/java/fr/free/nrw/commons/upload/FileUtils.java new file mode 100644 index 000000000..c57b2bd53 --- /dev/null +++ b/commons/src/main/java/fr/free/nrw/commons/upload/FileUtils.java @@ -0,0 +1,138 @@ +package fr.free.nrw.commons.upload; + +import android.content.ContentUris; +import android.content.Context; +import android.database.Cursor; +import android.net.Uri; +import android.os.Build; +import android.os.Environment; +import android.provider.MediaStore; +import android.provider.DocumentsContract; + +public class FileUtils { + + /** + * Get a file path from a Uri. This will get the the path for Storage Access + * Framework Documents, as well as the _data field for the MediaStore and + * other file-based ContentProviders. + * + * @param context The context. + * @param uri The Uri to query. + * @author paulburke + */ + public static String getPath(final Context context, final Uri uri) { + + final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; + + // DocumentProvider + if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { + // ExternalStorageProvider + if (isExternalStorageDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + if ("primary".equalsIgnoreCase(type)) { + return Environment.getExternalStorageDirectory() + "/" + split[1]; + } + } + // DownloadsProvider + else if (isDownloadsDocument(uri)) { + + final String id = DocumentsContract.getDocumentId(uri); + final Uri contentUri = ContentUris.withAppendedId( + Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); + + return getDataColumn(context, contentUri, null, null); + } + // MediaProvider + else if (isMediaDocument(uri)) { + final String docId = DocumentsContract.getDocumentId(uri); + final String[] split = docId.split(":"); + final String type = split[0]; + + Uri contentUri = null; + if ("image".equals(type)) { + contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI; + } else if ("video".equals(type)) { + contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI; + } else if ("audio".equals(type)) { + contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI; + } + + final String selection = "_id=?"; + final String[] selectionArgs = new String[]{ + split[1] + }; + + return getDataColumn(context, contentUri, selection, selectionArgs); + } + } + // MediaStore (and general) + else if ("content".equalsIgnoreCase(uri.getScheme())) { + return getDataColumn(context, uri, null, null); + } + // File + else if ("file".equalsIgnoreCase(uri.getScheme())) { + return uri.getPath(); + } + + return null; + } + + /** + * Get the value of the data column for this Uri. This is useful for + * MediaStore Uris, and other file-based ContentProviders. + * + * @param context The context. + * @param uri The Uri to query. + * @param selection (Optional) Filter used in the query. + * @param selectionArgs (Optional) Selection arguments used in the query. + * @return The value of the _data column, which is typically a file path. + */ + public static String getDataColumn(Context context, Uri uri, String selection, + String[] selectionArgs) { + + Cursor cursor = null; + final String column = "_data"; + final String[] projection = { + column + }; + + try { + 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; + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is ExternalStorageProvider. + */ + public static boolean isExternalStorageDocument(Uri uri) { + return "com.android.externalstorage.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is DownloadsProvider. + */ + public static boolean isDownloadsDocument(Uri uri) { + return "com.android.providers.downloads.documents".equals(uri.getAuthority()); + } + + /** + * @param uri The Uri to check. + * @return Whether the Uri authority is MediaProvider. + */ + public static boolean isMediaDocument(Uri uri) { + return "com.android.providers.media.documents".equals(uri.getAuthority()); + } +} \ No newline at end of file diff --git a/commons/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java b/commons/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java index c6eb6698b..e1d454fe9 100644 --- a/commons/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java +++ b/commons/src/main/java/fr/free/nrw/commons/upload/ShareActivity.java @@ -1,9 +1,11 @@ package fr.free.nrw.commons.upload; import android.content.*; +import android.database.Cursor; import android.os.*; import com.nostra13.universalimageloader.core.ImageLoader; import android.net.*; +import android.provider.MediaStore; import android.support.v4.app.NavUtils; import com.actionbarsherlock.view.MenuItem; @@ -153,7 +155,6 @@ public class ShareActivity .add(R.id.single_upload_fragment_container, shareView, "shareView") .commit(); } - uploadController.prepareService(); } @@ -187,13 +188,16 @@ public class ShareActivity } mediaUriString = mediaUri.toString(); + ImageLoader.getInstance().displayImage(mediaUriString, backgroundImageView); + Log.d(TAG, "Uri: " + mediaUriString); + Log.d(TAG, "Ext storage dir: " + Environment.getExternalStorageDirectory()); + //convert image Uri to file path - FilePathConverter uriObj = new FilePathConverter(this, mediaUri); - String filePath = uriObj.getFilePath(); + String filePath = FileUtils.getPath(this, mediaUri); + Log.d(TAG, "Filepath: " + filePath); - - if (filePath != null) { + if (filePath != null && !filePath.equals("")) { //extract the coordinates of image in decimal degrees Log.d(TAG, "Calling GPSExtractor"); GPSExtractor imageObj = new GPSExtractor(filePath); @@ -223,16 +227,12 @@ public class ShareActivity Log.d(TAG, "Cache found, setting categoryList in MwVolleyApi to " + displayCatList.toString()); MwVolleyApi.setGpsCat(displayCatList); } - } } - ImageLoader.getInstance().displayImage(mediaUriString, backgroundImageView); - if(savedInstanceState != null) { contribution = savedInstanceState.getParcelable("contribution"); } - requestAuthToken(); }