Electronhub.com - searching electronic component made easy

Android download file with Progressbar okHttp



In android it is often required to download file from server.
I generally use OkHttp and apache common io to download files.

OkHttp : This is the library which I mostly use for my projects.
Apache Common IO : This is the library which I use for file manipulation.

Lets start by adding these library to the build.gradle


    compile group: 'commons-io', name: 'commons-io', version: '2.6'
    compile 'com.facebook.stetho:stetho-okhttp3:1.5.0'





Lets create and util file namely DownloadUtils.java which will be responsible for downloading and showing progress bar.
I just modified the code sample of okHttp for my need



   package skd.app.androidfeatures.utils;


/*
 * Copyright (C) 2015 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import android.app.ProgressDialog;
import android.content.Context;
import android.util.Log;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSource;
import okio.ForwardingSource;
import okio.Okio;
import okio.Source;

public final class DownloadUtils {

    String fileName;
    String fileUrl;
    Context mContext;

    File root = android.os.Environment.getExternalStorageDirectory();
    File downloadDir = new File(root.getAbsolutePath() + "/androidfeatures/"); //it is my root directory
    ProgressDialog progress;
    final int totalProgressTime = 100;

    /**
     * This method will start downloading the file
     */
    public void startDownload() {
        progress.show();
        Log.wtf("SKDINFO", "Download started");
        //setup the dirs
        final File tmpFile = new File(downloadDir.getAbsolutePath() + "/" + fileName);
        if (downloadDir.exists() == false) {
            downloadDir.mkdirs();
            Log.wtf("SKDINFO", "folder created");
        }

        //setup the request
        final Request request = new Request.Builder()
                .url(fileUrl)
                .build();

        //setup the progressListner
        final ProgressListener progressListener = new ProgressListener() {
            boolean firstUpdate = true;

            @Override
            public void update(long bytesRead, long contentLength, boolean done) {
                if (done) {
                    Log.wtf("SKDINFO", "Download Complete");

                } else {

                    if (firstUpdate) {
                        firstUpdate = false;
                        if (contentLength == -1) {
                            Log.wtf("SKDINFO", "content-length: unknown");
                        } else {
                            Log.wtf("SKDINFO", "content-length: " + contentLength);
                        }
                    }


                    if (contentLength != -1) {
                        Log.wtf("SKDINFO", "" + (100 * bytesRead) / contentLength);
                        progress.setProgress((int)((100 * bytesRead) / contentLength));
                    }
                }
            }
        };


        //init okHttp client
        final OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(60, TimeUnit.MILLISECONDS)
                .readTimeout(60,TimeUnit.SECONDS)
                .addNetworkInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Response originalResponse = chain.proceed(chain.request());
                        return originalResponse.newBuilder()
                                .body(new ProgressResponseBody(originalResponse.body(), progressListener))
                                .build();
                    }
                })
                .build();

        //send the request and write the file

            Log.wtf("SKDINFO", "Download Starting");

            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Response response = client.newCall(request).execute();

                        if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

                        //download Success now
                        Log.wtf("SKDINFO", "Download Completed");
                        FileUtils.copyInputStreamToFile(response.body().byteStream(), tmpFile);
                        response.close(); //close reponse to avoid memory leak
                        progress.dismiss();
                    }catch (IOException e)
                    {
                        e.printStackTrace();
                        progress.dismiss();

                    }

                }
            }).start();





    }

  public DownloadUtils(Context context, String fileUrl, String fileName) {
        this.fileUrl = fileUrl;
        this.fileName = fileName;
        this.mContext = context;
        progress = new ProgressDialog(context);
        progress.setMessage("Downloading form ");
        progress.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        progress.setIndeterminate(false);
        progress.setCancelable(false);

      Log.wtf("SKDINFO", "DownloadUtils" + fileName);

    }

    /**
     * custom response body
     */
    private static class ProgressResponseBody extends ResponseBody {

        private final ResponseBody responseBody;
        private final ProgressListener progressListener;
        private BufferedSource bufferedSource;

        ProgressResponseBody(ResponseBody responseBody, ProgressListener progressListener) {
            this.responseBody = responseBody;
            this.progressListener = progressListener;
        }

        @Override
        public MediaType contentType() {
            return responseBody.contentType();
        }

        @Override
        public long contentLength() {
            return responseBody.contentLength();
        }

        @Override
        public BufferedSource source() {
            if (bufferedSource == null) {
                bufferedSource = Okio.buffer(source(responseBody.source()));
            }
            return bufferedSource;
        }


        private Source source(Source source) {
            return new ForwardingSource(source) {
                long totalBytesRead = 0L;

                @Override
                public long read(Buffer sink, long byteCount) throws IOException {
                    long bytesRead = super.read(sink, byteCount);
                    // read() returns the number of bytes read, or -1 if this source is exhausted.
                    totalBytesRead += bytesRead != -1 ? bytesRead : 0;
                    progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1);
                    return bytesRead;
                }
            };
        }
    }

    /**
     * Listner
     */
    interface ProgressListener {
        void update(long bytesRead, long contentLength, boolean done);
    }


}




Now Lets use this class.
Create and activity with a button in the layout.


public class DownladActivity extends AppCompatActivity {


    Button downloadbtn;
    Context mContext;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_downlad);
        mContext = this;

        downloadbtn = (Button) findViewById(R.id.button6);

        Log.wtf("SKDINFO", "download activity");


        downloadbtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Toast.makeText(mContext, "Start", Toast.LENGTH_SHORT).show();
                DownloadUtils down = new DownloadUtils(mContext, "http://mirrors.jenkins.io/war-stable/latest/jenkins.war", "package.zip");
                // DownloadUtils down = new DownloadUtils(mContext,"http://192.168.0.106/test/package.zip","package.zip");
                down.startDownload();


            }
        });


    }
}








Comments

  1. Extremely useful information which you have shared here about Android app development. This is a great way to enhance knowledge for us, and also beneficial for us. Thank you for sharing a post like this. Android development agency

    ReplyDelete
  2. Your blog is really appreciable. We had also create customized solutions using latest technology at affordable cost to help your start-up grow.
    Hire Mobile App Development Company

    ReplyDelete
  3. NekoPoi Android APK was developed and offered by nekopoi mod apk for Android users around the world to read their favorite content in one place for free.

    ReplyDelete
  4. terimakasih informasinya apakah ada Lowongan Kerja untuk saya?

    ReplyDelete

Post a Comment