Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> OkHttp學習(3)--))同步、異步之上傳文件至服務器(重寫RequestBody方法,實現上傳進度接口回調)

OkHttp學習(3)--))同步、異步之上傳文件至服務器(重寫RequestBody方法,實現上傳進度接口回調)

編輯:關於Android編程

此篇博客,我們通過2種方式來了解下okhttp的文件上傳至服務器

ps一下,還有一種就是添加params參數,生成post提交時的分塊request(這裡就不列出實例效果了,但是封裝代碼博文後附加)

同步上傳
異步上傳
還有一種就是添加params參數,生成post提交時的分塊request

在說明同步、異步上傳代碼前,我們先來了解下上傳圖片文件的大概思路:
我這裡貼出一個截圖,就很簡單明了了,截圖如下:
這裡寫圖片描述
截圖的意思就是將圖片壓縮成byte[]字節數組,然後通過Base64.encodeToString(bitmap2Bytes, Base64.DEFAULT)將字節數組,轉為64位的字符串,然後在封裝請求體,傳給服務器即可

了解完上傳圖片文件的大概思路後, 我們來看下我們代碼是如何實現的?
我公司請求是用的https,我這個例子,就沒有去https認證證書,我就直接https 不驗證證書方式(信任所有證書)
在SaflyApplication中進行如下代碼設置:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwcmUgY2xhc3M9"brush:java;"> public static OkHttpClient getUnsafeOkHttpClient() { try { final TrustManager[] trustAllCerts = new TrustManager[]{ new X509TrustManager() { @Override public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) { } @Override public java.security.cert.X509Certificate[] getAcceptedIssuers() { return new java.security.cert.X509Certificate[]{}; } } }; final SSLContext sslContext = SSLContext.getInstance("SSL"); sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); final javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory(); OkHttpClient.Builder builder = new OkHttpClient.Builder(); builder.sslSocketFactory(sslSocketFactory); builder.hostnameVerifier(new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { return true; } }); OkHttpClient okHttpClient = builder.connectTimeout(60, TimeUnit.SECONDS).writeTimeout(60, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).build(); return okHttpClient; } catch (Exception e) { throw new RuntimeException(e); } }

樓上的代碼,也是我找的度娘搜索的,下面這段代碼就初始化了一個OkHttpClient對象,設置了連接時間,讀取時間等信息

 OkHttpClient okHttpClient = builder.connectTimeout(60, TimeUnit.SECONDS).writeTimeout(60, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).build();

我們在OkHttpManger進行

 private Handler okHttpHandler;
    private OkHttpClient mOkHttpClient;
    private OkHttpManger(){
        this.mOkHttpClient = SaflyApplication.getInstance().getUnsafeOkHttpClient();
        this.okHttpHandler = new Handler(Looper.getMainLooper());
    }

    public static final OkHttpManger getInstance(){
        return SingleFactory.manger;
    }
    private static final class SingleFactory{
        private static final OkHttpManger manger = new OkHttpManger();
    }

構造一個單利模式,然後為了線程之間通訊,我們還初始化了一個handler,用來進行ui線程的頁面更新操作

我們先來看看同步上傳頭像代碼

Response response =  OkHttpManger.getInstance().postSyncJson("https://10.0.5.48:7771/SetVPHUserInfo", Json);
public Response postSyncJson(String url, String json) throws IOException {
        final RequestBody requestBody = RequestBody.create(JSON_TYPE, json);
        final Request request = new Request.Builder().url(url).post(requestBody).build();
        return mOkHttpClient.newCall(request).execute();
    }

本例中我構造json字符串是用的JSONObject的方式,
如果對如何構建Json字符串還不是很明白的,可以看我如下的博客文章:

fastjson–Gson生成Json字符串,並且解析Json字符串生成對象

JsonObject生成Json字符串,並且解析為對象—–JsonReader解析Json字符串
另外還有一種方式,就是自定義拼接的方式(我公司就是用的這樣的方法,這裡就不贅述了)

