In my previous work, I encountered the problem that urIs in different Android versions use different ways to obtain file paths.

Due to requirements, it is required to upload photos or select pictures from the album, and the pictures need to be compressed and the size cannot exceed 2M.

Pretty soon, the photo part is done. So the album in the selection of pictures is the same truth, should also be easy to solve.

The code for selecting the image is as follows:

intent = new Intent(Intent.ACTION_GET_CONTENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("image/*");
startActivityForResult(intent, FILE_CHOOSER_RESULT_CODE);
Copy the code

OnActivityResult (int requestCode, int resultCode, Intent Data)

What if you get the file by URI?

Now, for example, the URI of the content: / / media/extenral/images/media / 17766, and we need to get the corresponding file path.

if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) { Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.Media.DATA}, null, null, null); if (cursor ! = null) { if (cursor.moveToFirst()) { int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); if (columnIndex > -1) { path = cursor.getString(columnIndex); } } cursor.close(); } return path; }Copy the code

I thought everything was fine, but when I tried it on Android 4.4 and above, IT didn’t work at all. Because the Android 4.4 and above, on your mobile phone access to the URI into the content: / / com. Android. Will. Media. The documents/document/image % 3 a235700, It’s not the same type as we expected.

This is because on Android 4.4 and above, a DocumentUri is used to represent the URI of the obtained file.

So we need to adapt the DocumentUri again.

if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) { if (DocumentsContract.isDocumentUri(context, uri)) { if (isExternalStorageDocument(uri)) { // ExternalStorageProvider final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("primary".equalsIgnoreCase(type)) { path = Environment.getExternalStorageDirectory() + "/" + split[1]; return path; } } else if (isDownloadsDocument(uri)) { // DownloadsProvider final String id = DocumentsContract.getDocumentId(uri); final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); path = getDataColumn(context, contentUri, null, null); return path; } else if (isMediaDocument(uri)) { // MediaProvider 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]}; path = getDataColumn(context, contentUri, selection, selectionArgs); return path; } } } private 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; } private static boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); } private static boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents".equals(uri.getAuthority()); } private static boolean isMediaDocument(Uri uri) { return "com.android.providers.media.documents".equals(uri.getAuthority()); }Copy the code

Ok, the above code is still easy to read. This solves the problem for Android 4.4 and above. Add the URI starting with file:// as well:

if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) {
    path = uri.getPath();
    return path;
}
Copy the code

Perfect. Here’s the full FileUtils code to use:

public final class FileUtils { public static String getFilePathByUri(Context context, Uri uri) { String path = null; // If (contentresolver.scheme_file.equals (uri.getScheme())) {path = uri.getPath(); return path; } // Start with content:// Such as the content: / / media/extenral/images/media / 17766 if (ContentResolver. SCHEME_CONTENT. Equals (uri) getScheme () && Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.Media.DATA}, null, null, null); if (cursor ! = null) { if (cursor.moveToFirst()) { int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); if (columnIndex > -1) { path = cursor.getString(columnIndex); } } cursor.close(); } return path; } // 4.4 and later start with content://, Such as the content: / / com. Android. Will the media. The documents/document/image % 3 a235700 if (ContentResolver.SCHEME_CONTENT.equals(uri.getScheme()) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { if (DocumentsContract.isDocumentUri(context, uri)) { if (isExternalStorageDocument(uri)) { // ExternalStorageProvider final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; if ("primary".equalsIgnoreCase(type)) { path = Environment.getExternalStorageDirectory() + "/" + split[1]; return path; } } else if (isDownloadsDocument(uri)) { // DownloadsProvider final String id = DocumentsContract.getDocumentId(uri); final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(id)); path = getDataColumn(context, contentUri, null, null); return path; } else if (isMediaDocument(uri)) { // MediaProvider 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]}; path = getDataColumn(context, contentUri, selection, selectionArgs); return path; } } } return null; } private 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; } private static boolean isExternalStorageDocument(Uri uri) { return "com.android.externalstorage.documents".equals(uri.getAuthority()); } private static boolean isDownloadsDocument(Uri uri) { return "com.android.providers.downloads.documents".equals(uri.getAuthority()); } private static boolean isMediaDocument(Uri uri) { return "com.android.providers.media.documents".equals(uri.getAuthority()); }}Copy the code

That’s it. That’s it.

Good bye!