1. 程式人生 > >OKHTTP_三行程式碼實現檔案下載(dialog顯示進度)

OKHTTP_三行程式碼實現檔案下載(dialog顯示進度)

後來寫了一篇檔案下載的,使用的Xutil框架 ,穩定性更佳,建議大家使用,大型檔案不推薦OKHTTp

部落格地址 :http://blog.csdn.net/fkgjdkblxckvbxbgb/article/details/78273687

週末早,接下來幾篇部落格會對網路請求以及上傳下載進行一個最後是總結 。

封裝一個下載的工具類,使用OKHTTP實現帶進度條下載,dialog彈窗顯示進度。目前專案的網路請求框架基本都使用OKhttp,下載,上傳 用這個也是好的,看圖

本來是做的是電視版本的,用虛擬機器測試的,dialog樣式有變化 ,可以自己在專案中修改dialog的相關尺寸

不做和斷點續傳相關的,專案中的下載請求檔案較小,沒必要 。

專案是5.0的手機測試的,如果有更高的版本,請自行處理讀寫記憶體卡相關的許可權 。


先看主介面相關的程式碼,4行搞定 。

專案的類不多 ,思路清晰,結構簡單,可以直接拿過來稍微改定就可以在專案中使用。

完整程式碼下載地址 : http://download.csdn.net/detail/fkgjdkblxckvbxbgb/9907051

String downUrl = "http://58.63.233.48/app.znds.com/down/20170712/ystjg_2.6.0.1059_dangbei.apk";
String downPath = URL_VIDEO + "/tengxun.apk";
downManager = new DownManager(MainActivity.this); downManager.downSatrt(downUrl, downPath, "是否下載《騰訊視訊》");

使用dawnManager去封裝下載util,和dialog的顯示以及dialog進度條的更新

package com.reeman.demo.http;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.widget.Toast;
import com.reeman.demo.http.dialog.DownDialog; public class DownManager implements DownListener, DownDialog.DownDialogListener { Context context; DownDialog downDialog; DownUtil downUtil; public DownManager(Context context) { this.context = context; downDialog = new DownDialog(context); downDialog.setOnDialogClickListener(this); downUtil = new DownUtil(this); } public static final int DOWN_START = 0; public static final int DOWN_PROGRESS = DOWN_START + 1; public static final int DOWN_SUCCESS = DOWN_PROGRESS + 1; public static final int DOWN_FAILED = DOWN_SUCCESS + 1; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case DOWN_START: downDialog.updateView(0, "準備下載", 0); break; case DOWN_PROGRESS: int progress = msg.arg1; long speed = (long) msg.obj; downDialog.updateView(progress, "下載中", speed); break; case DOWN_SUCCESS: downDialog.updateView(100, "下載完成", 0); downDialog.dissmiss(); Toast.makeText(context, "下載完成", Toast.LENGTH_SHORT).show(); break; case DOWN_FAILED: downDialog.updateView(0, "下載異常", 0); break; } } }; /*** * 開始下載 * @param downUrl * 下載地址 * @param downPath * 儲存的地址 * @param desc * dialog顯示的描述 */ String downUrl; String downPath; public void downSatrt(String downUrl, String downPath, String desc) { this.downUrl = downUrl; this.downPath = downPath; downDialog.show(desc); } @Override public void downStart() { handler.sendEmptyMessage(DOWN_START); } @Override public void downProgress(int progress, long speed) { Message msg = new Message(); msg.what = DOWN_PROGRESS; msg.arg1 = progress; msg.obj = speed; handler.sendMessage(msg); } @Override public void downSuccess(String downUrl) { handler.sendEmptyMessage(DOWN_SUCCESS); } @Override public void downFailed(String failedDesc) { handler.sendEmptyMessage(DOWN_FAILED); } @Override public void noSure() { downUtil.cacleDown(); } @Override public void sure() { downUtil.downFile(downUrl, downPath); } }