針對本例的上傳服務端的json格式,我們用JSONObject如下方法即可生成所需要的json字符串

  private String createJson() throws JSONException {
        JSONObject jsonObject = new JSONObject();

        JSONObject body = new JSONObject();
        body.put("photo_type", "jpeg");
        body.put("nickname", "hehe");
        body.put("context", Base64.encodeToString(bitmap2Bytes, Base64.DEFAULT));

        JSONObject head = new JSONObject();
        head.put("godin_id", "0e6ad2a71e31752deb69d6e8c9eabe76");
        head.put("app_type", "3");
        head.put("os_type", "android");

        JSONObject Request = new JSONObject();
        Request.put("body", body);
        Request.put("head", head);

        jsonObject.put("Request", Request);
        return jsonObject.toString();
    }

然後在response.isSuccessful()進行判斷返回結果就可以了
這裡寫圖片描述

由於我是直接訪問的公司上傳頭像的接口,godin_id字段是寫死的,服務端沒有注冊的記錄,所以就返回auth error的錯誤,不過我問了服務端的同事,已經收到該請求,通訊成功

我們在來看看異步上傳頭像代碼

 OkHttpManger.getInstance().postAsyncJsonn("https://10.0.5.48:7771/SetVPHUserInfo", Json, new OkHttpManger.MyCallback()
   public void postAsyncJsonn(String url, String json, MyCallback mCallback) throws IOException {
        final RequestBody requestBody = RequestBody.create(JSON_TYPE, json);
        final Request request = new Request.Builder().url(url).post(requestBody).build();
        deliveryResult(mOkHttpClient.newCall(request),mCallback);
    }

然後進行接口回調

private void deliveryResult(final Call call, final MyCallback mCallback) {
        call.enqueue(new Callback() {
            @Override
            public void onFailure(final Call call, final IOException e) {
                okHttpHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (mCallback != null) {
                            mCallback.onFailture();
                        }
                    }
                });

            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                final String responseStr = response.body().string();

                okHttpHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (mCallback != null) {
                            mCallback.onSuccess(responseStr);
                        }
                    }
                });

            }
        });
    }

然後截圖是一樣的,也是可以通訊成功的。

以上就是同步、異步2種方式,上傳頭像至服務器

接下來我們看看另外一個方式,不過這個方法我沒有去實踐代碼,不過有代碼封裝,以下就是代碼

/**
     * 同步基於post的文件上傳
     * @param url 地址
     * @param files 提交的文件數組
     * @param fileKeys 提交的文件數組key
     * @param params 提交的鍵值對
     * @return Response
     */
    public Response uploadSync(String url, File[] files, String[] fileKeys, Param[] params) throws IOException {
        final RequestBody requestBody = buildMultipartFormRequestBody(files, fileKeys, params);
        final Request request = new Request.Builder().url(url).post(requestBody).build();
        return mOkHttpClient.newCall(request).execute();
    }

    /**
     * 異步基於post的文件上傳,回傳上傳進度
     * @param url 地址
     * @param files 提交的文件數組
     * @param fileKeys 提交的文件數組key
     * @param params 提交的鍵值對
     */
    public void uploadAsync(String url, File[] files, String[] fileKeys,
                            final OKHttpUICallback.ProgressCallback uploadListener, Param[] params) throws IOException {
        final RequestBody requestBody = buildMultipartFormRequestBody(files, fileKeys, params);
        final Request request = new Request.Builder().url(url).post(new ProgressBody.ProgressRequestBody(requestBody, uploadListener, okHttpHandler)).build();
        mOkHttpClient.newCall(request).enqueue(new OKHttpThreadCallback(okHttpHandler, uploadListener, false));
    }


