Markdown版本筆記 | 個人GitHub首頁 | 個人博客 | 個人微信 | 個人郵箱 |
---|---|---|---|---|
MyAndroidBlogs | baiqiantao | baiqiantao | bqt20094 | baiqiantao@sina.com |
You'll also need Okio , which OkHttp uses for fast I/O and resizable調整 buffers。
Okio的API文檔java
compile 'com.squareup.okhttp3:okhttp:3.8.0' compile 'com.squareup.okio:okio:1.13.0'
okhttp-3.9.0.jar
okio-1.13.0.jarreact
Android下的網絡框架:android
HttpClient在Android 6.0中已經被剔除掉了
,若是想要使用Volley還必須使用一個第三方的jai包。OkHttp是一個 Java 的 HTTP+SPDY
客戶端開發包,同時也支持 Android,須要 Android 2.3 以上,同時還須要一個okio包。git
Retrofit
默認會使用OKHttp處理其網絡層請求PS:
SPDY(讀做「SPeeDY」)是Google開發的基於TCP的應用層協議,用以最小化網絡延遲,提高網絡速度,優化用戶的網絡使用體驗。
SPDY並非一種用於替代HTTP的協議,而是對HTTP協議的加強。
新協議的功能包括數據流的多路複用、請求優先級以及HTTP報頭壓縮。
谷歌表示,引入SPDY協議後,在實驗室測試中頁面加載速度比原先快64%。github
HTTP is the way modern applications network. It's how we exchange data & media. Doing HTTP efficiently makes your stuff材料、塞滿 load faster and saves bandwidth帶寬.web
OkHttp is an HTTP client that's efficient by default:json
OkHttp perseveres堅忍 when the network is troublesome: it will silently沉默的 recover from common connection problems. If your service has multiple IP addresses, OkHttp will attempt alternate輪流、交替 addresses if the first connect fails. This is necessary for IPv4+IPv6 and for services hosted in redundant冗餘的、多餘的 data centers. OkHttp initiates開始 new connections with modern TLS features (SNI, ALPN), and falls back to TLS 1.0 if the handshake fails.api
Using OkHttp is easy. Its request/response API is designed with fluent流暢的 builders and immutability不變的. It supports both synchronous blocking calls
and async calls with callbacks
.緩存
OkHttp supports Android 2.3 and above. For Java, the minimum requirement is 1.7.
Here’s some libraries that work nicely with OkHttp.
Volley-OkHttp-Android: A fork of Volley with changes to work with OkHttp. 使用OkHttp進行更改的fork自Volley的一個庫。
Wire: Clean, lightweight protocol buffers for Android and Java. 適用於Android和Java的清潔、輕便的protocol buffers。
public class MainActivity extends ListActivity { private User mUser; private String mBaseUrl = "http://api.95xiu.com/"; private OkHttpClient client; private TextView mTv; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String[] array = {"post方式提交鍵值對數據", "get方式提交鍵值對數據",}; mTv = new TextView(this); getListView().addFooterView(mTv); setListAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, array)); client=new OkHttpClient.Builder().build(); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { switch (position) { case 0: postWithParams(); //post方式提交鍵值對數據 break; case 1: getWithParams(); //get方式提交鍵值對數據 break; } } private void postWithParams() { String url = mBaseUrl + "user/loginv2.php"; FormBody formBody = new FormBody.Builder() .add("user", "103468") .add("pass", "103468") .build(); Request request = new Request.Builder().url(url).post(formBody).build(); client.newCall(request) .enqueue(new okhttp3.Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { final String responseString = response.body().string();//響應的內容 Log.i("bqt", "【body】" + decodeUnicodeToString(responseString));//{"result":0,"msg":"用戶不存在"} mUser = new Gson().fromJson(responseString, User.class);//類型轉換 runOnUiThread(() -> mTv.setText(decodeUnicodeToString(responseString)));//線程切換 } }); } private void getWithParams() { String url = mBaseUrl + "app/news/index.php" + "?session_id=" + mUser.getMsg().getSession_id() + "&uid=" + mUser.getMsg().getId(); Request request = new Request.Builder().url(url).get().build(); client.newCall(request) .enqueue(new okhttp3.Callback() { @Override public void onFailure(Call call, IOException e) { } @Override public void onResponse(Call call, Response response) throws IOException { final String responseString = response.body().string(); runOnUiThread(() -> mTv.setText(decodeUnicodeToString(responseString))); } }); } //將Unicode編碼解析成字符串形式(如漢字) public static String decodeUnicodeToString(String uString) { StringBuilder sb = new StringBuilder(); int i = -1, pos = 0; while ((i = uString.indexOf("\\u", pos)) != -1) { sb.append(uString.substring(pos, i)); if (i + 5 < uString.length()) { pos = i + 6; sb.append((char) Integer.parseInt(uString.substring(i + 2, i + 6), 16)); } } sb.append(uString.substring(pos)); return sb.toString(); } }
public class OkHttp_Activity extends ListActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String[] array = {"應用程序攔截器", "網絡攔截器", "Rewriting Requests,重寫請求", "Rewriting Responses,重寫響應",}; setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, array)); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { new Thread(() -> {//裏面用的都是同步請求,因此必須在一個子線程中調用 try {//線程裏面的異常不能在線程外面捕獲或throws switch (position) { case 0: loggingInterceptor(true, new LoggingInterceptor());//應用程序攔截器 break; case 1: loggingInterceptor(false, new LoggingInterceptor());//網絡攔截器 break; case 2: loggingInterceptor(new Random().nextBoolean(), new GzipRequestInterceptor());//重寫請求 break; case 3: loggingInterceptor(new Random().nextBoolean(), new ReWriteCacheControlInterceptor());//重寫響應 break; } } catch (IOException e) { e.printStackTrace(); } }).start(); } private void loggingInterceptor(boolean isApplicationInterceptor, Interceptor interceptor) throws IOException { OkHttpClient client; if (isApplicationInterceptor) client = new OkHttpClient.Builder().addInterceptor(interceptor).build(); else client = new OkHttpClient.Builder().addNetworkInterceptor(interceptor).build(); Request request = new Request.Builder() .url("http://publicobject.com/helloworld.txt") .header("User-Agent", "OkHttp Example") .build(); Response response = client.newCall(request).execute(); //同步執行 if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); System.out.println("【響應url】" + response.request().url()); response.body().close(); } //使用一個自定義的TLS版本和密碼組來構建你本身的鏈接規範 private void connectionSpecs() { ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) .tlsVersions(TlsVersion.TLS_1_2) .cipherSuites(CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) .build(); OkHttpClient client = new OkHttpClient.Builder() .connectionSpecs(Collections.singletonList(spec)) .build(); } //Certificate Pinning,證書鎖定 public void certificatePinner() throws Exception { CertificatePinner certificatePinner = new CertificatePinner.Builder() .add("publicobject.com", "sha256/afwiKY3RxoMmLkuRW1l7QsPZTJPwDS2pdDROQjXw8ig=") .build(); OkHttpClient client = new OkHttpClient.Builder() .certificatePinner(certificatePinner) .build(); Request request = new Request.Builder() .url("https://publicobject.com/robots.txt") .build(); Response response = client.newCall(request).execute(); if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); for (java.security.cert.Certificate certificate : response.handshake().peerCertificates()) { System.out.println("【】" + CertificatePinner.pin(certificate)); } } //攔截器 class LoggingInterceptor implements Interceptor { @Override public Response intercept(Interceptor.Chain chain) throws IOException { Request request = chain.request();//發出的請求 long t1 = System.nanoTime(); System.out.println("【請求】" + String.format("Sending request %s on %s%n%s", request.url(), chain.connection(), request.headers())); Response response = chain.proceed(request);//生成與請求對應的響應。這裏是全部HTTP工做發生的地方 long t2 = System.nanoTime(); System.out.println("【響應】" + String.format("Received response for %s in %.1fms%n%s", response.request().url(), (t2 - t1) / 1e6d, response.headers())); return response; } } //This interceptor compresses the HTTP request body. Many webservers can't handle this! class GzipRequestInterceptor implements Interceptor { @Override public Response intercept(Interceptor.Chain chain) throws IOException { Request originalRequest = chain.request(); if (originalRequest.body() == null || originalRequest.header("Content-Encoding") != null) { return chain.proceed(originalRequest);//生成與請求對應的響應 } RequestBody compressedRequestBody = new RequestBody() { @Override public MediaType contentType() { return originalRequest.body().contentType(); } @Override public long contentLength() { return -1; // We don't know the compressed length in advance(提早)! } @Override public void writeTo(BufferedSink sink) throws IOException { BufferedSink gzipSink = Okio.buffer(new GzipSink(sink)); originalRequest.body().writeTo(gzipSink); gzipSink.close(); } }; Request compressedRequest = originalRequest.newBuilder() .header("Content-Encoding", "gzip")//添加、刪除或者替換請求頭 .method(originalRequest.method(), compressedRequestBody)//改變請求體 .build(); return chain.proceed(compressedRequest);//從新生成與請求對應的響應 } } //Dangerous interceptor that rewrites the server's cache-control header. class ReWriteCacheControlInterceptor implements Interceptor { @Override public Response intercept(Interceptor.Chain chain) throws IOException { Response originalResponse = chain.proceed(chain.request()); return originalResponse.newBuilder() .header("Cache-Control", "max-age=60")//重寫響應頭 .build(); } } }
//【retrofit2】 compile 'com.squareup.retrofit2:retrofit:2.3.0' compile 'com.squareup.retrofit2:converter-gson:2.3.0' compile 'com.squareup.retrofit2:adapter-rxjava:2.3.0' //【okhttp】 compile 'com.squareup.okhttp3:okhttp:3.8.0' compile 'com.squareup.okhttp3:logging-interceptor:3.8.0' compile 'com.squareup.okio:okio:1.13.0' //【butterknife】 compile 'com.jakewharton:butterknife:8.8.1' annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1' //【rxjava】 compile 'io.reactivex:rxandroid:1.1.0' compile 'io.reactivex:rxjava:1.1.6'
public interface GitHubApi { @GET("repos/{owner}/{repo}/contributors") Call<ResponseBody> contributorsBySimpleGetCall(@Path("owner") String owner, @Path("repo") String repo); @GET("repos/{owner}/{repo}/contributors") Call<List<Contributor>> contributorsByAddConverterGetCall(@Path("owner") String owner, @Path("repo") String repo); @Headers({"Accept: application/vnd.github.v3.full+json", "User-Agent: RetrofitBean-Sample-App", "name:ljd"}) @GET("repos/{owner}/{repo}/contributors") Call<List<Contributor>> contributorsAndAddHeader(@Path("owner") String owner, @Path("repo") String repo); @GET("search/repositories") Call<RetrofitBean> queryRetrofitByGetCall(@Query("q") String owner, @Query("since") String time, @Query("page") int page, @Query("per_page") int per_Page); @GET("search/repositories") Call<RetrofitBean> queryRetrofitByGetCallMap(@QueryMap Map<String, String> map); @GET("repos/{owner}/{repo}/contributors") Observable<List<Contributor>> contributorsByRxJava(@Path("owner") String owner, @Path("repo") String repo); @GET("users/{user}") Observable<User> userByRxJava(@Path("user") String user); @GET("/mobilesafe/shouji360/360safesis/360MobileSafe_6.2.3.1060.apk") Call<ResponseBody> retrofitDownload(); }
public class MainActivity extends ListActivity { private TextView tv; private static final String baseUrl = "https://api.github.com/"; private static final String mUserName = "square";//哪一個公司【square】 private static final String mRepo = "retrofit";//哪一個項目【retrofit】 private CompositeSubscription mSubscriptions = new CompositeSubscription(); protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); String[] array = {"一、簡單完整演示retrofit的使用", "二、添加Gson轉換器", "三、添加okHttp的日誌攔截器Interceptor", "四、使用本身封裝的API,演示@Headers", "五、演示同步請求", "六、演示@Query", "七、演示@QueryMap", "八、最簡單、完整的retrofit+rxJava示例", "九、rxJava+retrofit加強", "十、演示文件下載",}; tv = new TextView(this); tv.setTextColor(Color.BLUE); getListView().addFooterView(tv); setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, array)); } @Override protected void onDestroy() { if (mSubscriptions != null) mSubscriptions.unsubscribe(); super.onDestroy(); } @Override protected void onListItemClick(ListView l, View v, int position, long id) { switch (position + 1) { case 1://簡單完整演示retrofit的使用 requestGitHubContributorsSimple(); break; case 2://添加Gson轉換器 requestGitHubContributorsByConverter(); break; case 3://添加okHttp的日誌攔截器Interceptor requestGitHubContributorsAddOkHttpLog(); break; case 4://使用本身封裝的API,演示@Headers requestGitHubContributorsAddHeader(); break; case 5://演示同步請求 requestGitHubContributorsBySync(); break; case 6://演示@Query requestQueryRetrofitByGet(false); break; case 7://演示@QueryMap requestQueryRetrofitByGet(true); break; case 8://最簡單、完整的retrofit+rxJava示例 requestGitHubContributorsByRxJava(); break; case 9://rxJava+retrofit加強 requestGitHubContributorsWithFullUserInfo(); break; case 10://演示文件下載 retrofitDownload(); break; } } //一、簡單示例 private void requestGitHubContributorsSimple() { Retrofit retrofit = new Retrofit.Builder() .baseUrl(baseUrl) .build(); GitHubApi repo = retrofit.create(GitHubApi.class); Call<ResponseBody> call = repo.contributorsBySimpleGetCall(mUserName, mRepo); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) { String result = null; try { result = response.body().string(); if (result == null) return; } catch (IOException e) { e.printStackTrace(); } tv.setText("GitHub上對項目的貢獻-1:\n"); ArrayList<Contributor> list = new Gson().fromJson(result, new TypeToken<List<Contributor>>() { }.getType()); if (list == null || list.size() == 0) return; for (Contributor contributor : list) { tv.append(contributor.login + " " + contributor.contributions + "\n"); } } @Override public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) { Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show(); } }); } //二、添加Gson轉換器 private void requestGitHubContributorsByConverter() { new Retrofit.Builder() .baseUrl(baseUrl) .addConverterFactory(GsonConverterFactory.create())//轉換器 .build() .create(GitHubApi.class) .contributorsByAddConverterGetCall(mUserName, mRepo) .enqueue(new Callback<List<Contributor>>() { @Override public void onResponse(@NonNull Call<List<Contributor>> call, @NonNull Response<List<Contributor>> response) { List<Contributor> list = response.body(); tv.setText("GitHub上對項目的貢獻-2:\n"); if (list == null || list.size() == 0) return; for (Contributor contributor : list) { tv.append(contributor.login + " " + contributor.contributions + "\n"); } } @Override public void onFailure(@NonNull Call<List<Contributor>> call, @NonNull Throwable t) { Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show(); } }); } //三、添加okHttp的日誌攔截器Interceptor private void requestGitHubContributorsAddOkHttpLog() { HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY); Retrofit retrofit = new Retrofit.Builder() .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(new OkHttpClient.Builder().addInterceptor(logInterceptor).build()) .baseUrl(baseUrl) .addConverterFactory(GsonConverterFactory.create()) .build(); retrofit.create(GitHubApi.class) .contributorsByAddConverterGetCall(mUserName, mRepo) .enqueue(new Callback<List<Contributor>>() { @Override public void onResponse(@NonNull Call<List<Contributor>> call, @NonNull Response<List<com.bqt .retrofit.bean.Contributor>> response) { List<Contributor> list = response.body(); tv.setText("GitHub上對項目的貢獻-3:\n"); if (list == null || list.size() == 0) return; for (Contributor contributor : list) { tv.append(contributor.login + " " + contributor.contributions + "\n"); } } @Override public void onFailure(@NonNull Call<List<Contributor>> call, @NonNull Throwable t) { Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show(); } }); } //四、使用本身封裝的API,演示@Headers private void requestGitHubContributorsAddHeader() { createRetrofitService(GitHubApi.class) .contributorsAndAddHeader(mUserName, mRepo) .enqueue(new Callback<List<Contributor>>() { @Override public void onResponse(@NonNull Call<List<Contributor>> call, @NonNull Response<List<com.bqt .retrofit.bean.Contributor>> response) { List<Contributor> list = response.body(); tv.setText("GitHub上對項目的貢獻-4:\n"); if (list == null || list.size() == 0) return; for (Contributor contributor : list) { tv.append(contributor.login + " " + contributor.contributions + "\n"); } } @Override public void onFailure(@NonNull Call<List<Contributor>> call, @NonNull Throwable t) { } }); } //五、演示同步請求 private void requestGitHubContributorsBySync() { final Call<List<Contributor>> call = createRetrofitService(GitHubApi.class) .contributorsByAddConverterGetCall(mUserName, mRepo); new Thread(() -> { try { Response<List<Contributor>> response = call.execute();//在子線程中請求網絡 final List<Contributor> list = response.body(); runOnUiThread(() -> { tv.setText("GitHub上對項目的貢獻-5:\n"); for (Contributor contributor : list) { tv.append(contributor.login + " " + contributor.contributions + "\n"); } }); } catch (IOException e) { e.printStackTrace(); } }).start(); } //6和七、演示@Query和@QueryMap private void requestQueryRetrofitByGet(boolean isQueryMap) { GitHubApi mGitHubService = createRetrofitService(GitHubApi.class); Call<RetrofitBean> call; if (!isQueryMap) call = mGitHubService.queryRetrofitByGetCall("retrofit", "2016-03-29", 1, 3); else { Map<String, String> queryMap = new HashMap<>(); queryMap.put("q", "retrofit"); queryMap.put("since", "2016-03-29"); queryMap.put("page", "1"); queryMap.put("per_page", "3"); call = mGitHubService.queryRetrofitByGetCallMap(queryMap); } call.enqueue(new Callback<RetrofitBean>() { @Override public void onResponse(@NonNull Call<RetrofitBean> call, @NonNull Response<RetrofitBean> response) { RetrofitBean retrofitBean = response.body(); if (retrofitBean == null) return; List<Item> list = retrofitBean.getItems(); if (list == null || list.size() == 0) return; tv.setText(new SimpleDateFormat("yyyy.MM.dd HH:mm:ss SSS", Locale.getDefault()).format(new Date())); tv.append("\ntotal:" + retrofitBean.getTotalCount() + "\nincompleteResults:" + retrofitBean.getIncompleteResults()); for (Item item : list) { tv.append("\n\n【name】" + item.name); tv.append("\n【full_name】" + item.full_name); tv.append("\n【 description】" + item.description); } } @Override public void onFailure(@NonNull Call<RetrofitBean> call, @NonNull Throwable t) { } }); } //八、最簡單、完整的retrofit+rxJava示例 private void requestGitHubContributorsByRxJava() { createRetrofitService(GitHubApi.class) .contributorsByRxJava(mUserName, mRepo)// .subscribeOn(Schedulers.io())// .observeOn(AndroidSchedulers.mainThread())// .subscribe(...); } //九、rxJava+retrofit加強 private void requestGitHubContributorsWithFullUserInfo() { Subscription subscription = createRetrofitService(GitHubApi.class) .contributorsByRxJava(mUserName, mRepo)// .flatMap(...) .flatMap(...) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(...; mSubscriptions.add(subscription); } //十、演示文件下載 public void retrofitDownload() { //監聽下載進度 final ProgressDialog dialog = new ProgressDialog(this); dialog.setProgressNumberFormat("%1d KB/%2d KB"); dialog.setTitle("下載"); dialog.setMessage("正在下載,請稍後..."); dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); dialog.setCancelable(false); dialog.show(); ProgressHelper.setProgressHandler(new DownloadProgressHandler() { @Override protected void onProgress(long bytesRead, long contentLength, boolean done) { //在主線程中運行 dialog.setMax((int) (contentLength / 1024)); dialog.setProgress((int) (bytesRead / 1024)); if (done) dialog.dismiss(); } }); Retrofit retrofit = new Retrofit.Builder()// .addCallAdapterFactory(RxJavaCallAdapterFactory.create())// .addConverterFactory(GsonConverterFactory.create())// .baseUrl("http://msoftdl.360.cn") .client(ProgressHelper.addProgress(null).build()) .build(); retrofit.create(GitHubApi.class).retrofitDownload() .enqueue(new Callback<ResponseBody>() { @Override public void onResponse(@NonNull Call<ResponseBody> call, @NonNull Response<ResponseBody> response) { try { InputStream is = response.body().byteStream(); File file = new File(Environment.getExternalStorageDirectory(), "12345.apk"); FileOutputStream fos = new FileOutputStream(file); BufferedInputStream bis = new BufferedInputStream(is); byte[] buffer = new byte[1024]; int len; while ((len = bis.read(buffer)) != -1) { fos.write(buffer, 0, len); fos.flush(); } fos.close(); bis.close(); is.close(); } catch (IOException e) { e.printStackTrace(); } } @Override public void onFailure(@NonNull Call<ResponseBody> call, @NonNull Throwable t) { } }); } public static <T> T createRetrofitService(final Class<T> service) { HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor() .setLevel(HttpLoggingInterceptor.Level.BODY); OkHttpClient.Builder builder = new OkHttpClient.Builder().addInterceptor(httpLoggingInterceptor); Retrofit retrofit = new Retrofit.Builder()// .client(ProgressHelper.addProgress(builder).build())// .addCallAdapterFactory(RxJavaCallAdapterFactory.create())// .addConverterFactory(GsonConverterFactory.create())// .baseUrl("https://api.github.com/")// .build(); return retrofit.create(service); } }
請求參數封裝:
public interface BqtService { @GET("User") Observable<BqtRes<User>> getUser(); @FormUrlEncoded @POST("BuyInfo/buyRecord") Observable<BqtRes<ArrayList<MyClassBean>>> getHistory(@Field("user_id") int uid, @Field("page") int page); }
調用示例:
H.h().getUser() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(response -> L.i("onNext " + response.data.toString());//這裏response.data的類型便是User
retrofit、okhttp、RxJava、Gson、攔截器、Header等配置
public class H { private static Interceptor buildInterceptor() { final String token = AccountManager.getInstance().getToken(); PackageInfo packInfo = null; try { packInfo = App.app.getPackageManager().getPackageInfo(App.app.getPackageName(), 0); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } final int version = packInfo == null ? 1 : packInfo.versionCode; return new Interceptor() {//應用程序攔截器,只被調用一次 @Override public okhttp3.Response intercept(Chain chain) throws IOException { Request request = chain.request() .newBuilder() .addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") .addHeader("Accept-Encoding", "gzip, deflate") .addHeader("Connection", "keep-alive") .addHeader("Accept", "*/*") //****************************************自定義Header .addHeader("version", version + "")//app版本號 .addHeader("token", token == null ? "" : token)//登陸後返回的token .addHeader("mobile", "1")// 0-PC,1-Android,2-IOS,3-web .build(); return chain.proceed(request); } }; } private static Interceptor buildLogInterceptor() { return new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() { @Override public void log(String message) { L.d(message);//這裏會打印出大量的日誌出來,因此不要和手動打印的日誌混在一塊兒 } }).setLevel(HttpLoggingInterceptor.Level.BODY);//日誌顯示級別 } private static OkHttpClient buildOkHttp() { return new OkHttpClient.Builder() .addInterceptor(buildHeaderInterceptor())//自定義Header .addInterceptor(buildLogInterceptor())//日誌攔截 .connectTimeout(5, TimeUnit.SECONDS) .build(); } private static Gson buildGson() { return new GsonBuilder()//配置你的Gson .setDateFormat("yyyy-MM-dd hh:mm:ss") .setPrettyPrinting() .serializeNulls() .create(); } private static String buildBaseUrl() { switch (UrlHelper.getEnv()) { case 0: // baseUlr 必須以 / 結束,否則會拋出一個IllegalArgumentException return "http://test.talk.99cj.com.cn/"; case 1: return "http://wechat.99cj.com.cn/"; default: return "http://wechat.99cj.com.cn/"; } } private static Retrofit buildRetrofit(OkHttpClient client, Converter.Factory converterFactory, CallAdapter.Factory callAdapterFactory) { return new Retrofit.Builder() .baseUrl(buildBaseUrl()) .client(client) .addConverterFactory(converterFactory)//能夠接收自定義的Gson,固然也能夠不傳 .addCallAdapterFactory(callAdapterFactory) .build(); } private static <T> T createRetrofitService(final Class<T> service) { Retrofit retrofit = buildRetrofit(buildOkHttp(), // GsonConverterFactory.create(buildGson()),// RxJavaCallAdapterFactory.create());// return retrofit.create(service); } public static BqtService h() { return createRetrofitService(BqtService.class); } }
添加上述【HttpLoggingInterceptor】攔截器後會打印以下日誌
2017-06-20