Android 设置 Uri 时出现坏位图错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3681714/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 11:19:48  来源:igfitidea点击:

bad bitmap error when setting Uri

android

提问by retnuh

I would like to make an ImageView display an image on a website. So I create a new ImageView and execute imgView.setImageURI(uri);

我想让 ImageView 在网站上显示图像。所以我创建了一个新的 ImageView 并执行imgView.setImageURI(uri);

When I launch the app the image does not appear and I get the error, "resolveUri failed on bad Bitmap Uri (uri)".

当我启动应用程序时,图像没有出现,并且出现错误“resolveUri 在坏位图 Uri (uri) 上失败”。

Any ideas on how to solve this?

关于如何解决这个问题的任何想法?

采纳答案by Alex Volovoy

You need to download the image and then set it as bitmap. Here is one of the many examples: http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html

您需要下载图像,然后将其设置为位图。这是众多示例之一:http: //android-developers.blogspot.com/2010/07/multithreading-for-performance.html

回答by paxdiablo

If it's not a content URI, this linkmay help. It seems to indicate that imgView.setImageURI()should not be used for regular URIs. Copying in the relevant bit:

如果它不是内容 URI,则此链接可能会有所帮助。它似乎表明imgView.setImageURI()不应用于常规 URI。复制相关位:

Yes, ImageView.setImageURI(ContentURI uri)works, but it is for content URIs particular to the Android platform, not URIs specifying Internet resources. The convention is applied to binary objects (images, for example) which cannot be exposed directly through a ContentProvider's Cursor methods. Instead, a String reference is used to reference a distinct content URI, which can be resolved by a separate query against the content provider. The setImageURI method is simply a wrapper to perform those steps for you.

I have tested this usage of setImageView, and it does work as expected. For your usage, though, I'd look at BitmapFactory.decodeStream()and URL.openStream().

是的,ImageView.setImageURI(ContentURI uri)有效,但它适用于 Android 平台特有的内容 URI,而不是指定 Internet 资源的 URI。该约定适用于不能通过 ContentProvider 的 Cursor 方法直接公开的二进制对象(例如图像)。相反,字符串引用用于引用不同的内容 URI,可以通过针对内容提供者的单独查询来解析。setImageURI 方法只是一个为您执行这些步骤的包装器。

我已经测试了 的这种用法setImageView,它确实按预期工作。不过,对于您的使用,我会查看BitmapFactory.decodeStream()URL.openStream()

Also to make this answer self-contained, the sample code from another post at that link, showing how to do it:

同样为了使这个答案独立,该链接上另一篇文章的示例代码显示了如何做到这一点:

private Bitmap getImageBitmap(String url) {
    Bitmap bm = null;
    try {
        URL aURL = new URL(url);
        URLConnection conn = aURL.openConnection();
        conn.connect();
        InputStream is = conn.getInputStream();
        BufferedInputStream bis = new BufferedInputStream(is);
        bm = BitmapFactory.decodeStream(bis);
        bis.close();
        is.close();
    } catch (IOException e) {
        Log.e(TAG, "Error getting bitmap", e);
    }
    return bm;
} 

I haven't tested this code, I'm just paranoid and like to ensure SO answers are useful even if every other site on the net disappears :-)

我还没有测试过这段代码,我只是偏执,想确保即使网络上的其他所有站点都消失了,SO 的答案也是有用的 :-)

回答by Efi G

Glideis an awesome library for displaying images!

Glide是一个很棒的用于显示图像的库!

 Glide.with(context)
                    .load(uri)
                    .into(imageView);

回答by Faxon

Use library Picasso

Manifest

使用图书馆毕加索

显现

uses-permission android:name="android.permission.INTERNET"

使用权限 android:name="android.permission.INTERNET"

build gradle

构建gradle

implementation 'com.squareup.picasso:picasso:2.71828'

实现 'com.squareup.picasso:picasso:2.71828'

Activity:

活动:

Picasso.get().load(photoUrl).into(imageView);

Picasso.get().load(photoUrl).into(imageView);

回答by herry

First, you should download the image and save it in your device(sdcard or memory). Then, get its file path, using Uri.parse(filePath)to convert path to uri finally, call ImageView's setImageURI(Uri)to fullfill. -- I use this way to achieve my purpose and there is a bug:if the image is to large(maybe exceed 1Mb or so, it may report outOfMemeroy Exception!!!)

首先,您应该下载图像并将其保存在您的device(sdcard or memory). 然后,得到它的文件路径,Uri.parse(filePath)最后用来将路径转换为uri,调用ImageView's setImageURI(Uri)to fullfill。-- 我用这种方式实现了我的目的,有一个bug:如果图片太大(可能超过1Mb左右,可能会报outOfMemeroy Exception!!!)

回答by Martin Zeitler

I've wrote a simple AsyncTask, which converts remote HTTPSto local Uriby caching to SD card:

我写了一个简单的AsyncTask,它通过缓存到 SD 卡将远程转换HTTPS为本地Uri

public class ProfileImageTask extends AsyncTask<String, Void, Uri> {

    private boolean enforce = false;
    private IProfileImageTask listener;
    private String fileName = "photo.jpg";
    private String sdPath;
    private String url;

    /** Constructor */
    @RequiresPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
    public ProfileImageTask(@NonNull Context context, @NonNull String url, @NonNull IProfileImageTask listener) {
        this.sdPath = Environment.getExternalStorageDirectory() + "/" + context.getResources().getString(R.string.app_name) + "/";
        this.listener = listener;
        this.url = url;
    }

    @Override
    protected void onPreExecute() {

        /* setup destination directory */
        File directory = new File(this.sdPath + "temp");
        if (! directory.exists()) {directory.mkdirs();}

        /* setup file name */
        String[] parts = this.url.split("/");
        this.fileName = parts[parts.length - 1];
    }

    @Override
    protected Uri doInBackground(String... arguments) {
        File file = new File(this.sdPath + "temp", this.fileName);
        if(file.exists() && this.enforce) {file.delete();}
        if (! file.exists()) {
            try {
                URLConnection conn = new URL(this.url).openConnection();
                conn.connect();
                InputStream in = conn.getInputStream();
                FileOutputStream out = new FileOutputStream(file);
                byte[] b = new byte[1024]; int c;
                while ((c = in.read(b)) != -1) {out.write(b, 0, c);}
                out.close();
                in.close();
            } catch (IOException e) {
                Log.e("ProfileImageTask", e.getMessage());
            }
        }    
        return Uri.fromFile(file);
    }

    @Override
    protected void onPostExecute(Uri uri) {
        if (listener != null && uri != null) {
            this.listener.OnImageAvailable(uri);
        }
    }
}

The interface:

界面:

public interface IProfileImageTask {
    void OnImageAvailable(@NonNull Uri uri);    
}

And the implementation:

和实施:

@Override
public void OnImageAvailable(@NonNull Uri uri) {
    this.photoUrl.setImageURI(uri);
}

Tested with url alike https://lh3.googleusercontent.com/.../photo.jpg(which has about 179kb). One could still downscale larger images, render a set of thumbnails or pass the intended size.

用 url 进行了测试https://lh3.googleusercontent.com/.../photo.jpg(大约有 179kb)。仍然可以缩小较大的图像,渲染一组缩略图或传递预期大小。