Android 开发 框架系列 OkHttp使用详解

简介

okhttp是一个第三方类库,用于android中请求网络。这是一个开源项目,是安卓端最火热的轻量级框架,由移动支付Square公司贡献(该公司还贡献了Picasso和LeakCanary) 。用于替代HttpUrlConnection和Apache HttpClient(android API23 里已移除HttpClient)。

Android studio工程依赖:

implementation 'com.squareup.okhttp3:okhttp:3.11.0'

同步请求方式(get请求)

步骤一  创建请求接口网址

我使用了http://www.sosoapi.com/ 来创建了一个访问接口,用来验证OkHttp是否请求成功。如果你有兴趣了解,可以直接进入网站,里面有详细的demo演示。后续我将不在赘述这段。

我在请求响应里添加了一段JSON数据:

[
    {
        "name": "get测试",
        "content": "你成功获取了数据"
    }
]
步骤二  创建JSON解析方法

这里我写一下解析JSON数据的方法,来解析get或者post得到的JSON数据。后续我将不在赘述这段。

/**
     * JSON 解析方法
     * @param jsonData
     * @return
     */
    public String readJSONContent(String jsonData){
        try {
            StringBuffer sb = new StringBuffer();
            JSONArray jsonArray = new JSONArray(jsonData);
            for (int i=0;i<jsonArray.length();i++){
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                sb.append(jsonObject.getString("name")+"\n");
                sb.append(jsonObject.getString("content")+"\n");
            }
            return sb.toString();
        } catch (JSONException e) {
            Log.e("JSONException错误", "readContent: "+e.toString());
            return e.toString();
        }
    }
步骤三  创建OkHttp 同步请求
/**
     * 同步请求
     */
    public void synchro(){
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                OkHttpClient okHttpClient = new OkHttpClient();//创建单例
                Request request = new Request.Builder()//创建请求
                        .url("http://www.sosoapi.com/pass/mock/12003/test/gettest")
                        .build();
                try {
                    Response response = okHttpClient.newCall(request).execute();//执行请求
                    mContent = response.body().string();//得到返回响应

                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mtextView.setText(readJSONContent(mContent));
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e("OkHttpActivity", e.toString() );
                }
            }
        });
        thread.start();
    }

效果图:

异步请求方式(get请求)

注意1:异步请求方式,请求的回调会在子线程里,所以如果需要更新UI你需要切换到主线程。且你不需要在new 一个线程包裹这个异步请求了。另外如何切换到主线程请使用 Handler 例子:

注意2:在异步请求方法里,请不要将 public void onResponse(Call call, final Response response)回调里的response回调数据放到UI线程里解析,因为有一个天坑,有可能在UI线程里解析的时候response里面却还没有塞入数据(我也觉得很神奇,不知道写okhttp的公司是怎么想的,为什么不处理完所有数据在提供回调)

 

private Handler mHandler = new Handler(Looper.getMainLooper());
            mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        //主线程

                    }
                });    

