首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

在Android 10中从Uri获取绝对路径

在Android 10(API 级别 29)及更高版本中,获取文件的绝对路径变得更加复杂,因为访问外部存储的权限和方式发生了变化。特别是,Scoped Storage 的引入限制了应用对外部存储的直接访问。

以下是一些常见的方法来从 Uri 获取文件的绝对路径:

1. 使用 ContentResolverCursor

对于某些类型的 Uri,你可以使用 ContentResolverCursor 来查询文件的路径。

代码语言:javascript
复制
public String getRealPathFromURI(Context context, Uri uri) {
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = context.getContentResolver().query(uri, projection, null, null, null);
    if (cursor != null) {
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        String path = cursor.getString(column_index);
        cursor.close();
        return path;
    }
    return null;
}

2. 使用 DocumentFileFileDescriptor

对于 DocumentUri,你可以使用 DocumentFileFileDescriptor 来访问文件内容。

代码语言:javascript
复制
public String getFilePathFromURI(Context context, Uri uri) {
    if (DocumentsContract.isDocumentUri(context, uri)) {
        if (isExternalStorageDocument(uri)) {
            String docId = DocumentsContract.getDocumentId(uri);
            String[] split = docId.split(":");
            String type = split[0];

            if ("primary".equalsIgnoreCase(type)) {
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            }
        } else if (isDownloadsDocument(uri)) {
            String id = DocumentsContract.getDocumentId(uri);
            Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

            return getDataColumn(context, contentUri, null, null);
        } else if (isMediaDocument(uri)) {
            String docId = DocumentsContract.getDocumentId(uri);
            String[] split = docId.split(":");
            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;
            }

            String selection = "_id=?";
            String[] selectionArgs = new String[] {
                    split[1]
            };

            return getDataColumn(context, contentUri, selection, selectionArgs);
        }
    } else if ("content".equalsIgnoreCase(uri.getScheme())) {
        return getDataColumn(context, uri, null, null);
    } else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }

    return null;
}

public 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;
}

public boolean isExternalStorageDocument(Uri uri) {
    return "com.android.externalstorage.documents".equals(uri.getAuthority());
}

public boolean isDownloadsDocument(Uri uri) {
    return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}

public boolean isMediaDocument(Uri uri) {
    return "com.android.providers.media.documents".equals(uri.getAuthority());
}

3. 使用 FileUtils(适用于某些特定情况)

在某些情况下,你可以使用 FileUtils 类来处理文件的复制和路径获取。

代码语言:javascript
复制
public String getPathFromUri(Context context, Uri uri) {
    String filePath = null;
    if (DocumentsContract.isDocumentUri(context, uri)) {
        if (isExternalStorageDocument(uri)) {
            String docId = DocumentsContract.getDocumentId(uri);
            String[] split = docId.split(":");
            String type = split[0];
            if ("primary".equalsIgnoreCase(type)) {
                filePath = Environment.getExternalStorageDirectory() + "/" + split[1];
            }
        } else if (isDownloadsDocument(uri)) {
            String id = DocumentsContract.getDocumentId(uri);
            Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
            filePath = getDataColumn(context, contentUri, null, null);
        } else if (isMediaDocument(uri)) {
            String docId = DocumentsContract.getDocumentId(uri);
            String[] split = docId.split(":");
            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;
            }
            String selection = "_id=?";
            String[] selectionArgs = new String[] {
                    split[1]
            };
            filePath = getDataColumn(context, contentUri, selection, selectionArgs);
        }
    } else if ("content".equalsIgnoreCase(uri.getScheme())) {
        filePath = getDataColumn(context, uri, null, null);
    } else if ("file".equalsIgnoreCase(uri.getScheme())) {
        filePath = uri.getPath();
    }
    return filePath;
}

注意事项

  1. 权限:确保你的应用具有访问外部存储的权限。在Android 10及更高版本中,你可能需要请求 READ_EXTERNAL_STORAGEWRITE_EXTERNAL_STORAGE 权限。
  2. Scoped Storage:在Android 10及更高版本中,Scoped Storage 限制了对外部存储的访问。你可能需要使用 MediaStore API 或 SAF(Storage Access Framework)来访问文件。
  3. 兼容性:确保你的代码兼容不同的Android版本和设备。
页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

6分11秒

64从环信服务器获取所有群成员.avi

12分14秒

36从环信服务器获取联系人信息.avi

13分42秒

44从环信服务器获取群组联系人信息及条目的点击事件.avi

8分51秒

day04_Java基本语法/05-尚硅谷-Java语言基础-使用Scannner从键盘获取int型数据

17分26秒

day04_Java基本语法/06-尚硅谷-Java语言基础-使用Scannner从键盘获取多种类型数据

16分8秒

人工智能新途-用路由器集群模仿神经元集群

领券