下載狀態介面

package com.reeman.demo.http;
public interface DownListener {
    /**
     * 開始下載
*/
void downStart();
/***
     * 下載進度,和速度
* @param progress
* @param speed
*/
void downProgress(int progress, long speed);
/***
     * 下載完成
* @param downUrl
*/
void downSuccess(String downUrl);
/***
     * 下載失敗
* @param failedDesc
*/
void downFailed(String failedDesc);
}

下載的util

package com.reeman.demo.http;
import android.os.Environment;
import android.util.Log;
import android.webkit.DownloadListener;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Dispatcher;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
/**
 * Created by reeman on 2017/7/21.
 */
public class DownUtil implements Callback {

    OkHttpClient mOkHttpClient;
DownListener downListener;
String downPath;
String downUrl;
    public DownUtil(DownListener downListener) {
        this.downListener = downListener;
mOkHttpClient = new OkHttpClient.Builder()
                .connectTimeout(10, TimeUnit.SECONDS)
                .readTimeout(10, TimeUnit.SECONDS)
                .build();
}


    public void downFile(String downUrl, String downPath) {
        this.downUrl = downUrl;
        this.downPath = downPath;
        try {
            downListener.downStart();
String downDir = downPath.substring(0, downPath.lastIndexOf("/")).trim();
String downName = downPath.substring(downPath.lastIndexOf("/") + 1, downPath.length()).trim();
Log.i("down", "下載地址==" + downDir + "   下載的名字==" + downName);
File destDir = new File(downDir);
            if (destDir.isDirectory() && !destDir.exists()) {
                destDir.mkdirs();
}
            Request request = new Request.Builder().url(downUrl).build();
mOkHttpClient.newCall(request).enqueue(this);
} catch (Exception e) {
            downListener.downFailed(e.toString());
Log.d("down", "=================error==" + e.toString());
}
    }

    public void cacleDown() {
        Dispatcher dispatcher = mOkHttpClient.dispatcher();
//        for (Call call : dispatcher.queuedCalls()) {
//            call.cancel();
//        }
for (Call call : dispatcher.runningCalls()) {
            call.cancel();
}
    }


    @Override
public void onFailure(Call call, IOException e) {
        downListener.downFailed(e.toString());
Log.d("down", "onFailure");
}

    @Override
public void onResponse(Call call, Response response) throws IOException {
        InputStream is = null;
        byte[] buf = new byte[2048];
        int len = 0;
FileOutputStream fos = null;
        try {
            is = response.body().byteStream();
            long total = response.body().contentLength();
File file = new File(downPath);
            if (file.exists()) {
                Log.i("down", "檔案存在,刪除檔案==");
file.delete();
}
            if (!file.exists() && file.isFile()) {
                Log.i("down", "下載檔案不存在建立檔案==");
                boolean isCreat = file.createNewFile();
Log.i("down", "建立檔案==" + isCreat);
}
            fos = new FileOutputStream(file);
            long sum = 0;
            long saveSum = 0;
            while ((len = is.read(buf)) != -1) {
                fos.write(buf, 0, len);
sum += len;
                final int progress = (int) (sum * 1.0f / total * 100);
                final long speed = sum - saveSum;
saveSum = sum;
Log.d("down", "===================" + progress + "  speed =" + speed);
updateProgress(progress, speed);
}
            fos.flush();
downListener.downSuccess(downPath);
Log.d("down", "=================success==");
} catch (Exception e) {
            downListener.downFailed(e.toString());
Log.d("down", "=================error==" + e.toString());
} finally {
            if (is != null)
                is.close();
            if (fos != null)
                fos.close();
}
    }

    int lastProgress = 0;
    private void updateProgress(int progress, long speed) {
        if (progress > lastProgress) {
            downListener.downProgress(progress, speed);
}
        lastProgress = progress;
}


}

