OKHTTP_三行程式碼實現檔案下載(dialog顯示進度)
阿新 • • 發佈:2019-02-13
後來寫了一篇檔案下載的,使用的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(); } }