Combine the above answer,you should try catch the method getDataColumn() cursor.getColumnIndexOrThrow(column)
,otherwise,It will cause the IllegalArgumentException
in some device.
Caused by java.lang.IllegalArgumentException: column '_data' does not exist
at android.database.AbstractCursor.getColumnIndexOrThrow + 333(AbstractCursor.java:333)
at android.database.CursorWrapper.getColumnIndexOrThrow + 87(CursorWrapper.java:87)
at com.alo7.android.utils.strings.UriToPathUtil.getDataColumn + 108(UriToPathUtil.java:108)
at com.alo7.android.utils.strings.UriToPathUtil.getPath + 77(UriToPathUtil.java:77)
at com.alo7.android.student.activity.image.ImageControllerActivity.onActivityResult + 241(ImageControllerActivity.java:241)
at android.app.Activity.dispatchActivityResult + 7701(Activity.java:7701)
at android.app.ActivityThread.deliverResults + 5037(ActivityThread.java:5037)
at android.app.ActivityThread.handleSendResult + 5084(ActivityThread.java:5084)
at android.app.ActivityThread.-wrap20(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage + 2053(ActivityThread.java:2053)
at android.os.Handler.dispatchMessage + 108(Handler.java:108)
at android.os.Looper.loop + 166(Looper.java:166)
at android.app.ActivityThread.main + 7529(ActivityThread.java:7529)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run + 245(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main + 921(ZygoteInit.java:921)
For make the answer better.you can use like this,when cause the exception.through copy file to solve it.
public class UriToPathUtil {
/**
* 兼容各种Provider返回的Uri获取真实的文件路径
* 例如:content://media/external/images/media/2617144
* content://com.android.providers.media.documents/document/image%3A11746等
* @param context The context.
* @param uri The Uri to query.
* @author paulburke
*/
@RequiresApi(api = Build.VERSION_CODES.KITKAT)
public static String getPath(final Context context, final Uri uri) {
final boolean isAboveKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
// DocumentProvider
if(isAboveKitKat && 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];
}
// TODO handle non-primary volumes
}
// 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.
*/
private static String getDataColumn(Context context, Uri uri, String selection,
String[] selectionArgs) {
Cursor cursor = null;
final String column = MediaStore.Images.Media.DATA;
final String[] projection = {column};
try {
cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
null);
if(cursor != null && cursor.moveToFirst()) {
try {
final int column_index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(column_index);
} catch(IllegalArgumentException exception) {
return getFilePathFromURI(context, uri);
}
}
} finally {
if(cursor != null) cursor.close();
}
return null;
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
private 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.
*/
private 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.
*/
private static boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
// 部分文件可能无法读取到正确的URI 所以复制临时文件作为传输
private static String getFilePathFromURI(Context context, Uri contentUri) {
// copy file and send new file path
String fileName = getFileName(contentUri);
if(!TextUtils.isEmpty(fileName)) {
File copyFile = new File(context.getFilesDir() + File.separator + fileName);
copy(context, contentUri, copyFile);
return copyFile.getAbsolutePath();
}
return null;
}
private static String getFileName(Uri uri) {
if(uri == null) return null;
String fileName = null;
String path = uri.getPath();
if(path == null) return null;
int cut = path.lastIndexOf('/');
if(cut != -1) {
fileName = path.substring(cut + 1);
}
return fileName;
}
private static void copy(Context context, Uri srcUri, File dstFile) {
try {
InputStream inputStream = context.getContentResolver().openInputStream(srcUri);
if(inputStream == null) return;
OutputStream outputStream = new FileOutputStream(dstFile);
copyFile(inputStream, outputStream);
inputStream.close();
outputStream.close();
} catch(IOException e) {
e.printStackTrace();
}
}
private static void copyFile(InputStream inputStream, OutputStream outputStream)
throws IOException {
int BUFFER_SIZE = 1024 * 2;
byte[] buffer = new byte[BUFFER_SIZE];
BufferedInputStream in = new BufferedInputStream(inputStream, BUFFER_SIZE);
BufferedOutputStream out = new BufferedOutputStream(outputStream, BUFFER_SIZE);
int n;
try {
while((n = in.read(buffer, 0, BUFFER_SIZE)) != -1) {
out.write(buffer, 0, n);
}
out.flush();
} finally {
try {
out.close();
in.close();
} catch(IOException e) {
e.printStackTrace();
}
}
}
}