Android load from URL to Bitmap
Asked Answered
P

20

86

I have a question about loading an image from a website. The code I use is:

Display display = getWindowManager().getDefaultDisplay(); 
int width = display.getWidth();
int height = display.getHeight();
Bitmap bit=null;
try {
    bit = BitmapFactory.decodeStream((InputStream)new URL("http://www.mac-wallpapers.com/bulkupload/wallpapers/Apple%20Wallpapers/apple-black-logo-wallpaper.jpg").getContent());
} catch (Exception e) {}
Bitmap sc = Bitmap.createScaledBitmap(bit,width,height,true);
canvas.drawBitmap(sc,0,0,null);

But it always returns a null pointer exception and the program crashes out. The URL is valid, and it seems to work for everyone else. I'm using 2.3.1.

Patentee answered 24/1, 2012 at 19:37 Comment(3)
What crash message do you get? What's the stack trace? Do you know which line causes it to crash?Toner
The createScalesBitmap throws a NullPointerException because bit is null.Patentee
Needed the internet permission... Added <uses-permission android:name="android.permission.INTERNET" /> To androidmanifest.xmlPatentee
T
184
public static Bitmap getBitmapFromURL(String src) {
    try {
        URL url = new URL(src);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.connect();
        InputStream input = connection.getInputStream();
        Bitmap myBitmap = BitmapFactory.decodeStream(input);
        return myBitmap;
    } catch (IOException e) {
        // Log exception
        return null;
    }
}
Type answered 24/1, 2012 at 19:54 Comment(8)
how to load one from https ?Leonard
watch out for blocking main thread. This should be used in AsyncTask derived Class.Usage
The code is fine. But There will be exception of "Network on main thread". Try using this inside "Async Task".Archenteron
How to detect if the raised IOException is caused because of lack of Internet access?Evvie
plus 1 for being Android 6.0 friendlyWestley
Why would i need an http url connection when i could just do "InputStream in = url.openStream();" Is it more better to do it your way or mine fine? just wonderingLongish
It crashed because we were using network connection on main thread. @PatenteeBloodstain
Gives me an exception java.net.MalformedURLExceptionLamplighter
S
38

If you are using Picasso or Glide or Universal-Image-Loader for load image from url.
You can simply get the loaded bitmap by

For Picasso (current version 2.71828)

Java code

Picasso.get().load(imageUrl).into(new Target() {
    @Override
    public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
        // loaded bitmap is here (bitmap)
    }

    @Override
    public void onBitmapFailed(Drawable errorDrawable) { }

    @Override
    public void onPrepareLoad(Drawable placeHolderDrawable) {}
});

Kotlin code

Picasso.get().load(url).into(object : com.squareup.picasso.Target { 
    override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {
         // loaded bitmap is here (bitmap)
    }

    override fun onPrepareLoad(placeHolderDrawable: Drawable?) {}

    override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {}
})

For Glide
Check How does one use glide to download an image into a bitmap?

For Universal-Image-Loader
Java code

imageLoader.loadImage(imageUrl, new SimpleImageLoadingListener() 
{
    @Override
    public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) 
    {
         // loaded bitmap is here (loadedImage)
    }
});
Stoneblind answered 12/7, 2016 at 10:9 Comment(1)
Linh Thank you so much. This is one of the great answer for those who are using Picasso to load their images.Dedans
P
11

I Prefer these one:

Creates Bitmap from InputStream and returns it:

    public static  Bitmap downloadImage(String url) {
        Bitmap bitmap = null;
        InputStream stream = null;
        BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        bmOptions.inSampleSize = 1;

        try {
            stream = getHttpConnection(url);
            bitmap = BitmapFactory.decodeStream(stream, null, bmOptions);
            stream.close();
        }
        catch (IOException e1) {
            e1.printStackTrace();
            System.out.println("downloadImage"+ e1.toString());
        }
        return bitmap;
    }

  // Makes HttpURLConnection and returns InputStream

 public static  InputStream getHttpConnection(String urlString)  throws IOException {

        InputStream stream = null;
        URL url = new URL(urlString);
        URLConnection connection = url.openConnection();

        try {
            HttpURLConnection httpConnection = (HttpURLConnection) connection;
            httpConnection.setRequestMethod("GET");
            httpConnection.connect();

            if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                stream = httpConnection.getInputStream();
            }
        }
        catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("downloadImage" + ex.toString());
        }
        return stream;
    }

REMEMBER :

