[android] How to download and save an image in Android

How do you download and save an image from a given url in Android?

This question is related to android android-imageview imagedownload

The answer is


As Google tells, for now, don't forget to add also readable on external storage in the manifest :

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

Source : http://developer.android.com/training/basics/data-storage/files.html#GetWritePermission


Why do you really need your own code to download it? How about just passing your URI to Download manager?

public void downloadFile(String uRl) {
    File direct = new File(Environment.getExternalStorageDirectory()
            + "/AnhsirkDasarp");

    if (!direct.exists()) {
        direct.mkdirs();
    }

    DownloadManager mgr = (DownloadManager) getActivity().getSystemService(Context.DOWNLOAD_SERVICE);

    Uri downloadUri = Uri.parse(uRl);
    DownloadManager.Request request = new DownloadManager.Request(
            downloadUri);

    request.setAllowedNetworkTypes(
            DownloadManager.Request.NETWORK_WIFI
                    | DownloadManager.Request.NETWORK_MOBILE)
            .setAllowedOverRoaming(false).setTitle("Demo")
            .setDescription("Something useful. No, really.")
            .setDestinationInExternalPublicDir("/AnhsirkDasarp", "fileName.jpg");

    mgr.enqueue(request);

}

I have a simple solution which is working perfectly. The code is not mine, I found it on this link. Here are the steps to follow:

1. Before downloading the image, let’s write a method for saving bitmap into an image file in the internal storage in android. It needs a context, better to use the pass in the application context by getApplicationContext(). This method can be dumped into your Activity class or other util classes.

public void saveImage(Context context, Bitmap b, String imageName) 
{
    FileOutputStream foStream;
    try 
    {
        foStream = context.openFileOutput(imageName, Context.MODE_PRIVATE);
        b.compress(Bitmap.CompressFormat.PNG, 100, foStream);
        foStream.close();
    } 
    catch (Exception e) 
    {
        Log.d("saveImage", "Exception 2, Something went wrong!");
        e.printStackTrace();
    }
}

2. Now we have a method to save bitmap into an image file in andorid, let’s write the AsyncTask for downloading images by url. This private class need to be placed in your Activity class as a subclass. After the image is downloaded, in the onPostExecute method, it calls the saveImage method defined above to save the image. Note, the image name is hardcoded as “my_image.png”.

private class DownloadImage extends AsyncTask<String, Void, Bitmap> {
    private String TAG = "DownloadImage";
    private Bitmap downloadImageBitmap(String sUrl) {
        Bitmap bitmap = null;
        try {
            InputStream inputStream = new URL(sUrl).openStream();   // Download Image from URL
            bitmap = BitmapFactory.decodeStream(inputStream);       // Decode Bitmap
            inputStream.close();
        } catch (Exception e) {
            Log.d(TAG, "Exception 1, Something went wrong!");
            e.printStackTrace();
        }
        return bitmap;
    }

    @Override
    protected Bitmap doInBackground(String... params) {
        return downloadImageBitmap(params[0]);
    }

    protected void onPostExecute(Bitmap result) {
        saveImage(getApplicationContext(), result, "my_image.png");
    }
}

3. The AsyncTask for downloading the image is defined, but we need to execute it in order to run that AsyncTask. To do so, write this line in your onCreate method in your Activity class, or in an onClick method of a button or other places you see fit.

new DownloadImage().execute("http://developer.android.com/images/activity_lifecycle.png");

The image should be saved in /data/data/your.app.packagename/files/my_image.jpeg, check this post for accessing this directory from your device.

IMO this solves the issue! If you want further steps such as load the image you can follow these extra steps:

4. After the image is downloaded, we need a way to load the image bitmap from the internal storage, so we can use it. Let’s write the method for loading the image bitmap. This method takes two paramethers, a context and an image file name, without the full path, the context.openFileInput(imageName) will look up the file at the save directory when this file name was saved in the above saveImage method.

public Bitmap loadImageBitmap(Context context, String imageName) {
    Bitmap bitmap = null;
    FileInputStream fiStream;
    try {
        fiStream    = context.openFileInput(imageName);
        bitmap      = BitmapFactory.decodeStream(fiStream);
        fiStream.close();
    } catch (Exception e) {
        Log.d("saveImage", "Exception 3, Something went wrong!");
        e.printStackTrace();
    }
    return bitmap;
}

5. Now we have everything we needed for setting the image of an ImageView or any other Views that you like to use the image on. When we save the image, we hardcoded the image name as “my_image.jpeg”, now we can pass this image name to the above loadImageBitmap method to get the bitmap and set it to an ImageView.

someImageView.setImageBitmap(loadImageBitmap(getApplicationContext(), "my_image.jpeg"));

6. To get the image full path by image name.

File file            = getApplicationContext().getFileStreamPath("my_image.jpeg");
String imageFullPath = file.getAbsolutePath();

7. Check if the image file exists.

File file =

