OkHttp3Util的封裝

public class OkHttp3Util {

    /**
     * 懶漢 安全 加同步
     * 私有的靜態成員變量 只聲明不創建
     * 私有的構造方法
     * 提供返回實例的靜態方法
     */
    private static OkHttpClient okHttpClient = null;


    private OkHttp3Util() {
    }

    public static OkHttpClient getInstance() {
        if (okHttpClient == null) {
            //加同步安全
            synchronized (OkHttp3Util.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)//讀取超時

                            //.addInterceptor(new CommonParamsInterceptor())//添加的是應用攔截器...公共參數
                            //.addNetworkInterceptor(new CacheInterceptor())//添加的網絡攔截器

                            .cache(new Cache(sdcache.getAbsoluteFile(), cacheSize))//設置緩存
                            .build();
                }
            }

        }

        return okHttpClient;
    }

    /**
     * get請求
     * 參數1 url
     * 參數2 回調Callback
     */

    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("?");
        }

        //添加公共參數....
        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();
        //遍歷集合
        for (String key : params.keySet()) {
            builder.add(key, params.get(key));

        }

        //添加公共參數
        for (Map.Entry<String,String> entry: map.entrySet()) {
            builder.add(entry.getKey(),entry.getValue());
        }

        //創建Request
        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) {
        //創建OkHttpClient請求對象
        OkHttpClient okHttpClient = getInstance();

        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(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                Log.e("upload",e.getLocalizedMessage());
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                //上傳成功回調 目前不需要處理
                if (response.isSuccessful()){
                    String s = response.body().string();
                    Log.e("upload","上傳--"+s);
                }
            }
        });

    }

    /**
     * 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) {
        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 {
                    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);
    }

    /**
     * 公共參數攔截器
     */
    private static class CommonParamsInterceptor implements Interceptor{

        //攔截的方法
        @Override
        public Response intercept(Chain chain) throws IOException {

            //獲取到請求
            Request request = chain.request();
            //獲取請求的方式
            String method = request.method();
            //獲取請求的路徑
            String oldUrl = request.url().toString();

            Log.e("---攔截器",request.url()+"---"+request.method()+"--"+request.header("User-agent"));

            //要添加的公共參數...map
            Map<String,String> map = new HashMap<>();
            map.put("source","android");

            if ("GET".equals(method)){
                // 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

                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("?");
                }

               //添加公共參數....
                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();//新的路徑

                //拿着新的路徑重新構建請求
                request = request.newBuilder()
                        .url(newUrl)
                        .build();


            }else if ("POST".equals(method)){
                //先獲取到老的請求的實體內容
                RequestBody oldRequestBody = request.body();//....之前的請求參數,,,需要放到新的請求實體內容中去

                //如果請求調用的是上面doPost方法
                if (oldRequestBody instanceof FormBody){
                    FormBody oldBody = (FormBody) oldRequestBody;

                    //構建一個新的請求實體內容
                    FormBody.Builder builder = new FormBody.Builder();
                    //1.添加老的參數
                    for (int i=0;i<oldBody.size();i++){
                        builder.add(oldBody.name(i),oldBody.value(i));
                    }
                    //2.添加公共參數
                    for (Map.Entry<String,String> entry:map.entrySet()) {

                        builder.add(entry.getKey(),entry.getValue());
                    }

                    FormBody newBody = builder.build();//新的請求實體內容

                    //構建一個新的請求
                    request = request.newBuilder()
                            .url(oldUrl)
                            .post(newBody)
                            .build();
                }


            }


            Response response = chain.proceed(request);

            return response;
        }
    }


}
發佈了62 篇原創文章 · 獲贊 5 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章