Android includes two HTTP clients: HttpURLConnection and Apache HTTP Client. For Gingerbread and later, HttpURLConnection is the best choice.

From Android 3.x Honeycomb or later, you cannot perform Network IO on the UI thread and doing this throws android.os.NetworkOnMainThreadException. You must use Asynctask instead as shown below

/**     AsyncTAsk for Image Bitmap  */
    private class AsyncGettingBitmapFromUrl extends AsyncTask<String, Void, Bitmap> {


        @Override
        protected Bitmap doInBackground(String... params) {

            System.out.println("doInBackground");

            Bitmap bitmap = null;

            bitmap = AppMethods.downloadImage(params[0]);

            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {

            System.out.println("bitmap" + bitmap);

        }
    }
Pedrick answered 12/3, 2016 at 13:53 Comment(2)
What is the good practice to do this if I want to load multiple bitmaps and show them as backgrounds of list item in list views. Should I call Asynctask for every bitmap?Septi
I have a question about the AsyncTask. How do I call this method in the class that I want to convert the url to the Bitmap and how do I access the Bitmap inside this class?Cluff
R
6
public Drawable loadImageFromURL(String url, String name) {
    try {
        InputStream is = (InputStream) new URL(url).getContent();
        Drawable d = Drawable.createFromStream(is, name);
        return d;
    } catch (Exception e) {
        return null;
    }
}
Rhumb answered 21/5, 2012 at 10:7 Comment(0)
M
6

This method will do the trick with kotlin coroutine so it won't block the UI Main thread & will return resized circle bitmap image(like profile image)

 private var image: Bitmap? = null
 private fun getBitmapFromURL(src: String?) {
    CoroutineScope(Job() + Dispatchers.IO).launch {
        try {
            val url = URL(src)
            val bitMap = BitmapFactory.decodeStream(url.openConnection().getInputStream())
            image = Bitmap.createScaledBitmap(bitMap, 100, 100, true)
        } catch (e: IOException) {
            // Log exception
        }
    }
}
Morgen answered 14/8, 2020 at 20:23 Comment(1)
Thanks. It worked for me. But It gives a warning inappropriate blocking method call. It can block the UI Main thread.Glandule
N
3

Follow method to get url to bitmap in android just pass link of this image and get bitmap.

public static Bitmap getBitmapFromURL(String imgUrl) {
    try {
        URL url = new URL(imgUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.connect();
        InputStream input = connection.getInputStream();
        Bitmap myBitmap = BitmapFactory.decodeStream(input);
        return myBitmap;
    } catch (IOException e) {
        // Log exception
        return null;
    }
}
Nobody answered 5/9, 2016 at 10:3 Comment(0)
M
3

Its Working in Pie OS Use this

    @Override
    protected void onCreate() {
        super.onCreate();
        //setNotificationBadge();

        if (android.os.Build.VERSION.SDK_INT >= 9) {
            StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }

    }

        BottomNavigationView bottomNavigationView = (BottomNavigationView) findViewById(R.id.navigation);
        Menu menu = bottomNavigationView.getMenu();
        MenuItem userImage = menu.findItem(R.id.navigation_download);
        userImage.setTitle("Login");

        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try {

                    URL url = new URL("https://rukminim1.flixcart.com/image/832/832/jmux18w0/mobile/b/g/n/mi-redmi-6-mzb6387in-original-imaf9z8eheryfbsu.jpeg?q=70");
                    Bitmap myBitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());

                    Log.e("keshav", "Bitmap " + myBitmap);
                    userImage.setIcon(new BitmapDrawable(getResources(), myBitmap));

                } catch (IOException e) {
                    Log.e("keshav", "Exception " + e.getMessage());
                }
            }
        });
Myall answered 15/5, 2019 at 11:34 Comment(0)
W
3

Use Kotlin Coroutines to Handle Threading

The reason the code is crashing is because the Bitmap is attempting to be created on the Main Thread which is not allowed since it may cause Android Not Responding (ANR) errors.

Concepts Used

  • Kotlin Coroutines notes.
  • The Loading, Content, Error (LCE) pattern is used below. If interested you can learn more about it in this talk and video.
  • LiveData is used to return the data. I've compiled my favorite LiveData resource in these notes.
  • In the bonus code, toBitmap() is a Kotlin extension function requiring that library to be added to the app dependencies.

Implementation

Code

1. Create Bitmap in a different thread then the Main Thread.

In this sample using Kotlin Coroutines the function is being executed in the Dispatchers.IO thread which is meant for CPU based operations. The function is prefixed with suspend which is a Coroutine syntax.

