上一篇我们讲到了使用OKhttp实现文件上传,还有不清楚文件上传的小伙伴可以去看看。

今天,我们的重点是使用OKhttp实现文件下载,还是老规矩,先看效果:

我这个人写博文喜欢把效果先放出来,为什么呢?因为我觉得这样能方便小伙伴们知道,这是不是我所需要的效果,而不是看我长篇大论之后,发现并没有自己想要的。

我来解释一下大致的流程,还是和上一篇文件上传一样的界面,不同的是,现在我是有文本信息的:

  • 点击对应文件,弹出一个弹框,点击确认之后开始下载
  • 下载成功后,进度条会有提示
  • 同时系统会发送一个通知,告诉你文件下载成功

这里我们就不搞那么复杂了,关于弹框和进度条、通知栏啥的,就不细讲了,我们的重头戏是文件下载,那就从点击确定之后开始说咯?

好吧,这里又是两个封装好的工具类,大家接好了:

然后,你们会发现,这里我又把token放到请求头里去了,所以,为了不误人子弟,我还是默默注释了吧,放上正常的。

public class DownloadUtil {private static DownloadUtil downloadUtil;private final OkHttpClient okHttpClient;private Context context;private String TAG = "下载页面";public static DownloadUtil get() {if (downloadUtil == null) {downloadUtil = new DownloadUtil();}return downloadUtil;}private DownloadUtil() {okHttpClient = new OkHttpClient();}/*** @param url 下载连接* @param saveDir 储存下载文件的SDCard目录* @param listener 下载监听*/public void download(Context context, final String url, final String saveDir,final String fileName, final OnDownloadListener listener) {this.context= context;// 需要token的时候可以这样做// SharedPreferences sp=MyApp.getAppContext().getSharedPreferences("loginInfo", MODE_PRIVATE);// Request request = new Request.Builder().header("token",sp.getString("token" , "")).url(url).build();Request request = new Request.Builder().url(url).build();okHttpClient.newCall(request).enqueue(new Callback() {@Overridepublic void onFailure(Call call, IOException e) {// 下载失败listener.onDownloadFailed();}@Overridepublic void onResponse(Call call, Response response) throws IOException {InputStream is = null;byte[] buf = new byte[2048];int len = 0;FileOutputStream fos = null;// 储存下载文件的目录String savePath = isExistDir(saveDir);Log.w(TAG,"存储下载目录:"+savePath);try {is = response.body().byteStream();long total = response.body().contentLength();File file = new File(savePath, getNameFromUrl(fileName));Log.w(TAG,"最终路径:"+file);fos = new FileOutputStream(file);long sum = 0;while ((len = is.read(buf)) != -1) {fos.write(buf, 0, len);sum += len;int progress = (int) (sum * 1.0f / total * 100);// 下载中listener.onDownloading(progress);}fos.flush();// 下载完成listener.onDownloadSuccess();} catch (Exception e) {listener.onDownloadFailed();} finally {try {if (is != null)is.close();} catch (IOException e) {}try {if (fos != null)fos.close();} catch (IOException e) {}}}});}/*** @param saveDir* @return* @throws IOException* 判断下载目录是否存在*/private String isExistDir(String saveDir) throws IOException {// 下载位置File downloadFile = new File(Environment.getExternalStorageDirectory().getPath() + "/download/", saveDir);if (!downloadFile.mkdirs()) {downloadFile.createNewFile();}String savePath = downloadFile.getAbsolutePath();Log.w(TAG,"下载目录:"+savePath);return savePath;}/*** @param url* @return* 传入文件名*/@NonNullpublic String getNameFromUrl(String url) {return url;}public interface OnDownloadListener {/*** 下载成功*/void onDownloadSuccess();/*** @param progress* 下载进度*/void onDownloading(int progress);/*** 下载失败*/void onDownloadFailed();}
}

emm,还有一个:

public class FileProviderUtils {public static Uri getUriForFile(Context mContext, File file) {Uri fileUri = null;if (Build.VERSION.SDK_INT >= 24) {fileUri = getUriForFile24(mContext, file);} else {fileUri = Uri.fromFile(file);}return fileUri;}public static Uri getUriForFile24(Context mContext, File file) {Uri fileUri = android.support.v4.content.FileProvider.getUriForFile(mContext,BuildConfig.APPLICATION_ID + ".fileProvider",file);return fileUri;}public static void setIntentDataAndType(Context mContext,Intent intent,String type,File file,boolean writeAble) {if (Build.VERSION.SDK_INT >= 24) {intent.setDataAndType(getUriForFile(mContext, file), type);intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);if (writeAble) {intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);}} else {intent.setDataAndType(Uri.fromFile(file), type);}}
}

