android中实现OkHttp下载文件并带进度条

OkHttp是比较火的网络框架,它支持同步与异步请求,支持缓存,可以拦截,更方便下载大文件与上传文件的操作。下面我们用OkHttp来下载文件并带进度条!

相关资料:

官网地址:http://square.github.io/okhttp/

github源码地址:https://github.com/square/okhttp

一、服务器端简单搭建

可以参考搭建本地Tomcat服务器及相关配置这篇文章。

新建项目OkHttpServer,在WebContent目录下新建downloadfile目录,将要下载的jpg文件放在项目下。如下图:

启动服务器,文件下载地址为http://localhost:8080/OkHttpServer/download/2.jpg 。这样我们服务器就搭好了。

二、Android端

下面我们进入正题。

1.build.gradle的dependencies配置如下

compile 'com.android.support:appcompat-v7:24.1.1'
compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.squareup.okio:okio:1.7.0'

2.activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:paddingBottom="@dimen/activity_vertical_margin"
  android:paddingLeft="@dimen/activity_horizontal_margin"
  android:paddingRight="@dimen/activity_horizontal_margin"
  android:paddingTop="@dimen/activity_vertical_margin"
  tools:context="com.huang.myokhttp.MainActivity">

  <Button
    android:id="@+id/ok_download"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="下载文件" />

  <TextView
    android:id="@+id/download_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:text="0" />

  <ProgressBar
    android:id="@+id/download_progress"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:max="100" />

</RelativeLayout>

3.编写OkHttpUtil如下:

 private static OkHttpClient okHttpClient = new OkHttpClient.Builder().connectTimeout(10000, TimeUnit.MILLISECONDS)
                        .readTimeout(10000,TimeUnit.MILLISECONDS)
                        .writeTimeout(10000,TimeUnit.MILLISECONDS).build();

  //下载文件方法
  public static void downloadFile(String url, final ProgressListener listener, Callback callback){
  //增加拦截器
    OkHttpClient client = okHttpClient.newBuilder().addNetworkInterceptor(new Interceptor() {
      @Override
      public Response intercept(Chain chain) throws IOException {
        Response response = chain.proceed(chain.request());
        return response.newBuilder().body(new ProgressResponseBody(response.body(),listener)).build();
      }
    }).build();

    Request request = new Request.Builder().url(url).build();
    client.newCall(request).enqueue(callback);
  }

4.上面代码中的ProgressResponseBody是自己编写的类,ProgressListener 是监听的接口:

ProgressListener 接口

public interface ProgressListener {
//已完成的 总的文件长度 是否完成
  void onProgress(long currentBytes, long contentLength, boolean done);
}

ProgressResponseBody继承ResponseBody ,返回监听进度

public class ProgressResponseBody extends ResponseBody {
  public static final int UPDATE = 0x01;
  public static final String TAG = ProgressResponseBody.class.getName();
  private ResponseBody responseBody;
  private ProgressListener mListener;
  private BufferedSource bufferedSource;
  private Handler myHandler;
  public ProgressResponseBody(ResponseBody body, ProgressListener listener) {
    responseBody = body;
    mListener = listener;
    if (myHandler==null){
      myHandler = new MyHandler();
    }
  }

  /**
   * 将进度放到主线程中显示
   */
  class MyHandler extends Handler {

    public MyHandler() {
      super(Looper.getMainLooper());
    }

    @Override
    public void handleMessage(Message msg) {
      switch (msg.what){
        case UPDATE:
          ProgressModel progressModel = (ProgressModel) msg.obj;
          //接口返回
          if (mListener!=null)mListener.onProgress(progressModel.getCurrentBytes(),progressModel.getContentLength(),progressModel.isDone());
          break;

      }
    }
  }

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

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

  @Override
  public BufferedSource source() {

    if (bufferedSource==null){
      bufferedSource = Okio.buffer(mySource(responseBody.source()));
    }
    return bufferedSource;
  }

  private Source mySource(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);
        totalBytesRead +=bytesRead!=-1?bytesRead:0;
        //发送消息到主线程,ProgressModel为自定义实体类
        Message msg = Message.obtain();
        msg.what = UPDATE;
        msg.obj = new ProgressModel(totalBytesRead,contentLength(),totalBytesRead==contentLength());
        myHandler.sendMessage(msg);