getApplicationContext().getFileStreamPath("my_image.jpeg");
if (file.exists()) Log.d("file", "my_image.jpeg exists!");
  1. To delete the image file.

    File file = getApplicationContext().getFileStreamPath("my_image.jpeg"); if (file.delete()) Log.d("file", "my_image.jpeg deleted!");


@Droidman post is pretty comprehensive. Volley works good with small data of few kbytes. When I tried to use the 'BasicImageDownloader.java' the Android Studio gave me warning that the AsyncTask class should to be static or there could be leaks. I used Volley in another test app and that kept crashing because of leaks so I am worried about using Volley for the image downloader (images can be few 100 kB).

I used Picasso and it worked well, there is small change (probably an update on Picasso) from what is posted above. Below code worked for me:

    public static void imageDownload(Context ctx, String url){
    Picasso.get().load(yourURL)
            .into(getTarget(url));
}
private static Target getTarget(final String url){

    Target target2 = new Target() {
        @Override
        public void onBitmapLoaded(final Bitmap bitmap, Picasso.LoadedFrom from) {
            new Thread(new Runnable() {

                @Override
                public void run() {

                    File file = new File(localPath + "/"+"YourImageFile.jpg");
                    try {
                        file.createNewFile();
                        FileOutputStream ostream = new FileOutputStream(file);
                        bitmap.compress(Bitmap.CompressFormat.JPEG, 80, ostream);
                        ostream.flush();
                        ostream.close();
                    } catch (IOException e) {
                        Log.e("IOException", e.getLocalizedMessage());
                    }
                }
            }).start();
        }

        @Override
        public void onBitmapFailed(Exception e, Drawable errorDrawable) {
        }

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

I have just came from solving this problem on and I would like to share the complete code that can download, save to the sdcard (and hide the filename) and retrieve the images and finally it checks if the image is already there. The url comes from the database so the filename can be uniquely easily using id.

first download images

   private class GetImages extends AsyncTask<Object, Object, Object> {
    private String requestUrl, imagename_;
    private ImageView view;
    private Bitmap bitmap ; 
      private FileOutputStream fos;
    private GetImages(String requestUrl, ImageView view, String _imagename_) {
        this.requestUrl = requestUrl;
        this.view = view;
        this.imagename_ = _imagename_ ;
    }

    @Override
    protected Object doInBackground(Object... objects) {
        try {
            URL url = new URL(requestUrl);
            URLConnection conn = url.openConnection();
            bitmap = BitmapFactory.decodeStream(conn.getInputStream());
        } catch (Exception ex) {
        }
        return null;
    }

    @Override
    protected void onPostExecute(Object o) { 
        if(!ImageStorage.checkifImageExists(imagename_))
        { 
                view.setImageBitmap(bitmap);
                ImageStorage.saveToSdCard(bitmap, imagename_); 
            }  
        }  
   }

Then create a class for saving and retrieving the files

  public class ImageStorage {


public static String saveToSdCard(Bitmap bitmap, String filename) {

    String stored = null;

    File sdcard = Environment.getExternalStorageDirectory() ; 

    File folder = new File(sdcard.getAbsoluteFile(), ".your_specific_directory");//the dot makes this directory hidden to the user
    folder.mkdir(); 
    File file = new File(folder.getAbsoluteFile(), filename + ".jpg") ;
    if (file.exists())
        return stored ;

    try {
        FileOutputStream out = new FileOutputStream(file);
        bitmap.compress(Bitmap.CompressFormat.JPEG, 90, out);
        out.flush();
        out.close();
        stored = "success";
    } catch (Exception e) {
        e.printStackTrace();
    }
     return stored;
   }

public static File getImage(String imagename) {

        File mediaImage = null;
        try {
            String root = Environment.getExternalStorageDirectory().toString();
            File myDir = new File(root);
            if (!myDir.exists())
                return null;

            mediaImage = new File(myDir.getPath() + "/.your_specific_directory/"+imagename);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return mediaImage;
    }
public static boolean checkifImageExists(String imagename)
{
    Bitmap b = null ;
    File file = ImageStorage.getImage("/"+imagename+".jpg");
    String path = file.getAbsolutePath();

    if (path != null)
        b = BitmapFactory.decodeFile(path); 

    if(b == null ||  b.equals(""))
    {
        return false ;
    }
    return true ;
}
  }

Then To access the images first check if it is already there if not then download

          if(ImageStorage.checkifImageExists(imagename))
            {
                File file = ImageStorage.getImage("/"+imagename+".jpg"); 
                String path = file.getAbsolutePath(); 
                if (path != null){
                    b = BitmapFactory.decodeFile(path);
                    imageView.setImageBitmap(b);
                }  
            } else { 
                new GetImages(imgurl, imageView, imagename).execute() ; 
            }

this code perfectly run in my project

downloadImagesToSdCard(imagepath,imagepath);

private void downloadImagesToSdCard(String downloadUrl,String imageName)
        {
            try
            {
                URL url = new URL("www.xxx.com"+downloadUrl); 
                /* making a directory in sdcard */
            //  String sdCard=Environment.getExternalStorageDirectory().toString();
                ContextWrapper cw = new ContextWrapper(getActivity());
                 // path to /data/data/yourapp/app_data/imageDir
                File directory = cw.getDir("files", Context.MODE_PRIVATE);

                File myDir = new File(directory,"folder");

                /*  if specified not exist create new */
                if(!myDir.exists())
                {
                    myDir.mkdir();
                    Log.v("", "inside mkdir");
                }

                /* checks the file and if it already exist delete */
                String fname = imageName;
                File file = new File (myDir, fname);
                Log.d("file===========path", ""+file);
                if (file.exists ()) 
                    file.delete (); 

                /* Open a connection */
                URLConnection ucon = url.openConnection();
                InputStream inputStream = null;
                HttpURLConnection httpConn = (HttpURLConnection)ucon;
                httpConn.setRequestMethod("GET");
                httpConn.connect();
                inputStream = httpConn.getInputStream();
                /*if (httpConn.getResponseCode() == HttpURLConnection.HTTP_OK) 
                {
                    inputStream = httpConn.getInputStream();
                }*/

                FileOutputStream fos = new FileOutputStream(file);  
                int totalSize = httpConn.getContentLength();
                int downloadedSize = 0;   
                byte[] buffer = new byte[1024];
                int bufferLength = 0;
                while ( (bufferLength = inputStream.read(buffer)) >0 ) 
                {                 
                    fos.write(buffer, 0, bufferLength);                  
                    downloadedSize += bufferLength;                 
                    Log.i("Progress:","downloadedSize:"+downloadedSize+"totalSize:"+ totalSize) ;
                }   

                fos.close();
                Log.d("test", "Image Saved in sdcard..");  
                viewimage();
            }
            catch(IOException io)
            {                  
                io.printStackTrace();
            }
            catch(Exception e)
            {                     
                e.printStackTrace();
            }


        } 

        public void viewimage()
        {
              String path = serialnumber+".png";
               ContextWrapper cw = new ContextWrapper(getActivity());

                //path to /data/data/yourapp/app_data/dirName
                File directory = cw.getDir("files", Context.MODE_PRIVATE);

                File mypath=new File(directory,"folder/"+path);

                Bitmap b;
                try {
                    b = BitmapFactory.decodeStream(new FileInputStream(mypath));
                //  b.compress(format, quality, stream)
                    profile_image.setImageBitmap(Bitmap.createScaledBitmap(b, 120, 120, false));
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
        }

it might help you..

Button download_image = (Button)bigimagedialog.findViewById(R.id.btn_downloadimage);
                    download_image.setOnClickListener(new View.OnClickListener()
                    {
                        public void onClick(View v)
                        {
                            boolean success = (new File("/sdcard/dirname")).mkdir(); 
                            if (!success)
                            {
                                Log.w("directory not created", "directory not created");
                            }

                            try
                            {
                                URL url = new URL("YOUR_URL");
                                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                                connection.setDoInput(true);
                                connection.connect();
                                InputStream input = connection.getInputStream();
                                Bitmap myBitmap = BitmapFactory.decodeStream(input);

                                String data1 = String.valueOf(String.format("/sdcard/dirname/%d.jpg",System.currentTimeMillis()));

                                FileOutputStream stream = new FileOutputStream(data1);

                                ByteArrayOutputStream outstream = new ByteArrayOutputStream();
                                myBitmap.compress(Bitmap.CompressFormat.JPEG, 85, outstream);
                                byte[] byteArray = outstream.toByteArray();

                                stream.write(byteArray);
                                stream.close();

                                Toast.makeText(getApplicationContext(), "Downloading Completed", Toast.LENGTH_SHORT).show();
                            }
                            catch (Exception e)
                            {
                                e.printStackTrace();
                            }
                        }
                    });

Try this

 try
                {
                    Bitmap bmp = null;
                    URL url = new URL("Your_URL");
                    URLConnection conn = url.openConnection();
                    bmp = BitmapFactory.decodeStream(conn.getInputStream());
                    File f = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis() + ".jpg");
                    if(f.exists())
                        f.delete();
                    f.createNewFile();
                    Bitmap bitmap = bmp;
                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
                    bitmap.compress(Bitmap.CompressFormat.PNG, 0 /*ignored for PNG*/, bos);
                    byte[] bitmapdata = bos.toByteArray();
                    FileOutputStream fos = new FileOutputStream(f);
                    fos.write(bitmapdata);
                    fos.flush();
                    fos.close();
                    Log.e(TAG, "imagepath: "+f );
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }

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) {
            try {
                URL 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);
            saveImage(data);
        }

        private void saveImage(Bitmap data) {
            File createFolder = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"test");
            createFolder.mkdir();
            File saveImage = new File(createFolder,"downloadimage.jpg");
            try {
                OutputStream outputStream = new FileOutputStream(saveImage);
                data.compress(Bitmap.CompressFormat.JPEG,100,outputStream);
                outputStream.flush();
                outputStream.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

OUTPUTenter image description here

Make sure you added permission to write data in memory

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