Android使用Uri和位图缩小图库中的图像

Android使用Uri和位图缩小图库中的图像,android,bitmap,uri,android-contentprovider,filenotfoundexception,Android,Bitmap,Uri,Android Contentprovider,Filenotfoundexception,在尝试将图像转换为位图以显著缩小图像时,我收到FileNotFound异常 我正在检索用户从图库中选择的图像,如下所示 public static void GET_PICTURE_FROM_GALLERY (Activity activity) { Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT); getIntent.setType("image/*"); Intent pickIntent = new

在尝试将图像转换为位图以显著缩小图像时,我收到FileNotFound异常

我正在检索用户从图库中选择的图像,如下所示

public static void GET_PICTURE_FROM_GALLERY (Activity activity)
{
    Intent getIntent = new Intent(Intent.ACTION_GET_CONTENT);
    getIntent.setType("image/*");

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

    Intent chooserIntent = Intent.createChooser(getIntent, "Select Image");
    chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {pickIntent});

    activity.startActivityForResult(chooserIntent, REQUEST_SELECT_PHOTO);
}
然后,当用户完成拾取时:

public void setChosenPicture (Activity activity, Intent data)
{
    if(editingViewHelper != null)
    {
        String[] filePathColumn = {MediaStore.Images.Media.DATA};

        Uri selectedImage = data.getData();

        System.out.println("GOT URI: " + selectedImage.toString());

        Cursor cursor = activity.getContentResolver().query(selectedImage, filePathColumn, null, null, null);
        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        editingViewHelper.holder.tempUri = Uri.parse(cursor.getString(columnIndex));

        System.out.println("SET URI: " + editingViewHelper.holder.tempUri.toString());

        cursor.close();

        editingViewHelper.holder.imageView.setImageURI(editingViewHelper.holder.tempUri);
    }
}
这将产生以下结果:

GOT URI: content://media/external/images/media/110
SET URI: /storage/emulated/0/DIRECTORY/IMG_20170606_154512_1664512804.jpg
现在这很好用,但前提是我调用imageView.setImageUri(uri);然而,我不能这样做,因为我必须缩小图像的比例,这样应用程序就不会使用大量的内存。要做到这一点,我有这个方法

public static Bitmap decodeUri(Context c, Uri uri, final int requiredSize)
{
    System.out.println("URI: " + uri.toString());

    try
    {
        BitmapFactory.Options o = new BitmapFactory.Options();
        o.inJustDecodeBounds = true;

 //This line is where the error occurs. 
     BitmapFactory.decodeStream(c.getContentResolver().openInputStream(uri), null, o);  

        int width_tmp = o.outWidth;
        int height_tmp = o.outHeight;
        int scale = 1;

        while(true)
        {
            if(width_tmp / 2 < requiredSize || height_tmp / 2 < requiredSize)
                break;

            width_tmp /= 2;
            height_tmp /= 2;
            scale *= 2;
        }

        BitmapFactory.Options o2 = new BitmapFactory.Options();
        o2.inSampleSize = scale;

        return BitmapFactory.decodeStream(c.getContentResolver().openInputStream(uri), null, o2);
    }
    catch (FileNotFoundException e)
    {
        e.printStackTrace();
        return null;
    }
}
现在奇怪的是,这个方法确实有效,但只有当它从我的应用程序中拍摄的照片中传递Uri时。下面是最后一个方法的输出示例,它不会抛出任何错误

Uri: content://com.subliroid.dinnerdecider.provider/external_files/Pictures/DIRECTORY/IMG_20170606_154512_1664512804.jpg

我可以使用这两种类型的uri调用imageView.setImageUri(uri),但我不能缩小其中一种类型。我可以忽略这一点,直到我开始在真正的设备上测试我的应用程序,与emulator拍摄的小设备相比,这些设备可以拍摄4k+的照片

到目前为止,最简单的方法是删除大部分代码并使用现有的。谷歌推荐;我用过,还有很多其他的

然后,当用户完成拾取时:

public void setChosenPicture (Activity activity, Intent data)
{
    if(editingViewHelper != null)
    {
        String[] filePathColumn = {MediaStore.Images.Media.DATA};

        Uri selectedImage = data.getData();

        System.out.println("GOT URI: " + selectedImage.toString());

        Cursor cursor = activity.getContentResolver().query(selectedImage, filePathColumn, null, null, null);
        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        editingViewHelper.holder.tempUri = Uri.parse(cursor.getString(columnIndex));

        System.out.println("SET URI: " + editingViewHelper.holder.tempUri.toString());

        cursor.close();

        editingViewHelper.holder.imageView.setImageURI(editingViewHelper.holder.tempUri);
    }
}
query()
调用在许多情况下都会失败(可移动存储上的图像,用户选择的应用程序可能是您在响应您的
意图时所不期望的,等等)

最后,我有以下.output FileNotFound异常

URI: /storage/emulated/0/DIRECTORY/IMG_20170606_154512_1664512804.jpg
java.io.FileNotFoundException: No content provider: /storage/emulated/0/DIRECTORY/IMG_20170606_154512_1664512804.jpg
您不必要地创建了一个新的
Uri
,但这样做是错误的,因为传递到
Uri.parse()
的值没有方案


如果您不打算使用现有的、已经调试过的代码(即图像加载库),请将
Uri
传递到位图缩放代码中。然后,在当前实现中冻结UI时,确定何时将大部分逻辑移出主应用程序线程。

到目前为止,最简单的方法是删除大部分代码并使用现有的。谷歌推荐;我用过,还有很多其他的

然后,当用户完成拾取时:

public void setChosenPicture (Activity activity, Intent data)
{
    if(editingViewHelper != null)
    {
        String[] filePathColumn = {MediaStore.Images.Media.DATA};

        Uri selectedImage = data.getData();

        System.out.println("GOT URI: " + selectedImage.toString());

        Cursor cursor = activity.getContentResolver().query(selectedImage, filePathColumn, null, null, null);
        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
        editingViewHelper.holder.tempUri = Uri.parse(cursor.getString(columnIndex));

        System.out.println("SET URI: " + editingViewHelper.holder.tempUri.toString());

        cursor.close();

        editingViewHelper.holder.imageView.setImageURI(editingViewHelper.holder.tempUri);
    }
}
query()
调用在许多情况下都会失败(可移动存储上的图像,用户选择的应用程序可能是您在响应您的
意图时所不期望的,等等)

最后,我有以下.output FileNotFound异常

URI: /storage/emulated/0/DIRECTORY/IMG_20170606_154512_1664512804.jpg
java.io.FileNotFoundException: No content provider: /storage/emulated/0/DIRECTORY/IMG_20170606_154512_1664512804.jpg
您不必要地创建了一个新的
Uri
,但这样做是错误的,因为传递到
Uri.parse()
的值没有方案

如果您不打算使用现有的、已经调试过的代码(即图像加载库),请将
Uri
传递到位图缩放代码中。然后,在当前实现中冻结UI时,确定何时将此逻辑的大部分移出主应用程序线程