从URL获取Android可绘制图像

31

我目前正在使用以下代码将URL中的图像加载为可绘制对象。

Drawable drawable_from_url(String url, String src_name) 
throws java.net.MalformedURLException, java.io.IOException {
        return Drawable.createFromStream(((java.io.InputStream)new java.net.URL(url).getContent()), src_name);

}

这段代码的功能完全符合要求,但似乎存在兼容性问题。在1.5版本中,当我给它一个URL时,它会抛出FileNotFoundException异常。但是在2.2版本中,给定完全相同的URL,它可以正常运行。以下URL是我给这个函数的示例输入。

http://bks6.books.google.com/books?id=aH7BPTrwNXUC&printsec=frontcover&img=1&zoom=5&edge=curl&sig=ACfU3U2aQRnAX2o2ny2xFC1GmVn22almpg

我应该如何以一种跨平台的方式从URL中加载图片?

8个回答

50

位图不是可绘制对象。如果您确实需要一个可绘制对象,请执行以下操作:

public static Drawable drawableFromUrl(String url) throws IOException {
    Bitmap x;

    HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
    connection.connect();
    InputStream input = connection.getInputStream();

    x = BitmapFactory.decodeStream(input);
    return new BitmapDrawable(Resources.getSystem(), x);
}

(我使用了在https://dev59.com/YXE95IYBdhLWcg3wMrAB#2416360中找到的技巧)


1
很好的答案,但请注意构造函数已被弃用。使用BitmapDrawable(Resources, Bitmap)来确保可绘制对象正确设置其目标密度。 - avalancha
应该更新由于已弃用,回答得很好。 - mochadwi

16

我自己解决了。我使用以下代码将其加载为位图。

Bitmap drawable_from_url(String url) throws java.net.MalformedURLException, java.io.IOException {

    HttpURLConnection connection = (HttpURLConnection)new URL(url) .openConnection();
    connection.setRequestProperty("User-agent","Mozilla/4.0");

    connection.connect();
    InputStream input = connection.getInputStream();

    return BitmapFactory.decodeStream(input);
}

还要加上用户代理很重要,因为如果没有用户代理,Google Books会拒绝访问。


它会抛出异常,例如android.os.NetworkOnMainThreadException。 - Prince Dholakiya
这是不正确的,@Prince,请查看我的答案,使用AsyncTask来避免NetworkOnMainThreadException。 - Jorgesys

5

我似乎记得以前遇到过这个问题;当时我使用的是1.5版本。 - I82Much

3
从URL中获取Drawable图像,您必须使用AsyncTask来避免NetWorkOnMainThreadException,在onPostExecute()中获得的结果Drawable可以设置为您的ImageView:
    final String urlImage = "https://www.android.com/static/2016/img/hero-carousel/banner-android-p-2.jpg";

    new AsyncTask<String, Integer, Drawable>(){

        @Override
        protected Drawable doInBackground(String... strings) {
            Bitmap bmp = null;
            try {
                HttpURLConnection connection = (HttpURLConnection) new URL(urlImage).openConnection();
                connection.connect();
                InputStream input = connection.getInputStream();
                bmp = BitmapFactory.decodeStream(input);
            } catch (IOException e) {
                e.printStackTrace();
            }
            return new BitmapDrawable(bmp);
        }

        protected void onPostExecute(Drawable result) {

            //Add image to ImageView
            myImageView.setImageDrawable(result);

        }


    }.execute();

1
以下代码对我有效:
Matrix Mat = new Matrix();

Bitmap Source = BitmapFactory.decodeFile("ItemImagePath");

Bitmap Destination = Bitmap.createScaledBitmap( Source, 320, 320, true );

Source = Bitmap.createBitmap( Destination, 0, 0, Destination.getWidth(), Destination.getHeight(),Mat, true );

ItemImageView.setImageBitmap(Source);

1

Kotlin解决方案与Coil

fun convertUrlToDrawable(url: String, result: (Drawable) -> Unit) {
val loader = ImageLoader(context = appContext)
val req = ImageRequest.Builder(appContext)
    .allowHardware(true)
    .allowConversionToBitmap(true)
    .data(url) // demo link
    .target { drawable ->
        result(drawable)
    }
    .build()
loader.enqueue(req)

}


1

您可以使用Glide将您的imageURL加载为Drawable,然后在需要时重复使用它。
以下是实现此策略的方法:

Glide.with(ctx)
      .asDrawable()
      .load(mImageURL)
      .into(new CustomTarget<Drawable>() {
        @Override
        public void onResourceReady(@NonNull Drawable resource, @Nullable Transition<? super Drawable> transition) {
           // Your imageURL is now converted to a drawable 'resource'
        }

        @Override
        public void onLoadCleared(@Nullable Drawable placeholder) {
           
        }
      });

0
你可以使用com.androidquery.AndroidQuery来实现这个简单的操作。例如:
AQuery aq = new AQuery(this);
aq.id(view).image("http://yourserver/yourimage.png", true, true, 300, new BitmapAjaxCallback() {
        @Override
        public void callback(String url, ImageView imageView, Bitmap bitmap, AjaxStatus status) {
            Drawable drawable = new BitmapDrawable(getResources(), bm);
        }
    });

如果你使用BitmapAjaxCallback,你将可以访问Bitmap,然后将其包装为BitmapDrawable。

这个人询问如何从网址创建可绘制对象,而你的方法在底层已经实现了这个功能,但无法获取到该可绘制对象;相反,你需要传递一个视图,该库会将从网址下载的图像设置在视图上。那么怎么能算作是回答问题的答案呢? - Munim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接