生成post提交時的分塊request

    private RequestBody buildMultipartFormRequestBody(File[] files, String[] fileKeys, Param[] params){
        if(params == null){
            params = new Param[0];
        }
        MultipartBody.Builder builder = new MultipartBody.Builder();
        for(Param param:params){
            builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + param.key + "\""),
                    RequestBody.create(null, param.value));
        }
        if(files == null){
            files = new File[0];
        }
        if(fileKeys == null){
            fileKeys = new String[0];
        }

        if(fileKeys.length != files.length){
            throw new ArrayStoreException("fileKeys.length != files.length");
        }
        RequestBody fileBody = null;
        int length = files.length;
        for(int i = 0;i

我們重點來看看ProgressBody.ProgressRequestBody的代碼 Okio中有兩個關鍵的接口,Sink和Source,這兩個接口都繼承了Closeable接口;而Sink可以簡單的看做OutputStream,Source可以簡單的看做InputStream。而這兩個接口都是支持讀寫超時設置的。 它們各自有一個支持緩沖區的子類接口,BufferedSink和BufferedSource,而BufferedSink有一個實現類RealBufferedSink,BufferedSource有一個實現類RealBufferedSource

if(bufferedSink == null){
                //開始包裝
                bufferedSink = Okio.buffer(sink(sink));
            }
            //寫入
            requestBody.writeTo(bufferedSink);
            bufferedSink.flush();

然後在發布進度

        private Sink sink(Sink sink){
            return new ForwardingSink(sink) {
                //當前寫入字節數
                long byteWriteed = 0L;
                //總得字節數
                long contentBytes = 0L;
                @Override
                public void write(Buffer source, long byteCount) throws IOException {
                    super.write(source, byteCount);
                    if(mHandler != null && mListener != null){
                        if(contentBytes == 0L){
                            contentBytes = contentLength();
                        }
                        byteWriteed += byteCount;
                        mListener.onProgress(byteWriteed, contentBytes, byteWriteed == contentBytes);
                    }
                }
            };

然後在

 mOkHttpClient.newCall(request).enqueue(new OKHttpThreadCallback(okHttpHandler, uploadListener, false));

在成功回調的接口中,進行如下操作

@Override
    public void onResponse(Call call, Response response) throws IOException {
        if(isDownload){
            download(call,response);
        }else{
            postSuccess(call,response);
        }
    }
private void postSuccess(final Call call, final Response response){
        if(UICallback != null && UIHandler != null){
            UIHandler.post(new Runnable() {
                @Override
                public void run() {
                    UICallback.onSuccess(call, response,downFile == null?null:downFile.getAbsolutePath());
                }
            });
        }
    }

然後在主界面在進行接口回調,去實現其他一些操作

///////////////以下是代碼////////////////////以下是代碼/////////////////以下是代碼/////////////////////

MainActivity

package com.example.administrator.myapplication;

import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;


import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.IOException;

import okhttp3.Response;

public class MainActivity extends Activity implements View.OnClickListener {


    Button uploadSync,uploadAsync;
    private String responseStr;
    private byte[] bitmap2Bytes;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        uploadSync = (Button) findViewById(R.id.uploadSync);
        uploadAsync = (Button) findViewById(R.id.uploadAsync);
        uploadSync.setOnClickListener(this);
        uploadAsync.setOnClickListener(this);

        Resources res = getResources();
        Bitmap bmp = BitmapFactory.decodeResource(res, R.mipmap.ic_launcher);
        bitmap2Bytes = Bitmap2Bytes(bmp);

    }


    public byte[] Bitmap2Bytes(Bitmap bm) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.PNG, 100, baos);
        return baos.toByteArray();
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.uploadSync:
                try {
                    Json = createJson();
                    Log.i("MainActivity","postSyncByParams2 Json:"+Json);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
                new Thread() {
                    @Override
                    public void run() {
                        try {
                            Response response =  OkHttpManger.getInstance().postSyncJson("https://10.0.5.48:7771/SetVPHUserInfo", Json);
                            if (response.isSuccessful()){
                                responseStr = response.body().string();
                                Log.i("MainActivity","postSyncByParams2:"+responseStr);
                            }else{
                                Log.i("MainActivity","postSyncByParams2 error");
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }.start();

                break;
            case R.id.uploadAsync:
                try {
                    Json = createJson();
                    Log.i("MainActivity","postSyncByParams2 Json:"+Json);
                } catch (JSONException e) {
                    e.printStackTrace();
                }

                try {
                    OkHttpManger.getInstance().postAsyncJsonn("https://10.0.5.48:7771/SetVPHUserInfo", Json, new OkHttpManger.MyCallback() {

                        @Override
                        public void onSuccess(String result) {
                            Log.i("MainActivity","result----"+result);
                        }

                        @Override
                        public void onFailture() {

                        }
                    });
                } catch (IOException e) {
                    e.printStackTrace();
                }


                break;

        }

    }


    String Json = null;
    private String createJson() throws JSONException {
        JSONObject jsonObject = new JSONObject();

        JSONObject body = new JSONObject();
        body.put("photo_type", "jpeg");
        body.put("nickname", "hehe");
        body.put("context", Base64.encodeToString(bitmap2Bytes, Base64.DEFAULT));

        JSONObject head = new JSONObject();
        head.put("godin_id", "0e6ad2a71e31752deb69d6e8c9eabe76");
        head.put("app_type", "3");
        head.put("os_type", "android");


        JSONObject Request = new JSONObject();
        Request.put("body", body);
        Request.put("head", head);

        jsonObject.put("Request", Request);
        return jsonObject.toString();
    }
}

SaflyApplication

package com.example.administrator.myapplication;

import android.app.Application;


import java.util.concurrent.TimeUnit;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import okhttp3.OkHttpClient;

public class SaflyApplication extends Application {
    private static SaflyApplication instance;

    @Override
    public void onCreate() {
        super.onCreate();
        this.instance = this;
    }

    public static SaflyApplication getInstance() {

        return instance;
    }

    public static OkHttpClient getUnsafeOkHttpClient() {
        try {
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                        }

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                        }

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new java.security.cert.X509Certificate[]{};
                        }
                    }
            };

            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            final javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslSocketFactory);
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });

            OkHttpClient okHttpClient = builder.connectTimeout(60, TimeUnit.SECONDS).writeTimeout(60, TimeUnit.SECONDS).readTimeout(60, TimeUnit.SECONDS).build();
            return okHttpClient;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

