1. 程式人生 > >get post 封裝公共引數工具類

get post 封裝公共引數工具類

package com.dash.a02_okhttp3_02;

import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Cache;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * Created by Dash on 2017/12/8.
 *
 * 公共引數封裝分為兩種方式....source=android,,,appVersion=100
 *      一:封裝到doGet和doPost方法中
 *
 *
 *      二:封裝到攔截器(interceptor):攔截一個請求,然後新增引數進去
 */
public class OkHttp3Util_02 {


    /**
     * 懶漢 安全 加同步
     * 1.私有的靜態成員變數 只宣告不建立
     * 2.私有的構造方法
     * 3.提供返回例項的靜態方法
     */
    private static OkHttpClient okHttpClient = null;


    private OkHttp3Util_02() {
    }

    public static OkHttpClient getInstance() {

        if (okHttpClient == null) {
            //加同步安全
            synchronized (OkHttp3Util_02.class) {
                if (okHttpClient == null) {
                    //okhttp可以快取資料....指定快取路徑
                    File sdcache = new File(Environment.getExternalStorageDirectory(), "cache");
                    //指定快取大小
                    int cacheSize = 10 * 1024 * 1024;

                    okHttpClient = new OkHttpClient.Builder()//構建器
                            .connectTimeout(15, TimeUnit.SECONDS)//連線超時
                            .writeTimeout(20, TimeUnit.SECONDS)//寫入超時
                            .readTimeout(20, TimeUnit.SECONDS)//讀取超時


                            .cache(new Cache(sdcache.getAbsoluteFile(), cacheSize))//設定快取
                            .build();
                }
            }

        }

        return okHttpClient;
    }

    /**
     * get請求
     * 引數1 url
     * 引數2 回撥Callback
     *
     * oldUrl表示老的地址,,,是沒封裝公共引數之前的地址....公共引數指的是source=android
     *
     * // 1.http://www.baoidu.com/login                --------? key=value&key=value
     // 2.http://www.baoidu.com/login?               --------- key=value&key=value
     // 3.http://www.baoidu.com/login?mobile=11111    -----&key=value&key=value
     */

    public static void doGet(String oldUrl, Callback callback) {

        //要新增的公共引數...map
        Map<String,String> map = new HashMap<>();
        map.put("source","android");


        StringBuilder stringBuilder = new StringBuilder();//建立一個stringBuilder...字串緩衝區

        stringBuilder.append(oldUrl);

        if (oldUrl.contains("?")){
            //?在最後面....2型別
            if (oldUrl.indexOf("?") == oldUrl.length()-1){

            }else {
                //3型別...拼接上&
                stringBuilder.append("&");
            }
        }else {
            //不包含? 屬於1型別,,,先拼接上?號
            stringBuilder.append("?");
        }

        //新增公共引數....source=android&appVersion=100&
        for (Map.Entry<String,String> entry: map.entrySet()) {
            //拼接
            stringBuilder.append(entry.getKey())
                    .append("=")
                    .append(entry.getValue())
                    .append("&");
        }

        //刪掉最後一個&符號
        if (stringBuilder.indexOf("&") != -1){
            stringBuilder.deleteCharAt(stringBuilder.lastIndexOf("&"));
        }
        //得到含有公共引數的新路徑.....使用新路徑去請求
        String newUrl = stringBuilder.toString();

        //建立OkHttpClient請求物件
        OkHttpClient okHttpClient = getInstance();
        //建立Request
        Request request = new Request.Builder().url(newUrl).build();
        //得到Call物件
        Call call = okHttpClient.newCall(request);
        //執行非同步請求
        call.enqueue(callback);


    }

    /**
     * post請求
     * 引數1 url
     * 引數2 Map<String, String> params post請求的時候給伺服器傳的資料
     *      add..("","")
     *      add()
     */

    public static void doPost(String url, Map<String, String> params, Callback callback) {

        //要新增的公共引數...map
        Map<String,String> map = new HashMap<>();
        map.put("source","android");

        //建立OkHttpClient請求物件
        OkHttpClient okHttpClient = getInstance();
        //3.x版本post請求換成FormBody 封裝鍵值對引數

        FormBody.Builder builder = new FormBody.Builder();
        //遍歷集合,,,map集合遍歷方式
        for (String key : params.keySet()) {
            builder.add(key, params.get(key));

        }

        //新增公共引數的map結合中的引數
        for (String key : map.keySet()) {
            builder.add(key, map.get(key));

        }


        //建立Request....formBody...new formBody.Builder()...add()....build()
        Request request = new Request.Builder().url(url).post(builder.build()).build();

        Call call = okHttpClient.newCall(request);
        call.enqueue(callback);

    }

