【问题标题】:ACTION_PICK image picker returns diffrent uri formatsACTION_PICK 图像选择器返回不同的 uri 格式
【发布时间】:2016-09-14 11:59:38
【问题描述】:

我正在使用图像选择器选择图像,然后将此图像上传到服务器。

我的代码在所有安卓设备上都能完美运行除了小米 手机。

For all device Uri returned is of type : content://media/external/images/media/523

For Mi devices Uri returned is of type:file:///storage/emulated/0/DCIM/Camera/IMG_20160912_160415.jpg

Cursor cursor = context.getContentResolver().query() 返回 如果 uri 的格式不是 content://*

,则为 null
 private void pickImage() {

        Intent photoPickerIntent = new Intent(
                Intent.ACTION_PICK,
                android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
        photoPickerIntent.setType("image/*");

        startActivityForResult(photoPickerIntent, 0);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);



        if (resultCode == RESULT_OK) {
            Uri selectedImageUri = data.getData();
            if (selectedImageUri != null) {
                selectedImagePath = Utils.getImagePath(selectedImageUri, DepositBankWireActivity.this);
                Log.i("uplaod", "selectedImagePath" + selectedImagePath);
}
}

 public static String getImagePath(Uri uri, Context context) {
        Log.i("getImagePath",""+uri+" mime "+getMimeType(uri,context));

            String[] projection = {MediaStore.MediaColumns.DATA,
                    MediaStore.Images.ImageColumns.ORIENTATION};
            Cursor cursor = context.getContentResolver().query(uri, projection, null, null,
                    null);
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);

    }

有没有一种标准的方法来实现图像选择器,它返回 来自 uri 的正确图像路径,例如 /storage/emulated/0/Pictures/Screenshots/test.png 用于上传。

【问题讨论】:

  • 使用getContentResolver().openInputStream(yourUri)
  • 小米手机在此类事件中总是会出现问题,并且在大多数情况下可用的解决方案非常少。
  • @pskink 如何从输入流中获取图像路径。请帮忙。谢谢
  • 路径?你需要什么路径?
  • @pskink 我正在使用一个需要文件路径的库,例如 /storage/emulated/0/Pictures/Screenshots/test.png 。这个库压缩图像并在服务器上进行多部分图像上传。

标签: android uri android-gallery


【解决方案1】:

MediaStoreDATA 列不需要为您提供可以使用的文件系统路径。例如,图像可能位于 Android 4.4+ 上的可移动存储上,MediaStore 可以访问,但您不能。 MediaStore 也可以在其索引中包含不是设备本地的图像,而是来自 Google 照片之类的服务(有人告诉我)。

所以,你的第一步是摆脱getImagePath(),因为它不可靠。

最简单且性能最高的解决方案是找到一种无需文件系统访问即可“压缩图像并在服务器上 [执行] 多部分图像上传”的方法。例如,您可以通过openInputStream() 上的ContentResolver 访问InputStream,这将适用于您的问题中显示的两种Uri。使用InputStream 找到一些方法来完成您的工作。

如果您确定这是不可能的,则无论如何您都需要获取 InputStream 并制作内容的本地副本(例如,在 getCacheDir() 中)。然后,使用您的本地副本,完成后将其删除。

【讨论】:

  • 除了 CommonsWare 所说的你可以使用 File#createTempFile 创建一个 tmp 文件
  • 是否有可靠的第三种选择可以准确地保留图像?我实际上是在执行此答案中的建议,但决定放弃它的原因很简单,因为它不能确保数据完整性(在我的情况下是照片)。由于我只收到InputStream 没有关于照片原始编码的信息,因此我创建的图像的质量可能低于原始图像,具体取决于我使用的 JPEG 压缩设置。
  • 另外,复制原始数据绝对高效,尤其是在涉及额外的资源密集型步骤时,例如照片的 JPEG 压缩。
  • 我最终使用了一种混合方法:我尝试先将 URI 转换为文件系统路径,如果失败,则返回读取 InputStream,将其转换为 JPEG 图像并上传。这应该是健壮的,同时尽可能保留原始数据。要转换 URI => 路径,我正在使用这个实用程序类,它似乎可以处理很多边缘情况:github.com/iPaulPro/aFileChooser/blob/master/aFileChooser/src/…
  • @VickyChijwani:“因为我只得到一个 InputStream,没有关于照片原始编码的信息”——你会得到照片的原始字节(例如,JPEG)。 JPEG 将包含 JPEG 编码的详细信息。 “复制原始数据绝对不是高性能的” - 然后不要复制数据。 “我正在使用这个似乎可以处理很多边缘情况的实用程序类”——它处理的情况很少,就整个 Android 生态系统而言,可能会导致您的应用程序崩溃(例如,推断的路径已启用可移动存储)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-17
  • 2021-04-06
  • 1970-01-01
  • 2018-03-16
相关资源
最近更新 更多