从 Uri 获取真实路径 - android Q 中不推荐使用 DATA
Get real path from Uri - DATA is deprecated in android Q
我成功实施了一种方法,通过从 ACTION_PICK
意图返回的 Uri
从图库中检索图像的真实路径。这是一个示例:
// getRealPathFromURI(intent.getData());
private String getRealPathFromURI(Uri contentURI) {
String result;
Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
if (cursor == null) { // Source is Dropbox or other similar local file path
result = contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
}
return result;
}
就这样answer.
最近将 compileSdkVersion
更新为 29
,显然每个人使用的 DATA
属性是 deprecated。
在官方文档中,他们建议改用 FileDescriptor,问题是我不知道具体如何。
我唯一找到的是这个 question。不过在那里没有找到合适的答案。
请使用建议的方式或任何其他方式帮助我解决这个弃用问题。
谢谢。
更新:
使用 @CommonsWare's 并使用 context.getContentResolver.openInputStream(Uri)
.
将返回的 Uri(用户选择的图像)复制到本地目录
甚至尝试从 Google 驱动器中检索文件 - 而且成功了。唯一的问题是它花费了很长时间(5MB 文件大约需要 20 秒)。
作为奖励,我获准删除外部存储权限,使用应用程序的本地目录不需要该权限。
我没有更多的外部路径!
I'm successfully implementing a method for retrieving the real path of an image from gallery by the Uri returned from ACTION_PICK intent.
该代码可能不适用于所有图像。 DATA
不需要指向您可以访问的文件系统路径。
Just like this answer.
FWIW,this 是我对这个问题的回答。
Only thing i found is this question. Didn't find a proper answer there though.
该技术不是特别好,将不再有效,因为 Android 已锁定 /proc
。
In the official docs, they recommend to use FileDescriptor instead, problem is i don't know exactly how.
更一般的概念是,你用ContentResolver
来配合Uri
,不管你得到的是InputStream
(openInputStream()
),OutputStream
(openOutputStream()
),或 FileDescriptor
。使用这些东西消费内容。如果您有一些 API 绝对需要一个文件,请将内容(例如,从 InputStream
)复制到您控制的文件(例如,在 getCacheDir()
中)。
作为奖励,现在您的代码也可以使用存储访问框架(例如,ACTION_OPEN_DOCUMENT
)和互联网(例如,OkHttp),如果以及何时有用的话。
一周前我也遇到过这个问题。
我的解决方案是从 URI 创建一个 InputStream
,然后通过复制输入流的内容从中创建一个 OutputStream
。
注意:您可以使用异步调用来调用此方法,因为复制非常大的文件可能会有一些延迟,并且您不想阻止您的 UI
@Nullable
public static String createCopyAndReturnRealPath(
@NonNull Context context, @NonNull Uri uri) {
final ContentResolver contentResolver = context.getContentResolver();
if (contentResolver == null)
return null;
// Create file path inside app's data dir
String filePath = context.getApplicationInfo().dataDir + File.separator
+ System.currentTimeMillis();
File file = new File(filePath);
try {
InputStream inputStream = contentResolver.openInputStream(uri);
if (inputStream == null)
return null;
OutputStream outputStream = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len;
while ((len = inputStream.read(buf)) > 0)
outputStream.write(buf, 0, len);
outputStream.close();
inputStream.close();
} catch (IOException ignore) {
return null;
}
return file.getAbsolutePath();
}
我成功实施了一种方法,通过从 ACTION_PICK
意图返回的 Uri
从图库中检索图像的真实路径。这是一个示例:
// getRealPathFromURI(intent.getData());
private String getRealPathFromURI(Uri contentURI) {
String result;
Cursor cursor = getContentResolver().query(contentURI, null, null, null, null);
if (cursor == null) { // Source is Dropbox or other similar local file path
result = contentURI.getPath();
} else {
cursor.moveToFirst();
int idx = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);
result = cursor.getString(idx);
cursor.close();
}
return result;
}
就这样answer.
最近将 compileSdkVersion
更新为 29
,显然每个人使用的 属性是 deprecated。
在官方文档中,他们建议改用 FileDescriptor,问题是我不知道具体如何。DATA
我唯一找到的是这个 question。不过在那里没有找到合适的答案。
请使用建议的方式或任何其他方式帮助我解决这个弃用问题。
谢谢。
更新:
使用 @CommonsWare's context.getContentResolver.openInputStream(Uri)
.
甚至尝试从 Google 驱动器中检索文件 - 而且成功了。唯一的问题是它花费了很长时间(5MB 文件大约需要 20 秒)。
作为奖励,我获准删除外部存储权限,使用应用程序的本地目录不需要该权限。
我没有更多的外部路径!
I'm successfully implementing a method for retrieving the real path of an image from gallery by the Uri returned from ACTION_PICK intent.
该代码可能不适用于所有图像。 DATA
不需要指向您可以访问的文件系统路径。
Just like this answer.
FWIW,this 是我对这个问题的回答。
Only thing i found is this question. Didn't find a proper answer there though.
该技术不是特别好,将不再有效,因为 Android 已锁定 /proc
。
In the official docs, they recommend to use FileDescriptor instead, problem is i don't know exactly how.
更一般的概念是,你用ContentResolver
来配合Uri
,不管你得到的是InputStream
(openInputStream()
),OutputStream
(openOutputStream()
),或 FileDescriptor
。使用这些东西消费内容。如果您有一些 API 绝对需要一个文件,请将内容(例如,从 InputStream
)复制到您控制的文件(例如,在 getCacheDir()
中)。
作为奖励,现在您的代码也可以使用存储访问框架(例如,ACTION_OPEN_DOCUMENT
)和互联网(例如,OkHttp),如果以及何时有用的话。
一周前我也遇到过这个问题。
我的解决方案是从 URI 创建一个 InputStream
,然后通过复制输入流的内容从中创建一个 OutputStream
。
注意:您可以使用异步调用来调用此方法,因为复制非常大的文件可能会有一些延迟,并且您不想阻止您的 UI
@Nullable
public static String createCopyAndReturnRealPath(
@NonNull Context context, @NonNull Uri uri) {
final ContentResolver contentResolver = context.getContentResolver();
if (contentResolver == null)
return null;
// Create file path inside app's data dir
String filePath = context.getApplicationInfo().dataDir + File.separator
+ System.currentTimeMillis();
File file = new File(filePath);
try {
InputStream inputStream = contentResolver.openInputStream(uri);
if (inputStream == null)
return null;
OutputStream outputStream = new FileOutputStream(file);
byte[] buf = new byte[1024];
int len;
while ((len = inputStream.read(buf)) > 0)
outputStream.write(buf, 0, len);
outputStream.close();
inputStream.close();
} catch (IOException ignore) {
return null;
}
return file.getAbsolutePath();
}