OKHTTP_三行代码实现文件下载(dialog显示进度)
后来写了一篇文件下载的,使用的Xutil框架 ,稳定性更佳,建议大家使用,大型文件不推荐OKHTTp
博客地址 :http://blog.****.net/fkgjdkblxckvbxbgb/article/details/78273687
周末早,接下来几篇博客会对网络请求以及上传下载进行一个最后是总结 。
封装一个下载的工具类,使用OKHTTP实现带进度条下载,dialog弹窗显示进度。目前项目的网络请求框架基本都使用OKhttp,下载,上传 用这个也是好的,看图
本来是做的是电视版本的,用虚拟机测试的,dialog样式有变化 ,可以自己在项目中修改dialog的相关尺寸
不做和断点续传相关的,项目中的下载请求文件较小,没必要 。
项目是5.0的手机测试的,如果有更高的版本,请自行处理读写内存卡相关的权限 。
先看主界面相关的代码,4行搞定 。
项目的类不多 ,思路清晰,结构简单,可以直接拿过来稍微改定就可以在项目中使用。
完整代码下载地址 : http://download.****.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(); } }