60

I'm using below method to download single image from url

public static Bitmap getBitmap(String url) { try { InputStream is = (InputStream) new URL(url).getContent(); Bitmap d = BitmapFactory.decodeStream(is); is.close(); return d; } catch (Exception e) { return null; } } 

Sometimes I get an outofmemory exception.

I am unable to catch outofmemory exception. The app will close. How to prevent this?

Is there a better method for downloading images that is also faster?

3
  • try to call System.gc() and recycle your bitmap by bitmap.recycle() this will relaese all the memory used by this selected bitmap but it does not nullify the bitmap object . To make the object null , we can assign it null i.e btimap == null Commented Aug 13, 2013 at 13:47
  • 1
    You can catch out of memory in Android: ...catch (OutOfMemoryError e){} Commented Aug 13, 2013 at 13:49
  • 2
    Here is the wonderful example to convert images to bitmap and list them in gridview, listview and in pager. Check this out github.com/nostra13/Android-Universal-Image-Loader Lazyload concept is used and instead of loading every time the images are stored in cache Commented Aug 13, 2013 at 14:00

13 Answers 13

9
 public void DownloadImageFromPath(String path){ InputStream in =null; Bitmap bmp=null; ImageView iv = (ImageView)findViewById(R.id.img1); int responseCode = -1; try{ URL url = new URL(path);//"http://192.xx.xx.xx/mypath/img1.jpg HttpURLConnection con = (HttpURLConnection)url.openConnection(); con.setDoInput(true); con.connect(); responseCode = con.getResponseCode(); if(responseCode == HttpURLConnection.HTTP_OK) { //download in = con.getInputStream(); bmp = BitmapFactory.decodeStream(in); in.close(); iv.setImageBitmap(bmp); } } catch(Exception ex){ Log.e("Exception",ex.toString()); } } 
Sign up to request clarification or add additional context in comments.

Comments

8

Step 1: Declaring Permission in Android Manifest

First thing to do in your first Android Project is you declare required permissions in your ‘AndroidManifest.xml’ file.

For Android Download Image from URL, we need permission to access the internet to download file and read and write internal storage to save image to internal storage.

Add following lines of code at the top of tag of AndroidManifest.xml file:

<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 

Step 2: Request required permission from user

Android allows every app to run in a sandbox. If an app needs to access certain resources or information outside that sandbox, it needs to request permission from user.

From Android 6.0 onward, Google wants developers to request permission from user from within the app, for more details on permissions read this.

Therefore for Android Download Image from URL, you’ll need to request Read Storage and Write

For this, we will use the following lines of code to first check if the required permission is already granted by the user, if not then we will request permission for storage read and write permission.

We’re creating a method ‘Downlaod Image’, you can simple call this wherever you need to download the image.

void DownloadImage(String ImageUrl) { if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED && ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 123); ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 123); showToast("Need Permission to access storage for Downloading Image"); } else { showToast("Downloading Image..."); //Asynctask to create a thread to downlaod image in the background new DownloadsImage().execute(ImageUrl); } } 

Now that we have requested and been granted the user permission, to start with android download image from url, we will create an AsyncTask, as you are not allowed to run a background process in the main thread.

class DownloadsImage extends AsyncTask<String, Void,Void>{ @Override protected Void doInBackground(String... strings) { URL url = null; try { url = new URL(strings[0]); } catch (MalformedURLException e) { e.printStackTrace(); } Bitmap bm = null; try { bm = BitmapFactory.decodeStream(url.openConnection().getInputStream()); } catch (IOException e) { e.printStackTrace(); } //Create Path to save Image File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES+ "/AndroidDvlpr"); //Creates app specific folder if(!path.exists()) { path.mkdirs(); } File imageFile = new File(path, String.valueOf(System.currentTimeMillis())+".png"); // Imagename.png FileOutputStream out = null; try { out = new FileOutputStream(imageFile); } catch (FileNotFoundException e) { e.printStackTrace(); } try{ bm.compress(Bitmap.CompressFormat.PNG, 100, out); // Compress Image out.flush(); out.close(); // Tell the media scanner about the new file so that it is // immediately available to the user. MediaScannerConnection.scanFile(MainActivity.this,new String[] { imageFile.getAbsolutePath() }, null,new MediaScannerConnection.OnScanCompletedListener() { public void onScanCompleted(String path, Uri uri) { // Log.i("ExternalStorage", "Scanned " + path + ":"); // Log.i("ExternalStorage", "-> uri=" + uri); } }); } catch(Exception e) { } return null; } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); showToast("Image Saved!"); } } 

In the above give lines of code, a URL and Bitmap is created, using BitmapFactory.decodeStream, file is downloaded.

The File path is created to save the image (We have created a folder named ‘AndroidDvlpr’ in DIRECTORY_PICTURES) and download is initialized.

After downloading the file MediaScannerConnection, is called to read metadata from the file and add the file to the media content provider so the image is available for the user.

In the above lines of code, we have also created a method, showToast() to show Toast. complete code here:

void showToast(String msg){ Toast.makeText(MainActivity.this,msg,Toast.LENGTH_SHORT).show(); } 

Read more here

Comments

6

Add This Dependency For Android Networking Into Your Project

compile 'com.amitshekhar.android:android-networking:1.0.0'

 String url = "http://ichef.bbci.co.uk/onesport/cps/480/cpsprodpb/11136/production/_95324996_defoe_rex.jpg"; File file; String dirPath, fileName; Button downldImg; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Initialization Of DownLoad Button downldImg = (Button) findViewById(R.id.DownloadButton); // Initialization Of DownLoad Button AndroidNetworking.initialize(getApplicationContext()); //Folder Creating Into Phone Storage dirPath = Environment.getExternalStorageDirectory() + "/Image"; fileName = "image.jpeg"; //file Creating With Folder & Fle Name file = new File(dirPath, fileName); //Click Listener For DownLoad Button downldImg.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { AndroidNetworking.download(url, dirPath, fileName) .build() .startDownload(new DownloadListener() { @Override public void onDownloadComplete() { Toast.makeText(MainActivity.this, "DownLoad Complete", Toast.LENGTH_SHORT).show(); } @Override public void onError(ANError anError) { } }); } }); } } 

After Run This Code Check Your Phone Memory You Can See There A Folder - Image Check Inside This Folder , You see There a Image File with name of "image.jpeg"

Thank You !!!

1 Comment

it gives an network error but there is no network error actually!
5

You can download image by Asyn task use this class:

public class ImageDownloaderTask extends AsyncTask<String, Void, Bitmap> { private final WeakReference<ImageView> imageViewReference; private final MemoryCache memoryCache; private final BrandItem brandCatogiriesItem; private Context context; private String url; public ImageDownloaderTask(ImageView imageView, String url, Context context) { imageViewReference = new WeakReference<ImageView>(imageView); memoryCache = new MemoryCache(); brandCatogiriesItem = new BrandItem(); this.url = url; this.context = context; } @Override protected Bitmap doInBackground(String... params) { return downloadBitmap(params[0]); } @Override protected void onPostExecute(Bitmap bitmap) { if (isCancelled()) { bitmap = null; } if (imageViewReference != null) { ImageView imageView = imageViewReference.get(); if (imageView != null) { if (bitmap != null) { memoryCache.put("1", bitmap); brandCatogiriesItem.setUrl(url); brandCatogiriesItem.setThumb(bitmap); // BrandCatogiriesItem.saveLocalBrandOrCatogiries(context, brandCatogiriesItem); imageView.setImageBitmap(bitmap); } else { Drawable placeholder = imageView.getContext().getResources().getDrawable(R.drawable.placeholder); imageView.setImageDrawable(placeholder); } } } } private Bitmap downloadBitmap(String url) { HttpURLConnection urlConnection = null; try { URL uri = new URL(url); urlConnection = (HttpURLConnection) uri.openConnection(); int statusCode = urlConnection.getResponseCode(); if (statusCode != HttpStatus.SC_OK) { return null; } InputStream inputStream = urlConnection.getInputStream(); if (inputStream != null) { Bitmap bitmap = BitmapFactory.decodeStream(inputStream); return bitmap; } } catch (Exception e) { Log.d("URLCONNECTIONERROR", e.toString()); if (urlConnection != null) { urlConnection.disconnect(); } Log.w("ImageDownloader", "Error downloading image from " + url); } finally { if (urlConnection != null) { urlConnection.disconnect(); } } return null; } } 

And call this like:

new ImageDownloaderTask(thumbImage, item.thumbnail, context).execute(item.thumbnail); 

2 Comments

Please advice me how memoryCache is used. I am new.
@VishnuPrabhu you can use Glide that is much easier way to show images and some of feature are very new in that:github.com/bumptech/glide
4

I recommend using the altex-image-downloader library, which makes it easy to download images:

AltexImageDownloader.writeToDisk(context, Imageurl, "IMAGES"); 

Add dependency in app build gradle:

implementation 'com.artjimlop:altex-image-downloader:0.0.4' 

Comments

3

The OOM exception could be avoided by following the official guide to load large bitmap.

Don't run your code on the UI Thread. Use AsyncTask instead and you should be fine.

Comments

3

you can use below function to download image from url.

private Bitmap getImage(String imageUrl, int desiredWidth, int desiredHeight) { private Bitmap image = null; int inSampleSize = 0; BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; options.inSampleSize = inSampleSize; try { URL url = new URL(imageUrl); HttpURLConnection connection = (HttpURLConnection)url.openConnection(); InputStream stream = connection.getInputStream(); image = BitmapFactory.decodeStream(stream, null, options); int imageWidth = options.outWidth; int imageHeight = options.outHeight; if(imageWidth > desiredWidth || imageHeight > desiredHeight) { System.out.println("imageWidth:"+imageWidth+", imageHeight:"+imageHeight); inSampleSize = inSampleSize + 2; getImage(imageUrl); } else { options.inJustDecodeBounds = false; connection = (HttpURLConnection)url.openConnection(); stream = connection.getInputStream(); image = BitmapFactory.decodeStream(stream, null, options); return image; } } catch(Exception e) { Log.e("getImage", e.toString()); } return image; } 

See complete explanation here

Comments

1
public class testCrop extends AppCompatActivity { ImageView iv; String imagePath = "https://style.pk/wp-content/uploads/2015/07/omer-Shahzad-performed-umrah-600x548.jpg"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.testcrpop); iv = (ImageView) findViewById(R.id.testCrop); imageDownload image = new imageDownload(testCrop.this, iv); image.execute(imagePath); } class imageDownload extends AsyncTask<String, Integer, Bitmap> { Context context; ImageView imageView; Bitmap bitmap; InputStream in = null; int responseCode = -1; //constructor. public imageDownload(Context context, ImageView imageView) { this.context = context; this.imageView = imageView; } @Override protected void onPreExecute() { } @Override protected Bitmap doInBackground(String... params) { URL url = null; try { url = new URL(params[0]); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setDoOutput(true); httpURLConnection.connect(); responseCode = httpURLConnection.getResponseCode(); if (responseCode == HttpURLConnection.HTTP_OK) { in = httpURLConnection.getInputStream(); bitmap = BitmapFactory.decodeStream(in); in.close(); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return bitmap; } @Override protected void onPostExecute(Bitmap data) { imageView.setImageBitmap(data); } } } 

OUTPUT

enter image description here

Comments

1

I'm still learning Android, so I cannot provide a rich context or reason for my suggestion, but this is what I am using to retrive files from both https and local urls. I am using this in my onActivity result (for both taking pictures and selecting from gallery), as well in an AsyncTask to retrieve the https urls.

InputStream input = new URL("your_url_string").openStream(); Bitmap myBitmap = BitmapFactory.decodeStream(input); 

1 Comment

While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value.
1

First Declare Permission in Android Manifest:-

<uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> 

MainActivityForDownloadImages.java

public class MainActivityForDownloadImages extends AppCompatActivity { // String urls = "https://stimg.cardekho.com/images/carexteriorimages/930x620/Kia/Kia-Seltos/6232/1562746799300/front-left-side-47.jpg"; String urls = "https://images5.alphacoders.com/609/609173.jpg"; Button button; public final Context context = this; ProgressDialog progressDialog ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main_for_download_images); if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.READ_EXTERNAL_STORAGE}, 0); } progressDialog = new ProgressDialog(context); button = findViewById(R.id.downloadImagebtn); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // initialize the progress dialog like in the first example // this is how you fire the downloader Intent intent = new Intent(context, DownloadService.class); intent.putExtra("url", urls); intent.putExtra("receiver", new DownloadReceiver(new Handler())); startService(intent); } }); } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == 0) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) { } } } private class DownloadReceiver extends ResultReceiver { public DownloadReceiver(Handler handler) { super(handler); } @Override protected void onReceiveResult(int resultCode, Bundle resultData) { super.onReceiveResult(resultCode, resultData); if (resultCode == DownloadService.UPDATE_PROGRESS) { int progress = resultData.getInt("progress"); //get the progress progressDialog.setProgress(progress); progressDialog.setMessage("Images Is Downloading"); progressDialog.show(); if (progress == 100) { progressDialog.dismiss(); } } } } } 

DownloadService.java

public class DownloadService extends IntentService { public static final int UPDATE_PROGRESS = 8344; String folder_main = "ImagesFolder"; public DownloadService() { super("DownloadService"); } @Override protected void onHandleIntent(Intent intent) { String urlToDownload = intent.getStringExtra("url"); ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra("receiver"); try { //create url and connect URL url = new URL(urlToDownload); URLConnection connection = url.openConnection(); connection.connect(); // this will be useful so that you can show a typical 0-100% progress bar int fileLength = connection.getContentLength(); // download the file InputStream input = new BufferedInputStream(connection.getInputStream()); File outerFolder = new File(Environment.getExternalStorageDirectory(), folder_main); File inerDire = new File(outerFolder.getAbsoluteFile(), System.currentTimeMillis() + ".jpg"); if (!outerFolder.exists()) { outerFolder.mkdirs(); } inerDire.createNewFile(); FileOutputStream output = new FileOutputStream(inerDire); byte data[] = new byte[1024]; long total = 0; int count; while ((count = input.read(data)) != -1) { total += count; // publishing the progress.... Bundle resultData = new Bundle(); resultData.putInt("progress", (int) (total * 100 / fileLength)); receiver.send(UPDATE_PROGRESS, resultData); output.write(data, 0, count); } // close streams output.flush(); output.close(); input.close(); } catch (IOException e) { e.printStackTrace(); } Bundle resultData = new Bundle(); resultData.putInt("progress", 100); receiver.send(UPDATE_PROGRESS, resultData); } } 

1 Comment

Please consider explaining how the code helps to solve OP's issue instead of spoonfeeding code.
0

Try this code to download an image from a URL on Android:

DownloadManager downloadManager = (DownloadManager)getSystemService(Context.DOWNLOAD_SERVICE); Uri uri = Uri.parse(imageName); DownloadManager.Request request = new DownloadManager.Request(uri); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); Long reference = downloadManager.enqueue(request); 

Comments

0

You can use this function to save your bitmap/image in gallery for all android version including Android 11

private fun addImageToGallery(fileName: String, bitmap: Bitmap, ctx: Context) { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { val fos: OutputStream val resolver = contentResolver val values = ContentValues() values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName) values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg") values.put( MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + File.separator + "EduImages" ) val imageUri = resolver.insert( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values ) fos = resolver.openOutputStream(imageUri!!) as OutputStream bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos) fos.close() Toast.makeText( ctx, "Saved in gallery", Toast.LENGTH_SHORT ).show() } else { val values = ContentValues() values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg") values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, fileName) values.put(MediaStore.Images.ImageColumns.TITLE, fileName) val uri: Uri? = ctx.contentResolver.insert( MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values ) uri?.let { ctx.contentResolver.openOutputStream(uri)?.let { stream -> val oStream = BufferedOutputStream(stream) bitmap.compress(Bitmap.CompressFormat.JPEG, 100, oStream) oStream.close() Toast.makeText(ctx, "Saved in gallery", Toast.LENGTH_SHORT) .show() } } } } catch (e: Exception) { Toast.makeText(ctx, e.localizedMessage, Toast.LENGTH_SHORT).show() } } 

Comments

0

What works best for me is to launch the URL and that allows the user to download the photo without having to set up any permissions or extra packages.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.