创建异步请求

     /**
     * get异步请求
     */
      public void asynchronous(){
          OkHttpClient okHttpClient = new OkHttpClient();
          Request request = new Request.Builder()
                  .url("http://www.sosoapi.com/pass/mock/12003/test/gettest")
                  .build();
          okHttpClient.newCall(request).enqueue(new Callback() {
              @Override
              public void onFailure(Call call, IOException e) {
                  //失败回调

              }

              @Override
              public void onResponse(Call call, final Response response) throws IOException {
            mContent = readJSONContent(response.body().string());
//响应成功,这个回调在子线程中,所以不需要创建线程 if (response.isSuccessful()){ //isSuccessful方法:如果代码位于(200…300)中,则返回true,这意味着请求已成功接收 runOnUiThread(new Runnable() { @Override public void run() { try { //因为在子线程,所以我们需要回到主线程中更新UI数据 mtextView.setText(mContent); } catch (IOException e) { e.printStackTrace(); } } }); } } }); }

Post请求

post请求也同时有同步与异步方法,与上面一致,所以这里就不展示了,下面我们来看看post请求发送

/**
     * post请求
     */
    public void post(){
        new Thread(new Runnable() {
            @Override
            public void run() {
                //实例
                OkHttpClient okHttpClient = new OkHttpClient();

                //创建post请求数据表单
                RequestBody requestBody = new FormBody.Builder()
                        .add("name","请求post")
                        .add("password","123456")
                        .build();
                //创建请求
                final Request request = new Request.Builder()
                        .url("http://www.sosoapi.com/pass/mock/12003/test/posttest")
                        .post(requestBody)//添加post请求
                        .build();

                try {
                    //发送请求得到响应
                    final Response response = okHttpClient.newCall(request).execute();
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                mtextView.setText(readJSONContent(response.body().string()));
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }).start();

    }

效果图:

取消网络请求

取消okhttp的网络请求很简单只需要

call.cancel();

如何鉴别是网络异常还是主动取消,请求取消的回调在onFailure(Call call, IOException e)里回调,这个时候我们需要再次判断onFailure里回调的是我们自己主动取消的还是网络异常报错的

mCall.enqueue(new Callback() {//发送请求
    @Override
    public void onFailure(final Call call, final IOException e) {
        if (call.isCanceled()){
            listener.onCancel();

        }else {
            listener.onFailure(call, e);
        }
    }     
//省略下面代码...

 

RequestBody创建

RequestBody是okhttp  post发送数据配置类.在这之前我们先了解下回顾一下body类型

 

http有四种body类型,Content-Type POST提交数据的方式:
  • application/x-www-form-urlencoded 表单数据
  • multipart/form-data 表单文件上传
  • application/json 序列化JSON数据
  • text/xml XML数据

这些body类型需要在http header头部就写上,但是okhttp不需要我们手动在header写上类型了.okhttp提供了FormBody和MultipartBody的类型,方便你的快速创建 application/x-www-form-urlencoded 与 multipart/form-data
FormBody 创建方式
/**
     * 此body是 默认application/x-www-form-urlencoded,你可以进入FormBody类查看,第一行静态常量就是这个
     */
   public void FormBody(){
       FormBody.Builder builder = new FormBody.Builder();
       builder.add("key","content");
       builder.build();
   }
MultipartBody 创建方式

 

/**
     * multipart/form-data
     */
   public void MultipartBody(){
       RequestBody requestBody = new RequestBody() {
           @Override
           public MediaType contentType() {
               return null;
           }

           @Override
           public void writeTo(BufferedSink sink) throws IOException {
               //上传流 sink.write()


           }
       };
       MultipartBody.Builder builder = new MultipartBody.Builder();
       builder.addFormDataPart("key","content");//表单数据
       builder.addFormDataPart("file_key","/path/image.jpg",requestBody);//文件数据
       MultipartBody multipartBody = builder.build();
   }
手动创建4种body

当然,有特殊需求你还可以添加手动其他body类型,create也支持好几种数据的上传形式

 /**
     * 手动创建4种body
     */
   public void RequestBody(){
       RequestBody applicationFormUrlencodedBody = RequestBody.create(MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"),new String("demo").getBytes());
       RequestBody multipartBody = RequestBody.create(MediaType.parse("multipart/form-data; charset=utf-8"),new File("/path/image.jpg"));
       RequestBody jsonBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"),"content");
       RequestBody textbody = RequestBody.create(MediaType.parse("text/xml; charset=utf-8"),"content");

   }

 

实现OkHttpClient客户端单例模式

public class OkHttpClientCreate {
    private static final boolean IS_RETRY = false;//失败是否重连
    private static final int CONNECT_TIME = 10;//设置连接超时时间 单位:秒
    private static final int READ_TIME = 10;//设置读取超时时间
    private static final int WRITE_TIME = 10;//设置写入超时间
    private static OkHttpClient mOkHttpClient;
    public static OkHttpClient CreateClient(){
        if (mOkHttpClient == null){
            return mOkHttpClient = new OkHttpClient.Builder()
                    .retryOnConnectionFailure(IS_RETRY)
                    .connectTimeout(CONNECT_TIME,TimeUnit.SECONDS)//连接超时
                    .readTimeout(READ_TIME,TimeUnit.SECONDS)//读取超时
                    .writeTimeout(WRITE_TIME,TimeUnit.SECONDS)//写入超时
//                    .callTimeout()//呼叫超时,设置此参数为整体流程请求的超时时间
//                    .addInterceptor() //设置拦截器
//                    .authenticator() //设置认证器
//                    .proxy()//设置代理
                    .build();
        }
        return mOkHttpClient;
    }

    public static void destroy(){
        mOkHttpClient = null;
    }
    
}

监听打印OkHttp请求头文件内容

使用okhttp网络日志拦截器需添加以下依赖:

implementation 'com.squareup.okhttp3:logging-interceptor:3.6.0'


定义拦截器中的网络日志工具:

 HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {

            @Override
            public void log(String message) {
                 Log.d("logInterceptor", message);
            }
        });
        logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);


初始化OkHttpClient,并添加网络日志拦截器:

mOkHttpClient = new OkHttpClient.Builder()
                    .addInterceptor(logInterceptor) //设置拦截器
                    .build();

文件下载功能实现(含断点续传)

package okhttpdemo.com.libs.net.httpBase;
import android.util.Log;
import org.json.JSONObject;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttpdemo.com.libs.net.httpBase.listener.HttpDownListener;
/**
 *@content: okhttp的下载功能工具类 (分别包含:1.无断点续传的get下载 2.有断点续传的get下载 3.无断点续传的post下载 4.有断点续传的post下载)
 *@time:2018-12-12
 *@build:z
 */

public class OkHttpDownUtil {
    private static final String TAG = "OkHttpDownUtil";
    private Call mCall;
    private long mAlreadyDownLength = 0;//已经下载长度
    private long mTotalLength = 0;//整体文件大小
    private int mSign = 0; //标记当前运行的是那个方法
    private String mDownUrl;//下载网络地址
    private File mPath;//文件保存路径
    private JSONObject mJson;
    private HttpDownListener mHttpDownListener;//下载进度接口回调


    /**
     * 没有断点续传功能的get请求下载
     * @param downUrl 下载网络地址
     * @param saveFilePathAndName 保存路径
     */
    public void getDownRequest(final String downUrl, final File saveFilePathAndName, final HttpDownListener listener) {
        synchronized (this) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mSign = 1;
                    mDownUrl = downUrl;
                    mPath = saveFilePathAndName;
                    mHttpDownListener = listener;
                    mAlreadyDownLength = 0;
                    Request request = new Request.Builder()
                            .url(mDownUrl)
                            .get()
                            .build();
                    mCall = OkHttpClientCreate.CreateClient().newCall(request);//构建了一个完整的http请求
                    mCall.enqueue(new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                            if (mHttpDownListener != null) {
                                mHttpDownListener.onFailure(call, e);
                            }

                        }

                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            ResponseBody responseBody = response.body();
                            mTotalLength = responseBody.contentLength();//下载文件的总长度
                            InputStream inp = responseBody.byteStream();
                            FileOutputStream fileOutputStream = new FileOutputStream(mPath);
                            try {
                                byte[] bytes = new byte[2048];
                                int len = 0;
                                while ((len = inp.read(bytes)) != -1) {
                                    mAlreadyDownLength = mAlreadyDownLength + len;
                                    fileOutputStream.write(bytes, 0, len);
                                    if (mHttpDownListener != null) {
                                        mHttpDownListener.onResponse(call, response, mTotalLength, mAlreadyDownLength);
                                    }

                                }
                            } catch (Exception e) {
                                Log.e(TAG, "Get下载异常");

                            } finally {
                                fileOutputStream.close();
                                inp.close();
                                Log.e(TAG, "流关闭");
                            }
                        }
                    });


                }
            }).start();
        }
    }

    /**
     * 有断点续传功能的get下载
     * @param downUrl 下载地址
     * @param saveFilePathAndName 保存路径
     * @param listener 进度监听
     */
    public void getRenewalDownRequest(final String downUrl, final File saveFilePathAndName, final HttpDownListener listener){
        synchronized (this) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mSign = 2;
                    mDownUrl = downUrl;
                    mPath = saveFilePathAndName;
                    mHttpDownListener = listener;
                    Request request = new Request.Builder()
                            .url(mDownUrl)
                            .header("RANGE", "bytes=" + mAlreadyDownLength + "-")
                            .build();
                    mCall = OkHttpClientCreate.CreateClient().newCall(request);//构建了一个完整的http请求
                    mCall.enqueue(new Callback() { //发送请求
                        @Override
                        public void onFailure(Call call, IOException e) {
                            if (mHttpDownListener != null) {
                                mHttpDownListener.onFailure(call, e);
                            }
                            Log.e(TAG, "onFailure: 异常报错=" + e.toString());

                        }

                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            ResponseBody responseBody = response.body();
                            InputStream inputStream = responseBody.byteStream();//得到输入流
                            RandomAccessFile randomAccessFile = new RandomAccessFile(mPath, "rw");//得到任意保存文件处理类实例
                            if (mTotalLength == 0){
                                mTotalLength = responseBody.contentLength();//得到文件的总字节大小
                                randomAccessFile.setLength(mTotalLength);//预设创建一个总字节的占位文件
                            }
                            if (mAlreadyDownLength != 0){
                                randomAccessFile.seek(mAlreadyDownLength);
                            }
                            byte[] bytes = new byte[2048];
                            int len = 0;
                            try {
                                while ((len = inputStream.read(bytes)) != -1) {
                                    randomAccessFile.write(bytes,0,len);
                                    mAlreadyDownLength = mAlreadyDownLength + len;
                                    if (mHttpDownListener != null) {
                                        mHttpDownListener.onResponse(call, response, mTotalLength, mAlreadyDownLength);
                                    }
                                }

                            } catch (Exception e) {
                                Log.e(TAG, "Get下载异常");

                            } finally {
                                mAlreadyDownLength = randomAccessFile.getFilePointer();//记录当前保存文件的位置
                                randomAccessFile.close();
                                inputStream.close();
                                Log.e(TAG, "流关闭 下载的位置="+mAlreadyDownLength);
                            }

                        }
                    });

                }
            }).start();
        }

    }

    /**
     * 没有断点续传的post下载
     * @param downUrl
     * @param saveFilePathAndName
     * @param json
     * @param listener
     */
    public void postDownRequest(final String downUrl, final File saveFilePathAndName, final JSONObject json,final HttpDownListener listener){
       synchronized (this){
           new Thread(new Runnable() {
               @Override
               public void run() {
                   mSign = 3;
                   mDownUrl = downUrl;
                   mPath = saveFilePathAndName;
                   mJson = json;
                   mHttpDownListener = listener;
                   mAlreadyDownLength = 0;
                   Request request = new Request.Builder()
                           .url(mDownUrl)
                           .post(changeJSON(json))
                           .build();
                   mCall = OkHttpClientCreate.CreateClient().newCall(request);
                   mCall.enqueue(new Callback() {
                       @Override
                       public void onFailure(Call call, IOException e) {
                           if (mHttpDownListener!=null){
                               mHttpDownListener.onFailure(call,e);
                           }
                       }

                       @Override
                       public void onResponse(Call call, Response response) throws IOException {

                           ResponseBody responseBody = response.body();
                           mTotalLength = responseBody.contentLength();
                           InputStream inputStream = responseBody.byteStream();
                           FileOutputStream fileOutputStream = new FileOutputStream(mPath);
                           byte[] bytes = new byte[2048];
                           int len = 0;
                           try {
                               while ((len = inputStream.read(bytes)) != -1) {
                                   fileOutputStream.write(bytes, 0, len);
                                   mAlreadyDownLength = mAlreadyDownLength + len;
                                   if (mHttpDownListener != null) {
                                       mHttpDownListener.onResponse(call, response, mTotalLength, mAlreadyDownLength);
                                   }
                               }
                           }catch (Exception e){
                               Log.e(TAG, "Post下载异常");
                           }finally {
                               fileOutputStream.close();
                               inputStream.close();
                               Log.e(TAG, "流关闭");

                           }

                       }

                   });
               }
           }).start();
       }


    }

    /**
     * 支持断点续传的post下载
     * @param downUrl 下载网址
     * @param saveFilePathAndName 文件保存路径
     * @param json 参数
     * @param listener 接口回调
     */
    public void postRenewalDownRequest(final String downUrl, final File saveFilePathAndName, final JSONObject json, final HttpDownListener listener){
        synchronized (this){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mSign = 4;
                    mDownUrl = downUrl;
                    mPath = saveFilePathAndName;
                    mJson = json;
                    mHttpDownListener = listener;
                    Request request = new Request.Builder()
                            .url(mDownUrl)
                            .header("RANGE","bytes="+mAlreadyDownLength+"-")
                            .post(changeJSON(json))
                            .build();
                    mCall = OkHttpClientCreate.CreateClient().newCall(request);
                    mCall.enqueue(new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                            if (mHttpDownListener != null){
                                mHttpDownListener.onFailure(call,e);
                            }
                        }

                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            ResponseBody responseBody = response.body();
                            InputStream inputStream = responseBody.byteStream();
                            RandomAccessFile randomAccessFile = new RandomAccessFile(mPath,"rw");
                            if (mTotalLength == 0){
                                mTotalLength = responseBody.contentLength();
                                randomAccessFile.setLength(mTotalLength);
                            }
                            if (mAlreadyDownLength!=0){
                                randomAccessFile.seek(mAlreadyDownLength);
                            }
                            byte[] bytes = new byte[2048];
                            int len = 0;
                            try {
                                while ((len = inputStream.read(bytes)) != -1) {
                                    randomAccessFile.write(bytes, 0, len);
                                    mAlreadyDownLength = mAlreadyDownLength + len;
                                    if (mHttpDownListener != null) {
                                        mHttpDownListener.onResponse(call, response, mTotalLength, mAlreadyDownLength);
                                    }

                                }
                            }catch (Exception e){
                                Log.e(TAG, "Post下载异常");

                            }finally {
                                mAlreadyDownLength = randomAccessFile.getFilePointer();
                                randomAccessFile.close();
                                inputStream.close();
                                Log.e(TAG, "流关闭 下载的位置="+mAlreadyDownLength);
                            }

                        }
                    });

                }
            }).start();
        }

    }

    /**
     * 恢复下载
     */
    public void resume(){
        if (mSign==0){
            return;
        }
        switch (mSign){
            case 1:
                getDownRequest(mDownUrl,mPath,mHttpDownListener);
                break;
            case 2:
                getRenewalDownRequest(mDownUrl,mPath,mHttpDownListener);
                break;
            case 3:
                postDownRequest(mDownUrl,mPath,mJson,mHttpDownListener);
                break;
            case 4:
                postRenewalDownRequest(mDownUrl,mPath,mJson,mHttpDownListener);
                break;
            default:
                break;
        }

    }

    /**
     * 暂停下载
     */
    public void stop(){
        if (mCall!=null){
            mCall.cancel();
        }

    }

    /**
     * 删除下载文件
     */
    public void deleteCurrentFile(){
        if (mPath == null){
            Log.e(TAG, "deleteCurrentFile error : 没有路径");
            return;
        }
        if (!mPath.exists()){
            Log.e(TAG, "deleteCurrentFile error: 文件不存在");
            return;
        }
        mPath.delete();
        mAlreadyDownLength = 0;
        mTotalLength = 0;
        mSign = 0;
    }

    /**
     * 销毁
     */
    public void destroy(){
        if (mCall!=null){
            mCall.cancel();
            mCall = null;
        }
        mSign = 0;
        mDownUrl = null;
        mPath = null;
        mHttpDownListener = null;
        mAlreadyDownLength = 0;
        mTotalLength = 0;
    }

    /**
     * 转换Json参数为RequestBody
     * @param jsonParam json对象
     * @return RequestBody
     */
    private RequestBody changeJSON(JSONObject jsonParam){
        RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8")
                , String.valueOf(jsonParam));
        return requestBody;
    }

}