        return bytesRead;
      }
    };
  }
}

5.MainActivity的代码:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{

  public static final String TAG = MainActivity.class.getName();
  private ProgressBar download_progress;
  private TextView download_text;
  public static String basePath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/okhttp";
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    download_progress = (ProgressBar) findViewById(R.id.download_progress);
    download_text = (TextView) findViewById(R.id.download_text);

    findViewById(R.id.ok_download).setOnClickListener(this);
  }

  @Override
  public void onClick(View view) {
    switch (view.getId()){
      case R.id.ok_download:
        String url = "http://192.168.0.104:8080/OkHttpServer/download/2.jpg";
        final String fileName = url.split("/")[url.split("/").length - 1];
        Log.i(TAG, "fileName==" + fileName);
        OkHttpUtil.downloadFile(url, new ProgressListener() {
          @Override
          public void onProgress(long currentBytes, long contentLength, boolean done) {
            Log.i(TAG, "currentBytes==" + currentBytes + "==contentLength==" + contentLength + "==done==" + done);
            int progress = (int) (currentBytes * 100 / contentLength);
            download_progress.setProgress(progress);
            download_text.setText(progress + "%");
          }
        }, new Callback() {
          @Override
          public void onFailure(Call call, IOException e) {

          }

          @Override
          public void onResponse(Call call, Response response) throws IOException {
            if (response != null) {
              InputStream is = response.body().byteStream();
              FileOutputStream fos = new FileOutputStream(new File(basePath + "/" + fileName));
              int len = 0;
              byte[] buffer = new byte[2048];
              while (-1 != (len = is.read(buffer))) {
                fos.write(buffer, 0, len);
              }
              fos.flush();
              fos.close();
              is.close();
            }
          }
        });
        break;
    }
  }
}

6.最后不要忘了添加权限:

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