Bonus - After the Bitmap is created it is also compressed into an ByteArray so it can be passed via an Intent later outlined in this full sample.

Repository.kt

suspend fun bitmapToByteArray(url: String) = withContext(Dispatchers.IO) {
    MutableLiveData<Lce<ContentResult.ContentBitmap>>().apply {
        postValue(Lce.Loading())
        postValue(Lce.Content(ContentResult.ContentBitmap(
            ByteArrayOutputStream().apply {
                try {                     
                    BitmapFactory.decodeStream(URL(url).openConnection().apply {
                        doInput = true
                        connect()
                    }.getInputStream())
                } catch (e: IOException) {
                   postValue(Lce.Error(ContentResult.ContentBitmap(ByteArray(0), "bitmapToByteArray error or null - ${e.localizedMessage}")))
                   null
                }?.compress(CompressFormat.JPEG, BITMAP_COMPRESSION_QUALITY, this)
           }.toByteArray(), "")))
        }
    }

ViewModel.kt

//Calls bitmapToByteArray from the Repository
private fun bitmapToByteArray(url: String) = liveData {
    emitSource(switchMap(repository.bitmapToByteArray(url)) { lce ->
        when (lce) {
            is Lce.Loading -> liveData {}
            is Lce.Content -> liveData {
                emit(Event(ContentResult.ContentBitmap(lce.packet.image, lce.packet.errorMessage)))
            }
            is Lce.Error -> liveData {
                Crashlytics.log(Log.WARN, LOG_TAG,
                        "bitmapToByteArray error or null - ${lce.packet.errorMessage}")
            }
        }
    })
}

Bonus - Convert ByteArray back to Bitmap.

Utils.kt

fun ByteArray.byteArrayToBitmap(context: Context) =
    run {
        BitmapFactory.decodeByteArray(this, BITMAP_OFFSET, size).run {
            if (this != null) this
            // In case the Bitmap loaded was empty or there is an error I have a default Bitmap to return.
            else AppCompatResources.getDrawable(context, ic_coinverse_48dp)?.toBitmap()
        }
    }
Wearable answered 24/6, 2019 at 5:3 Comment(0)
S
2

Pass your Image URL: Try this:

private Bitmap getBitmap(String url) 
    {
        File file=fileCache.getFile(url);
        Bitmap bm = decodeFile(file);
        if(bm!=null) 
            return bm;
        try {
            Bitmap bitmap=null;
            URL ImageUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection)ImageUrl.openConnection();
            conn.setConnectTimeout(50000);
            conn.setReadTimeout(50000);
            conn.setInstanceFollowRedirects(true);
            InputStream is = conn.getInputStream();
            OutputStream os = new FileOutputStream(file);
            Utils.CopyStream(is, os);
            os.close();
            bitmap = decodeFile(file);
            return bitmap;
        } catch (Exception ex){
           ex.printStackTrace();
           return null;
        }
    }
    private Bitmap decodeFile(File file){
        try {
            BitmapFactory.Options opt = new BitmapFactory.Options();
            opt.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(file),null,opt);
            final int REQUIRED_SIZE=70;
            int width_tmp=opt.outWidth, height_tmp=opt.outHeight;
            int scale=1;
            while(true){
                if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                    break;
                width_tmp/=2;
                height_tmp/=2;
                scale*=2;
            }
            BitmapFactory.Options opte = new BitmapFactory.Options();
            opte.inSampleSize=scale;
            return BitmapFactory.decodeStream(new FileInputStream(file), null, opte);
        } catch (FileNotFoundException e) {}
        return null;
    }

Create Class Utils:

public class Utils {
    public static void CopyStream(InputStream is, OutputStream os)
    {
        final int buffer_size=1024;
        try
        {
            byte[] bytes=new byte[buffer_size];
            for(;;)
            {
              int count=is.read(bytes, 0, buffer_size);
              if(count==-1)
                  break;
              os.write(bytes, 0, count);
            }
        }
        catch(Exception ex){}
    }
}
Stier answered 7/10, 2015 at 7:26 Comment(0)
C
2

If you prefer Coil instead of Glide.

val imageRequest = ImageRequest.Builder(context)
        .data(imageUrl)
        .target { drawable ->
            val bitmap = drawable.toBitmap() // This is the bitmap 🚨
        }
        .build()
    ImageLoader(context).enqueue(imageRequest)
Cassity answered 7/11, 2021 at 12:43 Comment(0)
B
1

