The question:
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("https://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.
The Solutions:
Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.
Method 1
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;
}
}
Method 2
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)
}
});
Method 3
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);
}
}
Method 4
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;
}
}
Method 5
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
}
}
}
Method 6
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;
}
}
Method 7
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());
}
}
});
Method 8
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()
}
}
Method 9
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){}
}
}
Method 10
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"));
Method 11
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
}
});
Method 12
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
Method 13
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();
Method 14
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;
}
Method 15
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….:)
Method 16
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("https://....");
Bitmap image = BitmapFactory.decodeStream(url.openConnection().getInputStream());
} catch(IOException e) {
System.out.println(e);
}
Method 17
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;
}
Method 18
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([email protected], "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)
Method 19
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
Method 20
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)
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0