哇,写到这,我不得不吐槽一句,有时候真的是一失足成千古恨呐,之前搞这个搞了好久,报的啥错有点忘了,但好歹把方法总结了。说白了,还是太粗心。

所以才一直强调要注意细节,注意细节,注意细节,重要的事情说三次!

好了,回到正题,前方高能,一定要确保这些步骤:

1. AndroidManifest.xml

        <providerandroid:name="android.support.v4.content.FileProvider"android:authorities="com.manage_system.fileProvider"android:grantUriPermissions="true"android:exported="false"><meta-dataandroid:name="android.support.FILE_PROVIDER_PATHS"android:resource="@xml/file_paths" /></provider>

不知道你有没有注意到第二个工具类FileProviderUtils里有这样一个方法:

public static Uri getUriForFile24(Context mContext, File file) {
        Uri fileUri = android.support.v4.content.FileProvider.getUriForFile(mContext,
                BuildConfig.APPLICATION_ID + ".fileProvider",
                file);
        return fileUri;
    }

这里的.fileProvider就是和我们xml文件对应的,而这里最重要的是resource中我们在xml中自定义的file_paths。

2. file_paths.xml

与普通文件一样,在xml文件夹里新建一个,就是这样:

里面就写你下载的路径,我自己自定义的路径是 “ /download/ ”,可以参考下:

<?xml version="1.0" encoding="utf-8"?>
<paths><external-path path="download/" name="download" />
</paths>

好了,现在是万事俱备,只欠东风了。怎么调用这个方法呢?

调用之前,提醒一句,确保文件的读写权限在AndroidManifest.xml配置好了。

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

调用方法如下:

// url服务器地址,saveurl是下载路径,fileName表示的是文件名字
DownloadUtil.get().download(this, url,saveurl,fileName,  new DownloadUtil.OnDownloadListener() {@Overridepublic void onDownloadSuccess() {runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(TeacherThesisCommentActivity.this, "下载成功", Toast.LENGTH_SHORT).show();// 这里的弹框设置了进度条,下同dialog.dismiss();if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {return;}File file = new File(Environment.getExternalStorageDirectory().getPath() + "/download/"+fileName);Log.w(TAG,"路径2:"+file);try {Log.w(TAG,"打开");OpenFileUtils.openFile(mContext, file);} catch (Exception e) {Log.w(TAG,"无打开方式");e.printStackTrace();}}});}@Overridepublic void onDownloading(int progress) {dialog.setProgress(progress);}@Overridepublic void onDownloadFailed() {runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(TeacherThesisCommentActivity.this, "下载失败", Toast.LENGTH_SHORT).show();dialog.dismiss();}});}});

这里提两句,你可能看到里面有进度条的dialog,是因为在前面我有自定义下载进度条,如果不需要的话可以去掉。要这个效果的,可以看看下面:

                //文件在手机内存存储的路径final String saveurl="/download/";Log.w(TAG,"路径1:"+saveurl);//配置progressDialogfinal ProgressDialog dialog= new ProgressDialog(TeacherThesisCommentActivity.this);dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);dialog.setCanceledOnTouchOutside(false);dialog.setCancelable(true);dialog.setTitle("正在下载中");dialog.setMessage("请稍后...");dialog.setProgress(0);dialog.setMax(100);dialog.show();

评论里有小伙伴提醒我漏了一个OpenFileUtils.java文件,这里补上:

import android.content.Context;
import android.content.Intent;import java.io.File;public class OpenFileUtils {/*** 声明各种类型文件的dataType**/private static final String DATA_TYPE_APK = "application/vnd.android.package-archive";private static final String DATA_TYPE_VIDEO = "video/*";private static final String DATA_TYPE_AUDIO = "audio/*";private static final String DATA_TYPE_HTML = "text/html";private static final String DATA_TYPE_IMAGE = "image/*";private static final String DATA_TYPE_PPT = "application/vnd.ms-powerpoint";private static final String DATA_TYPE_EXCEL = "application/vnd.ms-excel";private static final String DATA_TYPE_WORD = "application/msword";private static final String DATA_TYPE_CHM = "application/x-chm";private static final String DATA_TYPE_TXT = "text/plain";private static final String DATA_TYPE_PDF = "application/pdf";/*** 未指定明确的文件类型,不能使用精确类型的工具打开,需要用户选择*/private static final String DATA_TYPE_ALL = "*/*";/*** 打开文件* @param mContext* @param file*/public static void openFile(Context mContext, File file) {if (!file.exists()) {return;}// 取得文件扩展名String end = file.getName().substring(file.getName().lastIndexOf(".") + 1, file.getName().length()).toLowerCase();// 依扩展名的类型决定MimeTypeswitch (end) {case "3gp":case "mp4":openVideoFileIntent(mContext, file);break;case "m4a":case "mp3":case "mid":case "xmf":case "ogg":case "wav":openAudioFileIntent(mContext, file);break;case "doc":case "docx":commonOpenFileWithType(mContext, file, DATA_TYPE_WORD);break;case "xls":case "xlsx":commonOpenFileWithType(mContext, file, DATA_TYPE_EXCEL);break;case "jpg":case "gif":case "png":case "jpeg":case "bmp":commonOpenFileWithType(mContext, file, DATA_TYPE_IMAGE);break;case "txt":commonOpenFileWithType(mContext, file, DATA_TYPE_TXT);break;case "htm":case "html":commonOpenFileWithType(mContext, file, DATA_TYPE_HTML);break;case "apk":commonOpenFileWithType(mContext, file, DATA_TYPE_APK);break;case "ppt":commonOpenFileWithType(mContext, file, DATA_TYPE_PPT);break;case "pdf":commonOpenFileWithType(mContext, file, DATA_TYPE_PDF);break;case "chm":commonOpenFileWithType(mContext, file, DATA_TYPE_CHM);break;default:commonOpenFileWithType(mContext, file, DATA_TYPE_ALL);break;}}/*** Android传入type打开文件* @param mContext* @param file* @param type*/public static void commonOpenFileWithType(Context mContext, File file, String type) {Intent intent = new Intent(Intent.ACTION_VIEW);intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);intent.addCategory(Intent.CATEGORY_DEFAULT);FileProviderUtils.setIntentDataAndType(mContext, intent, type, file, true);mContext.startActivity(intent);}/*** Android打开Video文件* @param mContext* @param file*/public static void openVideoFileIntent(Context mContext, File file) {Intent intent = new Intent(Intent.ACTION_VIEW);intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);intent.putExtra("oneshot", 0);intent.putExtra("configchange", 0);FileProviderUtils.setIntentDataAndType(mContext, intent, DATA_TYPE_VIDEO, file, false);mContext.startActivity(intent);}/*** Android打开Audio文件* @param mContext* @param file*/private static void openAudioFileIntent(Context mContext, File file) {Intent intent = new Intent(Intent.ACTION_VIEW);intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);intent.putExtra("oneshot", 0);intent.putExtra("configchange", 0);FileProviderUtils.setIntentDataAndType(mContext, intent, DATA_TYPE_AUDIO, file, false);mContext.startActivity(intent);}
}

android中使用okhttp实现文件下载相关推荐

  1. Android中使用OKHttp上传图片,从相机和相册中获取图片并剪切

    Android中使用OKHttp上传图片,从相机和相册中获取图片并剪切 效果: 注意: 1:网络权限 <uses-permission android:name="android.pe ...

  2. okhttp post php,Android_详解Android中使用OkHttp发送HTTP的post请求的方法,HTTP POST 和 PUT 请求可以包含要 - phpStudy...

    详解Android中使用OkHttp发送HTTP的post请求的方法 HTTP POST 和 PUT 请求可以包含要提交的内容.只需要在创建 Request 对象时,通过 post 和 put 方法来 ...

  3. Android中的OKHttp请求网络

    OKHttp 文章目录 OKHttp 一.简介 二.基本用法 1.依赖 2.使用OKHttp 2.1.get请求 2.2.post请求 3.案例操作演示(借助runOnUiThread()方法进行线程 ...

  4. Android中使用AsyncTask实现文件下载以及进度更新提示

    Android提供了一个工具类:AsyncTask,它使创建需要与用户界面交互的长时间运行的任务变得更简单.相对Handler来说AsyncTask更轻量级一些,适用于简单的异步处理,不需要借助线程和 ...

  5. android http常用配置,Android中Retrofit+OkHttp进行HTTP网络编程的使用指南

    Retrofit介绍:Retrofit(GitHub主页https://github.com/square/okhttp)和OkHttp师出同门,也是Square的开源库,它是一个类型安全的网络请求库 ...

  6. Android中使用封装的OKHttp上传图片,从相机和相册中获取图片并剪切

    Android中使用OKHttp上传图片,从相机和相册中获取图片并剪切 效果: 注意: 1:网络权限 <uses-permission android:name="android.pe ...

  7. 一个整合OkHttp 、Retrofit 、Volley 、RxJava、Novate多种开源网络框架的项目,高度的封装和集成,Android中Web网络请求一行代码解决

    一个整合OkHttp .Retrofit .Volley .RxJava.Novate多种开源网络框架的项目,高度的封装和集成,Android中Web网络请求一行代码解决 AndroidHttp 一个 ...

  8. android项目中使用的服务器上,android 开发中使用okhttp上传文件到服务器

    开发android手机客户端,常常会需要上传文件到服务器,比如:你手机里的照片. 使用okhttp会是一个很好的选择.它使用很简单,而且运行效率也很高. 首先,在 app/build.gradle 的 ...

  9. android文件下载功能实现,Android中DownloadManager实现文件下载实例详解

    Android中DownloadManager实现文件下载 下载 创建下载链接 DownloadManager.Request request = new DownloadManager.Reques ...

最新文章

  1. .net框架、CLR和C#的版本之间的对应关系
  2. jAVA not find main_java编程时出现Could not find the main class 怎么解决???
  3. ORACLE REDO 日志调整
  4. 高能同步辐射光源科学数据管理策略研究与应用
  5. iphone字体_朋友圈换个花样字体,发个朋友圈也高级过人
  6. 04-Bootstrap的插件
  7. 案例-图片缩放(CSS3)
  8. Proc恢复数据文件
  9. HDU 1213 How Many Tables 并查集 水~
  10. Hive之表类型解析
  11. html5中标签与类的区别,html5中section标签与div标签的区别是什么
  12. mysql exist和in的区别
  13. java的百度编辑器插件下载安装_ueditor-extend
  14. 小鱼易连 for mac常见问题解答
  15. mysql 拖库_【渗透测试】温故知新之拖库七种方法
  16. django.relatedField-关联域
  17. Android安卓备份还原
  18. linux下用户名怎么修改密码,LINUX用户名密码忘记怎么修改用户密码
  19. Python基础:函数的返回值return
  20. 遥感影像处理的几个概念

热门文章

  1. QQ移动端个人信息模块测试用例
  2. 从 Netflix 传奇看,结果导向的产品路线图如何制定?(下篇)
  3. 咒术师学院spellcaster university for mac
  4. OLE:对象的类没有在注册数据库中注册 问题的三种解决方法
  5. SourceGrid 2.0_ 翻译(1)
  6. salt ext_pillar
  7. react如何引入css
  8. photoshop裁剪图片
  9. NC6 查询工具类 QueryUtil.java
  10. 信管141王涵 1425052001 自我介绍