Try this:

AQuery aq = new AQuery(getActivity());
            aq.id(view.findViewById(R.id.image)).image(imageUrl, true, true, 0,  0,
                    new BitmapAjaxCallback() {
                        @Override
                        public void callback(String url, ImageView iv, Bitmap bm, AjaxStatus status){
                            iv.setImageBitmap(bm);
                        }
                    }.header("User-Agent", "android"));
Betel answered 28/8, 2013 at 5:51 Comment(0)
J
1
Glide.with(context)
    .load("http://test.com/yourimage.jpg")  
    .asBitmap()  // переводим его в нужный формат
    .fitCenter()
    .into(new SimpleTarget<Bitmap>(100,100) {
          @Override
          public void onResourceReady(Bitmap bitmap, GlideAnimation<? super Bitmap> glideAnimation) {

           // do something with you bitmap 

                bitmap

          }
    }); 
Jecon answered 31/8, 2017 at 21:34 Comment(1)
Welcome to stackoverflow. Please read How how to answer.Rhines
B
1
public static Bitmap getImgBitmapFromUri(final String url, final Activity context, final CropImageView imageView, final File file) {
    final Bitmap bitmap = null;
    AsyncTask.execute(new Runnable() {
        @Override
        public void run() {
            try {
                Utils.image = Glide.with(context)
                        .load(url).asBitmap()
                        .into(100, 100).get();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            context.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (imageView != null)
                        imageView.setImageBitmap(Utils.image);
                }
            });
        }
    });
    return Utils.image;
}

Use Glide library and run the following code in work thread as posted

Bortman answered 26/12, 2017 at 11:23 Comment(1)
Please edit to include a comment explaining this answer for the benefit of other users.Kasper
H
1
  private class AsyncTaskRunner extends AsyncTask<String, String, String> {
    String Imageurl;

    public AsyncTaskRunner(String Imageurl) {
        this.Imageurl = Imageurl;
    }

    @Override
    protected String doInBackground(String... strings) {

        try {

            URL url = new URL(Imageurl);
            thumbnail_r = BitmapFactory.decodeStream(url.openConnection().getInputStream());


        } catch (IOException e) {
        }
        return null;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);


        imgDummy.setImageBitmap(thumbnail_r);
        UtilityMethods.tuchOn(relProgress);
    }
}

Call asynctask like:

 AsyncTaskRunner asyncTaskRunner = new AsyncTaskRunner(uploadsModel.getImages());
        asyncTaskRunner.execute();
Harold answered 18/9, 2019 at 11:40 Comment(0)
T
0

very fast way , this method works very quickly:

private Bitmap getBitmap(String url) 
    {
        File f=fileCache.getFile(url);

        //from SD cache
        Bitmap b = decodeFile(f);
        if(b!=null)
            return b;

        //from web
        try {
            Bitmap bitmap=null;
            URL imageUrl = new URL(url);
            HttpURLConnection conn = (HttpURLConnection)imageUrl.openConnection();
            conn.setConnectTimeout(30000);
            conn.setReadTimeout(30000);
            conn.setInstanceFollowRedirects(true);
            InputStream is=conn.getInputStream();
            OutputStream os = new FileOutputStream(f);
            Utils.CopyStream(is, os);
            os.close();
            bitmap = decodeFile(f);
            return bitmap;
        } catch (Exception ex){
           ex.printStackTrace();
           return null;
        }
    }

    //decodes image and scales it to reduce memory consumption
    private Bitmap decodeFile(File f){
        try {
            //decode image size
            BitmapFactory.Options o = new BitmapFactory.Options();
            o.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(new FileInputStream(f),null,o);

            //Find the correct scale value. It should be the power of 2.
            final int REQUIRED_SIZE=70;
            int width_tmp=o.outWidth, height_tmp=o.outHeight;
            int scale=1;
            while(true){
                if(width_tmp/2<REQUIRED_SIZE || height_tmp/2<REQUIRED_SIZE)
                    break;
                width_tmp/=2;
                height_tmp/=2;
                scale*=2;
            }

            //decode with inSampleSize
            BitmapFactory.Options o2 = new BitmapFactory.Options();
            o2.inSampleSize=scale;
            return BitmapFactory.decodeStream(new FileInputStream(f), null, o2);
        } catch (FileNotFoundException e) {}
        return null;
    }
Tees answered 4/12, 2013 at 14:46 Comment(1)
Util.copyStream(is, os);Front
D
0