下載的顯示dialog ,裡面有一個自定義的藍色的進度條,可以直接替換android 自帶的progressBar,完整程式碼,在文章頂部

package com.reeman.demo.http.dialog;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.Window;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
import com.reeman.demo.R;
import com.reeman.demo.http.view.RopeProgressBar;
public class DownDialog {
    private Dialog dialog;
DownDialogListener dialogClick;
    public RopeProgressBar view_progress;
    public TextView tv_title;
    public TextView tv_speed;
Context context;
    private TextView tv_desc_update;
/***
     * 重新整理dialog
     *
     * @param progress
*            進度
* @param desc
*            下載秒速
* @param speed
*            下載速度
*/
public void updateView(int progress, String desc, long speed) {
        view_progress.setProgress(progress);
tv_title.setTextColor(0xff1fbaf3);
tv_title.setText("檔案下載(" + desc + ")");
tv_speed.setText(speed + " kb/s");
        if (desc.contains("異常")) {
            tv_title.setTextColor(Color.RED);
tv_title.setText("下載異常,請重新啟動程式");
}
    }

    public DownDialog(final Context context) {
        this.context = context;
        if (dialog == null) {
            dialog = new Dialog(context, R.style.MyDialog);
}
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        int width = 800;
        int height = 1280;
LayoutParams params = new RelativeLayout.LayoutParams(width, height);
View dialog_view = View.inflate(context, R.layout.dialog_down, null);
dialog.setContentView(dialog_view, params);
dialog.setCancelable(false); // true點選螢幕以外關閉dialog
tv_title = (TextView) dialog_view.findViewById(R.id.dialog_title);
tv_desc_update = (TextView) dialog_view.findViewById(R.id.tv_desc_update);
tv_speed = (TextView) dialog_view.findViewById(R.id.tv_speed);
btn_no = (Button) dialog_view.findViewById(R.id.btn_dialog_no);
btn_dialog_yes = (Button) dialog_view.findViewById(R.id.btn_dialog_yes);
view_progress = (RopeProgressBar) dialog_view.findViewById(R.id.update_progress);
btn_dialog_yes.setOnClickListener(new OnClickListener() {
            @SuppressLint("ResourceAsColor")
            public void onClick(View v) {
                view_progress.setVisibility(View.VISIBLE);
tv_desc_update.setVisibility(View.INVISIBLE);
btn_dialog_yes.setVisibility(View.GONE);
dialogClick.sure();
}
        });
btn_no.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                if (dialogClick != null) {
                    dialogClick.noSure();
dissmiss();
}
            }
        });
btn_no.setBackgroundColor(0xffB3B3B3);
btn_dialog_yes.setBackgroundColor(0xffB3B3B3);
btn_no.setOnFocusChangeListener(onFocusChangeListener);
btn_dialog_yes.setOnFocusChangeListener(onFocusChangeListener);
}

    private OnFocusChangeListener onFocusChangeListener = new OnFocusChangeListener() {

        @Override
public void onFocusChange(View v, boolean hasFocus) {
            if (hasFocus) {
                v.setBackgroundColor(Color.BLUE);
} else {
                v.setBackgroundColor(0xffB3B3B3);
}
        }
    };
Button btn_no;
    final Button btn_dialog_yes;
    public void show(String desc) {
        view_progress.setVisibility(View.INVISIBLE);
tv_desc_update.setVisibility(View.VISIBLE);
        if (desc != null && desc.length() > 4) {
            tv_desc_update.setText(desc);
}
        tv_speed.setText("0kb/s");
dialog.show();
}

    public void dissmiss() {
        if (dialog == null) {
            return;
}
        btn_dialog_yes.setVisibility(View.VISIBLE);
        if (dialog.isShowing()) {
            dialog.dismiss();
}
    }

    public void setOnDialogClickListener(DownDialogListener dc) {
        dialogClick = dc;
}

    public interface DownDialogListener {
        void noSure();
        void sure();
}

}