源码下载

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • android中用xml文件实现带边框背景效果的方法

    前言 在项目开发的过程中,有时我们会用到带边框的纯色背景图,类似效果如下: 一般的,我们会让设计给做个背景图,然后自己用.9处理一下,这样有些麻烦,我们可以简洁点实现,就是用xml文件. 下面给出一个范例: <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android" &g

  • Android开发实现文件关联方法介绍

    Android开发实现文件关联方法,做一个项目的时候,需要点击文件打开我们自己的app.首先讲一下点击普通文件打开app的方法,只需要三行代码,在app启动活动里加一个过滤器. <intent-filter> <category android:name="android.intent.category.LAUNCHER"> </category></action></intent-filter> <intent-fil

  • Android 将文件下载到指定目录的实现代码

    废话不多说了额,直接给大家贴代码了,具体代码如下所示: /** * 下载指定路径的文件,并写入到指定的位置 * * @param dirName * @param fileName * @param urlStr * @return 返回0表示下载成功,返回1表示下载出错 */ public int downloadFile(String dirName, String fileName, String urlStr) { OutputStream output = null; try { //

  • Android Uri和文件路径互相转换的实例代码

    在项目中需要用到将Uri转换为绝对路径,在网上找到一个方法,做个笔记 网上有不少方法,但是有的对4.4后的版本无效,这里的方法可以在4.4之后的版本将Uri转换为绝对路径 public class GetPathFromUri { /** * 专为Android4.4设计的从Uri获取文件绝对路径 */ public static String getPath(final Context context, final Uri uri) { final boolean isKitKat = Bui

  • Android文件下载功能实现代码

    本文实例为大家分享了Android文件下载功能的具体代码,供大家参考,具体内容如下 1.普通单线程下载文件: 直接使用URLConnection.openStream()打开网络输入流,然后将流写入到文件中! public static void downLoad(String path,Context context)throws Exception { URL url = new URL(path); InputStream is = url.openStream(); //截取最后的文件名

  • Android中实现OkHttp上传文件到服务器并带进度

    在上一讲中 OkHttp下载文件并带进度条 中,我们知道怎样去下载文件了.那上传文件呢 一.编写服务器端 在上一讲服务器下新建UploadFileServlet,代码如下:然后重启服务器! @WebServlet("/UploadFileServlet") @MultipartConfig public class UploadFileServlet extends HttpServlet { private static final long serialVersionUID = 1

  • android中实现OkHttp下载文件并带进度条

    OkHttp是比较火的网络框架,它支持同步与异步请求,支持缓存,可以拦截,更方便下载大文件与上传文件的操作.下面我们用OkHttp来下载文件并带进度条! 相关资料: 官网地址:http://square.github.io/okhttp/ github源码地址:https://github.com/square/okhttp 一.服务器端简单搭建 可以参考搭建本地Tomcat服务器及相关配置这篇文章. 新建项目OkHttpServer,在WebContent目录下新建downloadfile目录

  • Android中使用AsyncTask实现下载文件动态更新进度条功能

    1. 泛型 AysncTask<Params, Progress, Result> Params:启动任务时传入的参数,通过调用asyncTask.execute(param)方法传入. Progress:后台任务执行的进度,若不用显示进度条,则不需要指定. Result:后台任务结束时返回的结果. 2. 重要方法 doInBackground(Params... params):必须重写的方法,后台任务就在这里执行,会开启一个新的线程.params为启动任务时传入的参数,参数个数不定. on

  • Android 下载文件通知栏显示进度条功能的实例代码

    1.使用AsyncTask异步任务实现,调用publishProgress()方法刷新进度来实现(已优化) public class MyAsyncTask extends AsyncTask<String,Integer,Integer> { private Context context; private NotificationManager notificationManager; private NotificationCompat.Builder builder; public M

  • Handler实现线程之间的通信下载文件动态更新进度条

    1. 原理 每一个线程对应一个消息队列MessageQueue,实现线程之间的通信,可通过Handler对象将数据装进Message中,再将消息加入消息队列,而后线程会依次处理消息队列中的消息. 2. Message 初始化:一般使用Message.obtain()方法获取一个消息对象,该方法会检查Message对象池中是否存在可重复利用的对象,若无,才会new一个新对象. what:相当于Message的标识符,区别于其它消息. arg1.arg2:int类型,可传递整数. obj:objec

  • android 中win10 使用uwp控件实现进度条Marquez效果

    本文将告诉大家,如何做一个带文字的进度条,这个进度条可以用在游戏,现在我做的挂机游戏就使用了他. 如何做上图的效果,实际需要的是两个控件,一个是显示文字 的 TextBlock 一个是进度条. 那么如何让 文字和左边的距离变化?使用 TranslateTransform 看起来 Marquez 的界面就是: <ProgressBar x:Name="Mcdon" Maximum="100" Minimum="0" Value="2

  • C# Winform下载文件并显示进度条的实现代码

    方法一: 效果如下图所示: 代码如下: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WinShowDown { public partial class F

  • Android编程实现显示在标题上的进度条功能【附源码下载】

    本文实例讲述了Android编程实现显示在标题上的进度条功能.分享给大家供大家参考,具体如下: 今天我们来学习一下Android中显示在Activity标题上的进度条.在这个例子当中我们还能够学习到很多关于AsyncTask的知识. (1)准备用于显示到界面上的四张图片img01,img02,img03,img04 (2)在Activity的布局文件activity_main.xml中只定义一个线性布局LinearLayout,并为其设置一个id,代码如下: <LinearLayout xmln

  • asp.net单文件带进度条上传的解决方案

    最近做项目中遇到很多问题,比如带进度条的文件上传,看了网上很多资料还没找到真正意义上的ASP.NET实现进度条上传(可能是我没找到),下面我来跟大家分享一下我实现的这个程序. 首先看下界面效果,当然你可以完全修改界面为你自己所用. 先解释一下这个程序,该程序采用了jquery框架,实现了小文件上传,不超过80Mb,可以在web.config文件中进行相应的配置,但是有个最大值,具体需要查看msdn.开发环境采用visual studio 2013 .net framework 4.5,运行的时候

  • Retrofit+RxJava实现带进度条的文件下载

    项目中需要使用到更新版本,因此研究了一下Retrofit的下载文件,和进度条效果,其间也遇到了一些坑,写出来加深一下记忆,也为别的同学提供一下思路. 先说一下版本控制吧,通用做法基本上是通过接口获取服务器存储的app版本号,与应用的版本号进行比较,版本较低就去更新,先看一下如何获取应用版本号吧 PackageManager packageManager = mActivity.getPackageManager(); PackageInfo packageInfo = null; try { p

随机推荐