Please try this following steps.

1) Create AsyncTask in class or adapter(if you want to change the list item image).

public class AsyncTaskLoadImage extends AsyncTask<String, String, Bitmap> {
        private final static String TAG = "AsyncTaskLoadImage";
        private ImageView imageView;

        public AsyncTaskLoadImage(ImageView imageView) {
            this.imageView = imageView;
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            Bitmap bitmap = null;
            try {
                URL url = new URL(params[0]);
                bitmap = BitmapFactory.decodeStream((InputStream) url.getContent());
            } catch (IOException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return bitmap;
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            try {
                int width, height;
                height = bitmap.getHeight();
                width = bitmap.getWidth();

                Bitmap bmpGrayscale = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
                Canvas c = new Canvas(bmpGrayscale);
                Paint paint = new Paint();
                ColorMatrix cm = new ColorMatrix();
                cm.setSaturation(0);
                ColorMatrixColorFilter f = new ColorMatrixColorFilter(cm);
                paint.setColorFilter(f);
                c.drawBitmap(bitmap, 0, 0, paint);
                imageView.setImageBitmap(bmpGrayscale);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

2) Call the AsyncTask from your activity, fragment or adapter(inside onBindViewHolder).

2.a) For adapter:

    String src = current.getProductImage();
    new AsyncTaskLoadImage(holder.icon).execute(src);

2.b) For activity and fragment:

**Activity:**
  ImageView imagview= (ImageView) findViewById(R.Id.imageview);
  String src = (your image string);
  new AsyncTaskLoadImage(imagview).execute(src);

**Fragment:**
  ImageView imagview= (ImageView)view.findViewById(R.Id.imageview);
  String src = (your image string);
  new AsyncTaskLoadImage(imagview).execute(src);

3) Kindly run the app and check the image.

Happy coding....:)

Diehl answered 1/2, 2018 at 9:34 Comment(0)
G
0

If you load URL from bitmap without using AsyncTask, write two lines after setContentView(R.layout.abc);

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
        StrictMode.setThreadPolicy(policy);

try {
    URL url = new URL("http://....");
    Bitmap image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch(IOException e) {
    System.out.println(e);
}
Goodell answered 17/2, 2018 at 11:32 Comment(0)
P
0

If you are using Picasso for Images you can try method below!

public static Bitmap getImageBitmapFromURL(Context context, String imageUrl){
    Bitmap imageBitmap = null;
    try {
      imageBitmap = new AsyncTask<Void, Void, Bitmap>() {
        @Override
        protected Bitmap doInBackground(Void... params) {
          try {
            int targetHeight = 200;
            int targetWidth = 200;

            return Picasso.with(context).load(String.valueOf(imageUrl))
              //.resize(targetWidth, targetHeight)
              .placeholder(R.drawable.raw_image)
              .error(R.drawable.raw_error_image)
              .get();
          } catch (IOException e) {
            e.printStackTrace();
          }
          return null;
        }
      }.execute().get();
    } catch (InterruptedException e) {
      e.printStackTrace();
    } 
  return imageBitmap;
  }
Prandial answered 4/6, 2018 at 6:13 Comment(0)
A
0

if you are using Glide and Kotlin,

Glide.with(this)
            .asBitmap()
            .load("https://...")
            .addListener(object : RequestListener<Bitmap> {
                override fun onLoadFailed(
                    e: GlideException?,
                    model: Any?,
                    target: Target<Bitmap>?,
                    isFirstResource: Boolean
                ): Boolean {
                    Toast.makeText(this@MainActivity, "failed: " + e?.printStackTrace(), Toast.LENGTH_SHORT).show()
                    return false
                }

                override fun onResourceReady(
                    resource: Bitmap?,
                    model: Any?,
                    target: Target<Bitmap>?,
                    dataSource: DataSource?,
                    isFirstResource: Boolean
                ): Boolean {
                    //image is ready, you can get bitmap here
                    var bitmap = resource
                    return false
                }

            })
            .into(imageView)
Accordance answered 3/5, 2019 at 13:11 Comment(0)
C
0
fun getBitmap(url : String?) : Bitmap? {
    var bmp : Bitmap ? = null
    Picasso.get().load(url).into(object : com.squareup.picasso.Target {
        override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) {
            bmp =  bitmap
        }

        override fun onPrepareLoad(placeHolderDrawable: Drawable?) {}

        override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) {}
    })
    return bmp
}

Try this with picasso

Cinquecento answered 16/7, 2019 at 9:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.