Download image Android – External storage [Java]

Learn how to download image in your Android app. The download images will be saved in external storage using Java.

Demo

First we will create a download icon. Goto your drawable folder and create an XML file named “ic_file_download.xml” and paste the following code in it:

ic_file_download.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="#FF000000"
        android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/>
</vector>

Now we need to create a layout for dialog which will be opened. So create a file named “image_detail_dialog.xml” and paste the following code in it:

image_detail_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#cccccc"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#000000"
        android:padding="10dp">

        <ImageView
            android:id="@+id/download"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:src="@drawable/ic_file_download"
            android:tint="#ffffff" />
    </RelativeLayout>

    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="fitCenter"
        android:adjustViewBounds="true" />
</LinearLayout>

This will create a layout where you can see the download button on top right with black background color. And an image will be displayed in the center of screen with full width and height.

Now we need to show this dialog to the user. For that, we need to create a separate class which extends from Dialog. But, to save the image in SD Card or phone memory, we need to get external file write permission from user. So that code will only be run in Activity class.

So we need to create an interface first:

DownloadAttachmentListener.java

public interface DownloadAttachmentListener {
    void onDownloadClick(String imagePath);
    void onDownloaded();
}

It has 2 functions, 1 will be called when user requested to download the image. 2nd will be called when the image is fully downloaded and saved in SD Card or phone memory.

Now in your manifest file, set the permission to read and write the external storage:

AndroidManifest.xml

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

Downloading the file from server is an asynchronous task and can only be done in a class which extends from AsyncTask. So create a new class named “DownloadImageTask.java” and paste the following code in it:

DownloadImageTask.java

import android.content.Context;
import android.os.AsyncTask;
import android.os.Environment;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.ProtocolException;
import java.net.URL;

public class DownloadImageTask extends AsyncTask<Void, Void, Void> {
    private String imagePath, fileName;
    private Context context;
    private DownloadAttachmentListener downloadAttachmentListener;

    public DownloadImageTask(Context context, String imagePath, String fileName, DownloadAttachmentListener downloadAttachmentListener) {
        this.context = context;
        this.imagePath = imagePath;
        this.fileName = fileName;
        this.downloadAttachmentListener = downloadAttachmentListener;
    }

    @Override
    protected Void doInBackground(Void... voids) {
        try {
            File root = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
            File directoryPath = new File(root.getAbsolutePath() + "/" + context.getString(R.string.app_name));
            if (!directoryPath.exists()) {
                directoryPath.mkdir();
            }

            File cachePath = new File(directoryPath + "/" + fileName + ".jpg");
            cachePath.createNewFile();
            byte[] buffer = new byte[1024];
            int bufferLength;

            URL url = new URL(imagePath);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setRequestMethod("GET");
            urlConnection.setDoOutput(false);
            urlConnection.connect();

            InputStream inputStream = urlConnection.getInputStream();
            FileOutputStream fileOutput = new FileOutputStream(cachePath);
            while ((bufferLength = inputStream.read(buffer)) > 0) {
                fileOutput.write(buffer, 0, bufferLength);
            }

            fileOutput.write(buffer);
            fileOutput.close();
            inputStream.close();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (ProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    protected void onPostExecute(Void aVoid) {
        if (downloadAttachmentListener != null) {
            downloadAttachmentListener.onDownloaded();
        }
    }
}

It is receiving image path, file name which will be set in SD Card / phone memory and download attachment listener, which will call the function “onDownloaded()” when the image is fully downloaded and saved in user’s phone.

Now create this download attachment listener interface’s instance in your activity:

private DownloadAttachmentListener downloadAttachmentListener = new DownloadAttachmentListener() {
    @Override
    public void onDownloadClick(String imagePath) {
        // Check if we have write permission
        int permission = ActivityCompat.checkSelfPermission(getApplicationContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);

        if (permission != PackageManager.PERMISSION_GRANTED) {
            // We don't have permission so prompt the user
            ActivityCompat.requestPermissions(
                    YourActivity.this,
                    new String[]{
                            Manifest.permission.READ_EXTERNAL_STORAGE,
                            Manifest.permission.WRITE_EXTERNAL_STORAGE
                    },
                    100
            );
        } else {
            String fileName = new Date().getTime();
            new DownloadImageTask(getApplicationContext(), imagePath, fileName, downloadAttachmentListener).execute();
        }
    }

    @Override
    public void onDownloaded() {
        Toast.makeText(getApplicationContext(), "File has been saved at Phone\\Pictures\\" + getResources().getString(R.string.app_name), Toast.LENGTH_LONG).show();
    }
};

Now create a dialog which will display the layout we created above and when the dialog icon is clicked, we will call this “onDownloadClick” function:

PictureMessageDialog.java

package com.scp.app.scp_chatapp.custom;

import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.scp.app.scp_chatapp.R;
import com.scp.app.scp_chatapp.interfaces.DownloadAttachmentListener;
import com.scp.app.scp_chatapp.models.MessageModel;
import com.scp.app.scp_chatapp.utils.Utility;

public class PictureMessageDialog extends Dialog {
    private Context context;
    private String imagePath;

    private ImageView image, download;
    private DownloadAttachmentListener downloadAttachmentListener;

    public PictureMessageDialog setDownloadAttachmentListener(DownloadAttachmentListener downloadAttachmentListener) {
        this.downloadAttachmentListener = downloadAttachmentListener;
        return this;
    }

    public PictureMessageDialog(@NonNull Context context, int themeResId) {
        super(context, themeResId);
        this.context = context;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getWindow() != null) {
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        }
        setContentView(R.layout.image_detail_dialog);

        image = findViewById(R.id.image);
        download = findViewById(R.id.download);
        Glide.with(context)
                .load(imagePath)
                .asBitmap()
                .diskCacheStrategy(DiskCacheStrategy.NONE)
                .skipMemoryCache(true)
                .into(image);

        download.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                downloadAttachmentListener.onDownloadClick(messageModel);
            }
        });
    }

    public PictureMessageDialog setImagePath(String imagePath) {
        this.imagePath = imagePath;
        return this;
    }
}

This will create a dialog class and we are setting this to full screen width and height.

Now we just need to show the dialog class we created earlier and pass this interface instance, along with image path:

new PictureMessageDialog(YourActivity.this, android.R.style.Theme_Black_NoTitleBar_Fullscreen)
    .setDownloadAttachmentListener(downloadAttachmentListener)
    .setImagePath("https://www.nasa.gov/sites/default/files/styles/full_width_feature/public/pathfinder_full.jpg")
    .show();

You can call this function wherever you want to display the image in full screen. Once displayed, you will see a download icon on top right with black background. When that icon is clicked, you will be asked to give write permissions to your external storage. Once write external storage permission is granted, file will be saved in your phone memory, inside pictures folder. Following will be the path:

Phone/Pictures/{your_app_name}/filename.jpg

After download, you can see your image in android external storage.

Learn how to upload image from Android gallery to PHP server.

Profile update with picture – Android, Java, PHP, and MySQL

One Reply to “Download image Android – External storage [Java]”

  1. Undeniably believe that which you said. Your
    favorite justification appeared to be on the web the simplest thing to be aware
    of. I say to you, I certainly get irked while people think
    about worries that they plainly do not know about.
    You managed to hit the nail upon the top and also defined out the whole
    thing without having side effect , people can take a signal.
    Will likely be back to get more. Thanks

Comments are closed.