OkHttpManger

package com.example.administrator.myapplication;

import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import com.alibaba.fastjson.JSON;

import java.io.File;
import java.io.IOException;
import java.net.FileNameMap;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * OkHttp 工具類,
 * get的同步異步請求
 * post的json字符串同步異步上傳
 * post的鍵值對同步異步上傳
 * post文件異步上傳,回調結果以及進度
 * 異步下載文件,回調結果以及進度
 *
 * Created by Seeker on 2016/6/24.
 */
public final class OkHttpManger {

    private static final String TAG = "OkHttpManger";

    private static final MediaType JSON_TYPE = MediaType.parse("application/json; charset=utf-8");

    private Handler okHttpHandler;
    private OkHttpClient mOkHttpClient;
    private OkHttpManger(){
        this.mOkHttpClient = SaflyApplication.getInstance().getUnsafeOkHttpClient();
        this.okHttpHandler = new Handler(Looper.getMainLooper());
    }

    public static final OkHttpManger getInstance(){
        return SingleFactory.manger;
    }
    private static final class SingleFactory{
        private static final OkHttpManger manger = new OkHttpManger();
    }
    /////////////////////////同步異步上傳頭像//////////////////////////////

    interface MyCallback{
        void onSuccess(String result);
        void onFailture();
    }

    public Response postSyncJson(String url, String json) throws IOException {
        final RequestBody requestBody = RequestBody.create(JSON_TYPE, json);
        final Request request = new Request.Builder().url(url).post(requestBody).build();
        return mOkHttpClient.newCall(request).execute();
    }
    public void postAsyncJsonn(String url, String json, MyCallback mCallback) throws IOException {
        final RequestBody requestBody = RequestBody.create(JSON_TYPE, json);
        final Request request = new Request.Builder().url(url).post(requestBody).build();
        deliveryResult(mOkHttpClient.newCall(request),mCallback);
    }

    private void deliveryResult(final Call call, final MyCallback mCallback) {
        call.enqueue(new Callback() {
            @Override
            public void onFailure(final Call call, final IOException e) {
                okHttpHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (mCallback != null) {
                            mCallback.onFailture();
                        }
                    }
                });

            }