文件上传功能实现(含断点续传)

package okhttpdemo.com.libs.net.httpBase;

import android.util.Log;

import org.json.JSONObject;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.Map;
import java.util.Set;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttpdemo.com.libs.net.httpBase.listener.HttpUpListener;
import okio.BufferedSink;

public class OkHttpUpUtil {
    private static final String TAG = "OkHttpUpUtil";
    private String mUpUrl;
    private File mPath;
    private Call mCall;
    private Map<String,String> mParams;
    private long mAlreadyUpLength = 0;//已经上传长度
    private long mTotalLength = 0;//整体文件大小
    private int mSign = 0;
    private HttpUpListener mHttpUpListener;

    /**
     * post上传
     * @param upUrl
     * @param upFilePathAndName
     * @param params
     * @param listener
     */
    public void postUpRequest(final String upUrl, final File upFilePathAndName, final Map<String,String> params, final HttpUpListener listener){
        synchronized (this) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mSign = 1;
                    mUpUrl = upUrl;
                    mPath = upFilePathAndName;
                    mParams = params;
                    mHttpUpListener = listener;
                    mAlreadyUpLength = 0;
                    RequestBody requestBody = new RequestBody() {
                        @Override
                        public MediaType contentType() {
                            return null;
                        }

                        @Override
                        public void writeTo(BufferedSink sink) throws IOException {
                            RandomAccessFile randomAccessFile = new RandomAccessFile(mPath, "rw");
                            if (mTotalLength == 0) {
                                mTotalLength = randomAccessFile.length();
                            }
                            byte[] bytes = new byte[2048];
                            int len = 0;
                            try {
                                while ((len = randomAccessFile.read(bytes)) != -1) {
                                    sink.write(bytes, 0, len);
                                    mAlreadyUpLength = mAlreadyUpLength + len;
                                    if (mHttpUpListener != null) {
                                        mHttpUpListener.onUpFile(mTotalLength, mAlreadyUpLength);
                                    }
                                }
                            }catch (Exception e){
                                Log.e(TAG, "上传中断");
                            }finally {
                                randomAccessFile.close();//关闭流
                                Log.e(TAG, "流关闭");
                            }

                        }
                    };
//                MultipartBody multipartBody = new MultipartBody.Builder()
//                        .addPart(changeJSON(mJson))
//                        .addFormDataPart("file",mPath.getName(),requestBody)
//                        .build();
                    MultipartBody.Builder builder = new MultipartBody.Builder();
                    if (mParams!=null) {
                        Set<String> keys = mParams.keySet();
                        for (String key : keys) {
                            builder.addFormDataPart(key, mParams.get(key));
                        }
                    }
                    builder.addFormDataPart("file", mPath.getName(), requestBody);
                    MultipartBody multipartBody = builder.build();

                    Request request = new Request.Builder()
                            .url(mUpUrl)
                            .post(multipartBody)
                            .build();
                    mCall = OkHttpClientCreate.CreateClient().newCall(request);
                    mCall.enqueue(new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                            if (mHttpUpListener != null) {
                                mHttpUpListener.onFailure(call, e);
                            }
                        }

                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            if (mHttpUpListener != null) {
                                mHttpUpListener.onResponse(call, response);
                            }

                        }
                    });

                }
            }).start();
        }

    }

    /**
     * post断点上传
     * @param upUrl
     * @param upFilePathAndName
     * @param params
     * @param listener
     */
    public void postRenewalUpRequest(final String upUrl, final File upFilePathAndName, final Map<String,String> params, final HttpUpListener listener){
        synchronized (this){
            new Thread(new Runnable() {
                @Override
                public void run() {
                    mSign = 2;
                    mUpUrl = upUrl;
                    mPath = upFilePathAndName;
                    mParams = params;
                    mHttpUpListener = listener;
                    RequestBody requestBody = new RequestBody() {
                        @Override
                        public MediaType contentType() {
                            return null;
                        }

                        @Override
                        public void writeTo(BufferedSink sink) throws IOException {
                            RandomAccessFile randomAccessFile = new RandomAccessFile(mPath, "rw");
                            if (mTotalLength == 0) {
                                mTotalLength = randomAccessFile.length();
                            }
                            if (mAlreadyUpLength != 0){
                                randomAccessFile.seek(mAlreadyUpLength);
                            }
                            byte[] bytes = new byte[2048];
                            int len = 0;
                            try {
                                while ((len = randomAccessFile.read(bytes)) != -1) {
                                    sink.write(bytes, 0, len);
                                    mAlreadyUpLength = mAlreadyUpLength + len;
                                    if (mHttpUpListener != null) {
                                        mHttpUpListener.onUpFile(mTotalLength, mAlreadyUpLength);
                                    }
                                }
                            }catch (Exception e){
                                Log.e(TAG, "上传中断");
                            }finally {
                                mAlreadyUpLength = randomAccessFile.getFilePointer();
                                randomAccessFile.close();//关闭流
                                Log.e(TAG, "流关闭");
                            }

                        }
                    };

                    MultipartBody.Builder builder = new MultipartBody.Builder();
                    if (mParams!=null) {
                        Set<String> keys = mParams.keySet();
                        for (String key : keys) {
                            builder.addFormDataPart(key, mParams.get(key));
                        }
                    }
                    builder.addFormDataPart("file", mPath.getName(), requestBody);
                    MultipartBody multipartBody = builder.build();

                    Request request = new Request.Builder()
                            .url(mUpUrl)
                            .header("RANGE","bytes="+mAlreadyUpLength+"-"+mTotalLength)
                            .post(multipartBody)
                            .build();
                    mCall = OkHttpClientCreate.CreateClient().newCall(request);
                    mCall.enqueue(new Callback() {
                        @Override
                        public void onFailure(Call call, IOException e) {
                            if (mHttpUpListener != null) {
                                mHttpUpListener.onFailure(call, e);
                            }
                        }

                        @Override
                        public void onResponse(Call call, Response response) throws IOException {
                            if (mHttpUpListener != null) {
                                mHttpUpListener.onResponse(call, response);
                            }
                            mAlreadyUpLength = 0;
                            mTotalLength = 0;

                        }
                    });

                }
            }).start();
        }


    }

    /**
     * 恢复上传
     */
    public void resume(){
        if (mSign==0){
            return;
        }
        switch (mSign){
            case 1:
                postUpRequest(mUpUrl,mPath,mParams,mHttpUpListener);
                break;
            case 2:
                postRenewalUpRequest(mUpUrl,mPath,mParams,mHttpUpListener);
                break;
            case 3:

                break;
            case 4:

                break;
            default:
                break;
        }

    }

    /**
     * 暂停上传
     */
    public void stop(){
        if (mCall!=null){
            mCall.cancel();
        }

    }

    /**
     * 删除上传路径文件
     */
    public void deleteCurrentFile(){
        if (mPath == null){
            Log.e(TAG, "deleteCurrentFile error : 没有路径");
            return;
        }
        if (!mPath.exists()){
            Log.e(TAG, "deleteCurrentFile error: 文件不存在");
            return;
        }
        mPath.delete();
        mAlreadyUpLength = 0;
        mTotalLength = 0;
        mSign = 0;
    }

    /**
     * 销毁
     */
    public void destroy(){
        if (mCall!=null){
            mCall.cancel();
            mCall = null;
        }
        mSign = 0;
        mHttpUpListener = null;
        mPath = null;
        mHttpUpListener = null;
        mAlreadyUpLength = 0;
        mTotalLength = 0;
    }

    /**
     * 转换Json参数为RequestBody
     * @param jsonParam json对象
     * @return RequestBody
     */
    private RequestBody changeJSON(JSONObject jsonParam){
        RequestBody requestBody = FormBody.create(MediaType.parse("application/json; charset=utf-8")
                , String.valueOf(jsonParam));
        return requestBody;
    }





}

 

posted on 2018-08-31 21:45  观心静 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/guanxinjing/p/9708575.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值