Android 从相册选取图片获取其真实绝对路径的问题问询
问题根源
Android 4.4(API 19)之后,通过ACTION_GET_CONTENT从系统相册选取资源返回的是内容URI(以content://开头),而非传统的文件URI,直接调用Uri.getPath()获取到的只是内容提供者的虚拟标识,不是本地存储的真实文件路径,这就是你拿到/document/image:5632这类结果的原因。
适配步骤
- 首先添加必要权限,在
AndroidManifest.xml中声明存储读取权限:
<!-- Android 12及以下 --> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" /> <!-- Android 13及以上 --> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
注意:需要先动态申请对应权限,再调用相册选图逻辑,否则会出现权限拒绝导致无法获取路径。
- 新增URI转真实路径的工具方法:
public String getRealPathFromUri(Context context, Uri contentUri) { String filePath = null; String[] projection = {MediaStore.Images.Media.DATA}; Cursor cursor = context.getContentResolver().query(contentUri, projection, null, null, null); if (cursor != null) { if (cursor.moveToFirst()) { int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); filePath = cursor.getString(columnIndex); } cursor.close(); } // 适配系统媒体文档类特殊URI场景 if (filePath == null && DocumentsContract.isDocumentUri(context, contentUri)) { String docId = DocumentsContract.getDocumentId(contentUri); if ("com.android.providers.media.documents".equals(contentUri.getAuthority())) { String id = docId.split(":")[1]; String selection = MediaStore.Images.Media._ID + "=?"; String[] selectionArgs = new String[]{id}; Cursor cursor2 = context.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, projection, selection, selectionArgs, null); if (cursor2 != null) { if (cursor2.moveToFirst()) { filePath = cursor2.getString(cursor2.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)); } cursor2.close(); } } } return filePath; }
- 修改选图结果处理逻辑:
Uri imgUri = data.getData(); if (imgUri != null) { ivImage.setImageURI(imgUri); // 替换原有路径获取逻辑 mSelectedImagePath = getRealPathFromUri(this, imgUri); if (mSelectedImagePath != null) { Toast.makeText(AddPostActivity.this, mSelectedImagePath, Toast.LENGTH_LONG).show(); } else { // 部分Android 10+设备因分区存储限制无法直接获取公共目录路径,可复制文件到应用私有目录后再获取路径 Toast.makeText(AddPostActivity.this, "获取路径失败", Toast.LENGTH_SHORT).show(); } }
补充说明
如果你的应用目标适配Android 10(API 29)及以上版本,系统限制了公共目录的直接访问,如果你需要长期访问该图片,更稳妥的方案是将图片复制到应用私有目录(如context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)),再将私有目录下的文件路径存入数据库,不会有权限变更导致后续无法访问的问题。
内容的提问来源于stack exchange,提问作者SS-Salt
相关产品推荐
相关产品推荐