            @Override
            public void onResponse(Call call, final Response response) throws IOException {
                final String responseStr = response.body().string();

                okHttpHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (mCallback != null) {
                            mCallback.onSuccess(responseStr);
                        }
                    }
                });

            }
        });
    }
    ////////////////////////同步異步上傳頭像//////////////////////////////


    /**
     * 同步基於post的文件上傳
     * @param url 地址
     * @param file 提交的文件
     * @param fileKey 提交的文件key
     * @return Response
     */
    public Response uploadSync(String url, File file, String fileKey) throws IOException {
        return uploadSync(url, new File[]{file}, new String[]{fileKey}, new Param[0]);
    }

    /**
     * 同步基於post的文件上傳
     * @param url 地址
     * @param files 提交的文件數組
     * @param fileKeys 提交的文件數組key
     * @param params 提交的鍵值對
     * @return Response
     */
    public Response uploadSync(String url, File[] files, String[] fileKeys, Param[] params) throws IOException {
        final RequestBody requestBody = buildMultipartFormRequestBody(files, fileKeys, params);
        final Request request = new Request.Builder().url(url).post(requestBody).build();
        return mOkHttpClient.newCall(request).execute();
    }


    /**
     * 異步基於post的文件上傳,回傳上傳進度
     * @param url 地址
     * @param file 提交的文件
     * @param fileKey 提交的文件key
     */
    public void uploadAsync(String url, File file, String fileKey, OKHttpUICallback.ProgressCallback listener)
            throws IOException {
        uploadAsync(url, new File[]{file}, new String[]{fileKey}, listener, new Param[0]);
    }

    /**
     * 異步基於post的文件上傳,回傳上傳進度
     * @param url 地址
     * @param files 提交的文件數組
     * @param fileKeys 提交的文件數組key
     * @param params 提交的鍵值對
     */
    public void uploadAsync(String url, File[] files, String[] fileKeys,
                            final OKHttpUICallback.ProgressCallback uploadListener, Param[] params) throws IOException {
        final RequestBody requestBody = buildMultipartFormRequestBody(files, fileKeys, params);
        final Request request = new Request.Builder().url(url).post(new ProgressBody.ProgressRequestBody(requestBody, uploadListener, okHttpHandler)).build();
        mOkHttpClient.newCall(request).enqueue(new OKHttpThreadCallback(okHttpHandler, uploadListener, false));
    }



    /**
     * 生成post提交時的分塊request
     * @param files
     * @param fileKeys
     * @param params
     * @return
     */
    private RequestBody buildMultipartFormRequestBody(File[] files, String[] fileKeys, Param[] params){
        if(params == null){
            params = new Param[0];
        }
        MultipartBody.Builder builder = new MultipartBody.Builder();
        for(Param param:params){
            builder.addPart(Headers.of("Content-Disposition", "form-data; name=\"" + param.key + "\""),
                    RequestBody.create(null, param.value));
        }
        if(files == null){
            files = new File[0];
        }
        if(fileKeys == null){
            fileKeys = new String[0];
        }

        if(fileKeys.length != files.length){
            throw new ArrayStoreException("fileKeys.length != files.length");
        }
        RequestBody fileBody = null;
        int length = files.length;
        for(int i = 0;i<length;i++){ contenttype="" file="" filebody="RequestBody.create(MediaType.parse(guessMimeType(fileName)),file);" filename="file.getName();" filenamemap="" final="" name="\" pre="" private="" public="" return="" static="" string="" this.key="key;" this.value="value;" todo="" type="=">

ProgressBody 上傳的進度接口

package com.example.administrator.myapplication;

import android.os.Handler;
import java.io.IOException;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import okio.Buffer;
import okio.BufferedSink;
import okio.BufferedSource;
import okio.ForwardingSink;
import okio.ForwardingSource;
import okio.Okio;
import okio.Sink;
import okio.Source;

/**
 * Created by Seeker on 2016/7/27.
 */
public final class ProgressBody {

    /**
     * 包裝響應體,用於處理提示上傳進度
     *
     * Created by Seeker on 2016/6/29.
     */
    public static final class ProgressRequestBody extends RequestBody {

        //實際待包裝的請求體
        private final RequestBody requestBody;

        //上傳進度回調接口
        private OKHttpUICallback.ProgressCallback mListener;

        //包裝完成的BufferedSink
        private BufferedSink bufferedSink;

        //傳遞下載進度到主線程
        private Handler mHandler;

        public ProgressRequestBody(RequestBody requestBody, OKHttpUICallback.ProgressCallback listener, Handler handler){
            this.requestBody = requestBody;
            this.mListener = listener;
            this.mHandler = handler;
        }

        @Override
        public long contentLength() throws IOException {
            return requestBody.contentLength();
        }

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

        @Override
        public void writeTo(BufferedSink sink) throws IOException {
            if(bufferedSink == null){
                //開始包裝
                bufferedSink = Okio.buffer(sink(sink));
            }
            //寫入
            requestBody.writeTo(bufferedSink);
            bufferedSink.flush();
        }

        /**
         * 寫入,回調進度接口
         */

        private Sink sink(Sink sink){
            return new ForwardingSink(sink) {
                //當前寫入字節數
                long byteWriteed = 0L;
                //總得字節數
                long contentBytes = 0L;
                @Override
                public void write(Buffer source, long byteCount) throws IOException {
                    super.write(source, byteCount);
                    if(mHandler != null && mListener != null){
                        if(contentBytes == 0L){
                            contentBytes = contentLength();
                        }
                        byteWriteed += byteCount;
                        mListener.onProgress(byteWriteed, contentBytes, byteWriteed == contentBytes);
                    }
                }
            };
        }
    }
}

OKHttpThreadCallback上傳完畢後的接口方法

package com.example.administrator.myapplication;

import android.os.Handler;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;

public final class OKHttpThreadCallback implements Callback {

    private Handler UIHandler;

    private OKHttpUICallback.ProgressCallback UICallback;

    private boolean isDownload;

    private File downFile;

    public OKHttpThreadCallback(Handler handler, OKHttpUICallback.ProgressCallback callback, boolean isDownload){
        this.UIHandler = handler;
        this.UICallback = callback;
        this.isDownload = isDownload;
    }

    @Override
    public void onFailure(final Call call, final IOException e) {
        if(UICallback != null && UIHandler != null){
            UIHandler.post(new Runnable() {
                @Override
                public void run() {
                    UICallback.onError(call,e);
                }
            });
        }
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        if(isDownload){
            download(call,response);
        }else{
            postSuccess(call,response);
        }
    }

    /**
     * 設置保存file
     * @param file
     */
    public OKHttpThreadCallback setFile(File file){
        this.downFile = file;
        return this;
    }

    /**
     * 獲取下載數據並寫入文件
     * @param response
     */
    private void download(Call call, Response response) throws IOException {
        if(downFile == null){
            throw new NullPointerException("downFile == null");
        }
        byte[] buffer = new byte[2048];
        InputStream is = response.body().byteStream();
        int len;
        FileOutputStream fos = new FileOutputStream(downFile);
        while ((len = is.read(buffer)) != -1){
            fos.write(buffer,0,len);
        }
        fos.flush();
        if(is != null){
            is.close();
        }
        if (fos != null){
            fos.close();
        }
        postSuccess(call,null);
    }

    /**
     * 回調成功信息
     * @param call
     * @param response
     */
    private void postSuccess(final Call call, final Response response){
        if(UICallback != null && UIHandler != null){
            UIHandler.post(new Runnable() {
                @Override
                public void run() {
                    UICallback.onSuccess(call, response,downFile == null?null:downFile.getAbsolutePath());
                }
            });
        }
    }
}

OKHttpUICallback成功後需要實現的接口定義類

package com.example.administrator.myapplication;

import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import okhttp3.Call;
import okhttp3.Response;

/**
 * Created by safly on 2016/9/1.
 *
 * 回調主線程的接口
 */
public class OKHttpUICallback {

    /**
     * 異步回調接口
     */

    /**
     * 帶有進度的上傳、下載回調接口
     */
    public interface ProgressCallback{
        void onSuccess(Call call, Response response, String path);
        void onProgress(long byteReadOrWrite, long contentLength, boolean done);
        void onError(Call call, IOException e);
    }
}
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved