Android_data'在 getContentResolver 上不存在

Android _data' does not exist on getContentResolver

getColumnIndexOrThrow 引发异常

的原因可能是什么

java.lang.IllegalArgumentException:“_data”列不存在。可用列:[]

但是,如果您重命名文件并重试,它是否有效?

private static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {
        Cursor cursor = null;
        final String[] projection = {
                MediaStore.Files.FileColumns.DATA
        };
        try {
            cursor = context.getContentResolver().query(
                    uri, projection, selection, selectionArgs, null);
            if (cursor != null && cursor.moveToFirst()) {
                final int cindex = cursor.getColumnIndexOrThrow(projection[0]);
                return cursor.getString(cindex);
            }
        }
             catch (Exception e) {
                e.printStackTrace();
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

原始文件的目的是

content://com.sec.android.app.myfiles.FileProvider/device_storage/Download/myfile.pdf

但重命名后的文件显示为

content://0@media/external/file/588

MediaStore.Files.FileColumns.DATA 已弃用,column '_data' 不再存在。

Android Developer所述

This constant was deprecated in API level 29.

Apps may not have filesystem permissions to directly access this path. Instead of trying to open this path directly, apps should use ContentResolver#openFileDescriptor(Uri, String) to gain access.

如何使用 openFileDescriptor?

我尝试在跨应用程序中引入 2 个不同的广泛使用文件的示例

图像文件

if(uri==null)return;
ContentResolver contentResolver = getActivity().getContentResolver();
if(contentResolver==null)return;
ParcelFileDescriptor parcelFileDescriptor = contentResolver.openFileDescriptor(uri,"rw");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
if(fileDescriptor==null)return;
Bitmap bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor);
parcelFileDescriptor.close();

如何处理的例子很多bitmap

非图像文件

if(uri==null)return;
ContentResolver contentResolver = getActivity().getContentResolver();
if(contentResolver==null)return;
ParcelFileDescriptor parcelFileDescriptor = contentResolver.openFileDescriptor(uri,"rw");
FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
if(fileDescriptor==null)return;
FileInputStream fileInputStream = new FileInputStream(fileDescriptor);
FileOutputStream fileOutputStream = new FileOutputStream(fileDescriptor);
parcelFileDescriptor.close();

有很多例子说明如何处理FileInputStreamFileOutputStream

结论

尝试获得 absolute Path 没有任何意义,尽管没有必要除非提高安全性和隐私 issues.Indeed,Relative path 足以处理文件并且有 Abstract Representation implementationskernel ModeUser Mode 之间,可以将 Relative Path 映射到 Absolute Path 并且用户不需要知道。

openFileDescriptor 非常快并且兼容所有 android 版本