OkHttp3 攔截器 封裝公共引數
阿新 • • 發佈:2019-01-22
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.Interceptor;
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_03 {
/**
* 懶漢 安全 加同步
* 1.私有的靜態成員變數 只宣告不建立
* 2.私有的構造方法
* 3.提供返回例項的靜態方法
*/
private static OkHttpClient okHttpClient = null;
private OkHttp3Util_03() {
}
public static OkHttpClient getInstance() {
if (okHttpClient == null) {
//加同步安全
synchronized (OkHttp3Util_03.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())//新增應用攔截器的方法
.cache(new Cache(sdcache.getAbsoluteFile(), cacheSize))//設定快取
.build();
}
}
}
return okHttpClient;
}
/**
* get請求
* 引數1 url
* 引數2 回撥Callback
*
* oldUrl表示老的地址,,,是沒封裝公共引數之前的地址....公共引數指的是source=android
*
*/
public static void doGet(String oldUrl, Callback callback) {
//建立OkHttpClient請求物件
OkHttpClient okHttpClient = getInstance();
//建立Request
Request request = new Request.Builder().url(oldUrl).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) {
//建立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));
}
//建立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);
}
/**
* 封裝公共引數的攔截器
*/
private static class CommonParamsInterceptor implements Interceptor{
//intercept方法就是攔截的意思....攔截的是一個請求,,,一旦攔截之後可以對請求的引數進行處理
//Chain chain 鏈條的意思
@Override
public Response intercept(Chain chain) throws IOException {
Log.e("----","攔截器------");
//呼叫request()方法得到攔截的請求
Request request = chain.request();
//獲取請求的方式
String method = request.method();//GET POST
//攔截的請求的路徑
String oldUrl = request.url().toString();
//要新增的公共引數...map
Map<String,String> map = new HashMap<>();
map.put("source","android");
if ("GET".equals(method)){
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();
//新的路徑構建一個新的請求
request = request.newBuilder().url(newUrl).build();
}else if ("POST".equals(method)){
Log.e("--oldUrl--",oldUrl);
//引數在請求的實體內容上....拿到以前的引數,把以前的引數和公共引數全都新增到請求實體上
RequestBody requestBody = request.body();
if (requestBody instanceof FormBody){//前邊是不是後邊的子類/例項物件
FormBody oldBody = (FormBody) requestBody;//keywords...page
FormBody.Builder builder = new FormBody.Builder();
//先新增之前的引數
for (int i = 0;i<oldBody.size();i++){
//鍵值對的形式新增
builder.add(oldBody.name(i),oldBody.value(i));
}
//新增公共引數
for (Map.Entry<String,String> entry: map.entrySet()) {
builder.add(entry.getKey(),entry.getValue());
}
//構建一個新的請求
request = request.newBuilder().url(oldUrl).post(builder.build()).build();
}
}
//執行請求 獲取到響應
Response response = chain.proceed(request);
return response;
}
}
}
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.Interceptor;
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_03 {
/**
* 懶漢 安全 加同步
* 1.私有的靜態成員變數 只宣告不建立
* 2.私有的構造方法
* 3.提供返回例項的靜態方法
*/
private static OkHttpClient okHttpClient = null;
private OkHttp3Util_03() {
}
public static OkHttpClient getInstance() {
if (okHttpClient == null) {
//加同步安全
synchronized (OkHttp3Util_03.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())//新增應用攔截器的方法
.cache(new Cache(sdcache.getAbsoluteFile(), cacheSize))//設定快取
.build();
}
}
}
return okHttpClient;
}
/**
* get請求
* 引數1 url
* 引數2 回撥Callback
*
* oldUrl表示老的地址,,,是沒封裝公共引數之前的地址....公共引數指的是source=android
*
*/
public static void doGet(String oldUrl, Callback callback) {
//建立OkHttpClient請求物件
OkHttpClient okHttpClient = getInstance();
//建立Request
Request request = new Request.Builder().url(oldUrl).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) {
//建立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));
}
//建立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);
}
/**
* 封裝公共引數的攔截器
*/
private static class CommonParamsInterceptor implements Interceptor{
//intercept方法就是攔截的意思....攔截的是一個請求,,,一旦攔截之後可以對請求的引數進行處理
//Chain chain 鏈條的意思
@Override
public Response intercept(Chain chain) throws IOException {
Log.e("----","攔截器------");
//呼叫request()方法得到攔截的請求
Request request = chain.request();
//獲取請求的方式
String method = request.method();//GET POST
//攔截的請求的路徑
String oldUrl = request.url().toString();
//要新增的公共引數...map
Map<String,String> map = new HashMap<>();
map.put("source","android");
if ("GET".equals(method)){
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();
//新的路徑構建一個新的請求
request = request.newBuilder().url(newUrl).build();
}else if ("POST".equals(method)){
Log.e("--oldUrl--",oldUrl);
//引數在請求的實體內容上....拿到以前的引數,把以前的引數和公共引數全都新增到請求實體上
RequestBody requestBody = request.body();
if (requestBody instanceof FormBody){//前邊是不是後邊的子類/例項物件
FormBody oldBody = (FormBody) requestBody;//keywords...page
FormBody.Builder builder = new FormBody.Builder();
//先新增之前的引數
for (int i = 0;i<oldBody.size();i++){
//鍵值對的形式新增
builder.add(oldBody.name(i),oldBody.value(i));
}
//新增公共引數
for (Map.Entry<String,String> entry: map.entrySet()) {
builder.add(entry.getKey(),entry.getValue());
}
//構建一個新的請求
request = request.newBuilder().url(oldUrl).post(builder.build()).build();
}
}
//執行請求 獲取到響應
Response response = chain.proceed(request);
return response;
}
}
}