    /**
     * post請求上傳檔案....包括圖片....流的形式傳任意檔案...
     * 引數1 url
     * file表示上傳的檔案
     * fileName....檔案的名字,,例如aaa.jpg
     * params ....傳遞除了file檔案 其他的引數放到map集合
     *
     */
    public static void uploadFile(String url, File file, String fileName,Map<String,String> params,Callback callback) {
        //建立OkHttpClient請求物件
        OkHttpClient okHttpClient = getInstance();

        //MultipartBody多功能的請求實體物件,,,formBody只能傳表單形式的資料
        MultipartBody.Builder builder = new MultipartBody.Builder();
        builder.setType(MultipartBody.FORM);

        //引數
        if (params != null){
            for (String key : params.keySet()){
                builder.addFormDataPart(key,params.get(key));
            }
        }
        //檔案...引數name指的是請求路徑中所接受的引數...如果路徑接收引數鍵值是fileeeee,此處應該改變
        builder.addFormDataPart("file",fileName,RequestBody.create(MediaType.parse("application/octet-stream"),file));

        //構建
        MultipartBody multipartBody = builder.build();

        //建立Request
        Request request = new Request.Builder().url(url).post(multipartBody).build();

        //得到Call
        Call call = okHttpClient.newCall(request);
        //執行請求
        call.enqueue(callback);

    }

    /**
     * Post請求傳送JSON資料....{"name":"zhangsan","pwd":"123456"}
     * 引數一:請求Url
     * 引數二:請求的JSON
     * 引數三:請求回撥
     */
    public static void doPostJson(String url, String jsonParams, Callback callback) {
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonParams);
        Request request = new Request.Builder().url(url).post(requestBody).build();
        Call call = getInstance().newCall(request);
        call.enqueue(callback);

    }

    /**
     * 下載檔案 以流的形式把apk寫入的指定檔案 得到file後進行安裝
     * 引數er:請求Url
     * 引數san:儲存檔案的資料夾....download
     */
    public static void download(final Activity context, final String url, final String saveDir) {
        //get請求
        Request request = new Request.Builder().url(url).build();
        Call call = getInstance().newCall(request);

        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                //com.orhanobut.logger.Logger.e(e.getLocalizedMessage());
            }

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

                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;
                try {
                    //response.body().string()...json限制是1M大小...byteStream()流的方式

                    is = response.body().byteStream();//以位元組流的形式拿回響應實體內容
                    //apk儲存路徑
                    final String fileDir = isExistDir(saveDir);
                    //檔案
                    File file = new File(fileDir, getNameFromUrl(url));

                    fos = new FileOutputStream(file);
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                    }

                    fos.flush();

                    context.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Toast.makeText(context, "下載成功:" + fileDir + "," + getNameFromUrl(url), Toast.LENGTH_SHORT).show();
                        }
                    });

                    //apk下載完成後 呼叫系統的安裝方法......覆蓋安裝,,,只有包名和簽名的應用,並且版本和版本號升級後的才能安裝
                    Intent intent = new Intent(Intent.ACTION_VIEW);
                    intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
                    context.startActivity(intent);


                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    if (is != null) is.close();
                    if (fos != null) fos.close();


                }
            }
        });

    }

    /**
     * 判斷下載目錄是否存在......並返回絕對路徑
     *
     * @param saveDir
     * @return
     * @throws IOException
     */
    public static String isExistDir(String saveDir) throws IOException {
        // 下載位置
        if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {

            File downloadFile = new File(Environment.getExternalStorageDirectory(), saveDir);
            if (!downloadFile.mkdirs()) {
                downloadFile.createNewFile();
            }
            String savePath = downloadFile.getAbsolutePath();
            Log.e("savePath", savePath);
            return savePath;
        }
        return null;
    }

    /**
     * @param url
     * @return 從下載連線中解析出檔名
     */
    private static String getNameFromUrl(String url) {
        return url.substring(url.lastIndexOf("/") + 1);
    }

}