As I am supporting my app to Kitkat version, now in this the way of retrieve file from gallery was different.
I have preferred this Android Gallery on KitKat returns
Here is one way to access the Absolute path after selecting file.
After getting data in new URI format for KK(KitKat) like this way
content://com.android.providers.media.documents/document/image:2505
Just extract ID of your document
if(requestCode == GALLERY_KITKAT_INTENT_CALLED && resultCode == RESULT_OK){
Uri originalUri = data.getData();
final int takeFlags = data.getFlags()
& (Intent.FLAG_GRANT_READ_URI_PERMISSION
| Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
// Check for the freshest data.
getContentResolver().takePersistableUriPermission(originalUri, takeFlags);
/* now extract ID from Uri path using getLastPathSegment() and then split with ":"
then call get Uri to for Internal storage or External storage for media I have used getUri()
*/
String id = originalUri.getLastPathSegment().split(":")[1];
final String[] imageColumns = {MediaStore.Images.Media.DATA };
final String imageOrderBy = null;
Uri uri = getUri();
String selectedImagePath = "path";
Cursor imageCursor = managedQuery(uri, imageColumns,
MediaStore.Images.Media._ID + "="+id, null, imageOrderBy);
if (imageCursor.moveToFirst()) {
selectedImagePath = imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA));
}
Log.e("path",selectedImagePath ); // use selectedImagePath
}else if() {
// for older version use existing code here
}
// By using this method get the Uri of Internal/External Storage for Media
private Uri getUri() {
String state = Environment.getExternalStorageState();
if(!state.equalsIgnoreCase(Environment.MEDIA_MOUNTED))
return MediaStore.Images.Media.INTERNAL_CONTENT_URI;
return MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
}
Pratik's solution helped me alot. Following is the version which works for me in Kitkat 4.4.2. Three things which i changed are
1) Using content resolver to get the path
2) originalUri.getLastPathSegment().split(":")[1] gives me index out of bound so i'm using index 0 instead.Its been working so far
3) Removed takeflags and check for freshest data as we are filtering the cursor with id.
try {
Uri originalUri = data.getData();
String pathsegment[] = originalUri.getLastPathSegment().split(":");
String id = pathsegment[0];
final String[] imageColumns = { MediaStore.Images.Media.DATA };
final String imageOrderBy = null;
Uri uri = getUri();
Cursor imageCursor = activity.getContentResolver().query(uri, imageColumns,
MediaStore.Images.Media._ID + "=" + id, null, null);
if (imageCursor.moveToFirst()) {
value = imageCursor.getString(imageCursor.getColumnIndex(MediaStore.Images.Media.DATA));
}
} catch (Exception e) {
Toast.makeText(activity, "Failed to get image", Toast.LENGTH_LONG).show();
}
Perfectly working solution:
package utils;
/**
* Created by layer on 4/21/2015.
*/
import android.annotation.TargetApi;
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.DocumentsContract;
import android.provider.MediaStore;
public class ImageFilePath {
/**
* Method for return file path of Gallery image
*
* @param context
* @param uri
* @return path of the selected image file from gallery
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
public static String getPath(final Context context, final Uri uri) {
// check here to KITKAT or new version
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 the remote address
if (isGooglePhotosUri(uri))
return uri.getLastPathSegment();
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 index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(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());
}
/**
* @param uri
* The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
public static boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri
.getAuthority());
}
}
https://github.com/layerlre/Android-Utility-Class/blob/master/utils/ImageFilePath.java
Hope works for you.
Bitmap bitmap = MediaStore.Images.Media
.getBitmap(getActivity().getContentResolver(), uri);
I hope that this will help you.