1. build.gradle
implementation'com.squareup.retrofit2:retrofit:2.9.0'
implementation'com.google.code.gson:gson:2.8.6'
implementation'com.squareup.retrofit2:converter-gson:2.9.0'
如果想使用最新版本,可以把版本號改為+,然后去 External Libraries,看看下載下來的lib的版本號,再把+改為 看到的版本號即可。。 為什么,再改回來,使用+,可能每次都去網絡下載lib,導致編譯很慢。
版本號固定,比如gson, 2.8.6,本地已經有了,直接使用本地,不會再網絡請求。但是+號會,再次請求對比。不需要實時保持最新。
2.?public interface GitHubService {
@GET("check_update.php")
Call>reqNewVersionApk();
}
3.
{
OkHttpClient.Builder builder =new OkHttpClient.Builder();
? ? if (Consts.isDebug) {
HttpLoggingInterceptor loggingInterceptor =new HttpLoggingInterceptor("Retrofit2");
? ? ? ? //log打印級別,決定了log顯示的詳細程度
? ? ? ? loggingInterceptor.setPrintLevel(HttpLoggingInterceptor.Level.BODY);
? ? ? ? //log顏色級別,決定了log在控制臺顯示的顏色
? ? ? ? loggingInterceptor.setColorLevel(Level.INFO);
? ? ? ? builder.addInterceptor(loggingInterceptor);
? ? }
OkHttpClient client = builder.build();
? ? Retrofit retrofit =new Retrofit.Builder()
.client(client)
.baseUrl("http://www.xxx.xyz/xxx/app/")//要訪問的主機地址,注意以 /(斜線) 結束,不然可能會拋出異常
? ? ? ? ? ? .addConverterFactory(GsonConverterFactory.create())//添加Gson
? ? ? ? ? ? .build();
? ? GitHubService service = retrofit.create(GitHubService.class);
? ? // xxx/app/
? ? Call> call = service.reqNewVersionApk();
? ? call.enqueue(new Callback>() {
@Override
? ? ? ? public void onResponse(Call> call, retrofit2.Response> response) {
RespBase appUpdateResp = response.body();
? ? ? ? ? ? MyLog.print("appUpdateResp.getCode:" + appUpdateResp.getCode());
? ? ? ? ? ? MyLog.print("appUpdateResp.getdata.apkurl:" + appUpdateResp.getData().getApkUrl());
? ? ? ? }
@Override
? ? ? ? public void onFailure(Call> call, Throwable t) {
MyLog.printError(t);
? ? ? ? }
});
}
4.HttpLoggingInterceptor
/*
* Copyright 2016 jeasonlzy(廖子堯)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*? ? ? http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.lzy.okgo.interceptor;
import com.lzy.okgo.utils.IOUtils;
import com.lzy.okgo.utils.OkLogger;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import okhttp3.Connection;
import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Protocol;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.internal.http.HttpHeaders;
import okio.Buffer;
/**
* ================================================
* 作? ? 者:jeasonlzy(廖子堯)Github地址:https://github.com/jeasonlzy
* 版? ? 本:1.0
* 創建日期:2016/1/12
* 描? ? 述:OkHttp攔截器,主要用于打印日志
* 修訂歷史:
* ================================================
*/
public class HttpLoggingInterceptorimplements Interceptor {
private static final CharsetUTF8 = Charset.forName("UTF-8");
? ? private volatile LevelprintLevel = Level.NONE;
? ? private java.util.logging.LevelcolorLevel;
? ? private Loggerlogger;
? ? public enum Level {
NONE,? ? ? //不打印log
? ? ? ? BASIC,? ? ? //只打印 請求首行 和 響應首行
? ? ? ? HEADERS,? ? //打印請求和響應的所有 Header
? ? ? ? BODY? ? ? ? //所有數據全部打印
? ? }
public HttpLoggingInterceptor(String tag) {
logger = Logger.getLogger(tag);
? ? }
public void setPrintLevel(Level level) {
if (printLevel ==null)throw new NullPointerException("printLevel == null. Use Level.NONE instead.");
? ? ? ? printLevel = level;
? ? }
public void setColorLevel(java.util.logging.Level level) {
colorLevel = level;
? ? }
private void log(String message) {
logger.log(colorLevel, message);
? ? }
@Override
? ? public Responseintercept(Chain chain)throws IOException {
Request request = chain.request();
? ? ? ? if (printLevel == Level.NONE) {
return chain.proceed(request);
? ? ? ? }
//請求日志攔截
? ? ? ? logForRequest(request, chain.connection());
? ? ? ? //執行請求,計算請求時間
? ? ? ? long startNs = System.nanoTime();
? ? ? ? Response response;
? ? ? ? try {
response = chain.proceed(request);
? ? ? ? }catch (Exception e) {
log("<-- HTTP FAILED: " + e);
? ? ? ? ? ? throw e;
? ? ? ? }
long tookMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNs);
? ? ? ? //響應日志攔截
? ? ? ? return logForResponse(response, tookMs);
? ? }
private void logForRequest(Request request, Connection connection)throws IOException {
boolean logBody = (printLevel == Level.BODY);
? ? ? ? boolean logHeaders = (printLevel == Level.BODY ||printLevel == Level.HEADERS);
? ? ? ? RequestBody requestBody = request.body();
? ? ? ? boolean hasRequestBody = requestBody !=null;
? ? ? ? Protocol protocol = connection !=null ? connection.protocol() : Protocol.HTTP_1_1;
? ? ? ? try {
String requestStartMessage ="--> " + request.method() +' ' + request.url() +' ' + protocol;
? ? ? ? ? ? log(requestStartMessage);
? ? ? ? ? ? if (logHeaders) {
if (hasRequestBody) {
// Request body headers are only present when installed as a network interceptor. Force
// them to be included (when available) so there values are known.
? ? ? ? ? ? ? ? ? ? if (requestBody.contentType() !=null) {
log("\tContent-Type: " + requestBody.contentType());
? ? ? ? ? ? ? ? ? ? }
if (requestBody.contentLength() != -1) {
log("\tContent-Length: " + requestBody.contentLength());
? ? ? ? ? ? ? ? ? ? }
}
Headers headers = request.headers();
? ? ? ? ? ? ? ? for (int i =0, count = headers.size(); i < count; i++) {
String name = headers.name(i);
? ? ? ? ? ? ? ? ? ? // Skip headers from the request body as they are explicitly logged above.
? ? ? ? ? ? ? ? ? ? if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) {
log("\t" + name +": " + headers.value(i));
? ? ? ? ? ? ? ? ? ? }
}
log(" ");
? ? ? ? ? ? ? ? if (logBody && hasRequestBody) {
if (isPlaintext(requestBody.contentType())) {
bodyToString(request);
? ? ? ? ? ? ? ? ? ? }else {
log("\tbody: maybe [binary body], omitted!");
? ? ? ? ? ? ? ? ? ? }
}
}
}catch (Exception e) {
OkLogger.printStackTrace(e);
? ? ? ? }finally {
log("--> END " + request.method());
? ? ? ? }
}
private ResponselogForResponse(Response response, long tookMs) {
Response.Builder builder = response.newBuilder();
? ? ? ? Response clone = builder.build();
? ? ? ? ResponseBody responseBody = clone.body();
? ? ? ? boolean logBody = (printLevel == Level.BODY);
? ? ? ? boolean logHeaders = (printLevel == Level.BODY ||printLevel == Level.HEADERS);
? ? ? ? try {
log("<-- " + clone.code() +' ' + clone.message() +' ' + clone.request().url() +" (" + tookMs +"ms)");
? ? ? ? ? ? if (logHeaders) {
Headers headers = clone.headers();
? ? ? ? ? ? ? ? for (int i =0, count = headers.size(); i < count; i++) {
log("\t" + headers.name(i) +": " + headers.value(i));
? ? ? ? ? ? ? ? }
log(" ");
? ? ? ? ? ? ? ? if (logBody && HttpHeaders.hasBody(clone)) {
if (responseBody ==null)return response;
? ? ? ? ? ? ? ? ? ? if (isPlaintext(responseBody.contentType())) {
byte[] bytes = IOUtils.toByteArray(responseBody.byteStream());
? ? ? ? ? ? ? ? ? ? ? ? MediaType contentType = responseBody.contentType();
? ? ? ? ? ? ? ? ? ? ? ? String body =new String(bytes, getCharset(contentType));
? ? ? ? ? ? ? ? ? ? ? ? log("\tbody:" + body);
? ? ? ? ? ? ? ? ? ? ? ? responseBody = ResponseBody.create(responseBody.contentType(), bytes);
? ? ? ? ? ? ? ? ? ? ? ? return response.newBuilder().body(responseBody).build();
? ? ? ? ? ? ? ? ? ? }else {
log("\tbody: maybe [binary body], omitted!");
? ? ? ? ? ? ? ? ? ? }
}
}
}catch (Exception e) {
OkLogger.printStackTrace(e);
? ? ? ? }finally {
log("<-- END HTTP");
? ? ? ? }
return response;
? ? }
private static CharsetgetCharset(MediaType contentType) {
Charset charset = contentType !=null ? contentType.charset(UTF8) :UTF8;
? ? ? ? if (charset ==null) charset =UTF8;
? ? ? ? return charset;
? ? }
/**
* Returns true if the body in question probably contains human readable text. Uses a small sample
* of code points to detect unicode control characters commonly used in binary file signatures.
*/
? ? private static boolean isPlaintext(MediaType mediaType) {
if (mediaType ==null)return false;
? ? ? ? if (mediaType.type() !=null && mediaType.type().equals("text")) {
return true;
? ? ? ? }
String subtype = mediaType.subtype();
? ? ? ? if (subtype !=null) {
subtype = subtype.toLowerCase();
? ? ? ? ? ? if (subtype.contains("x-www-form-urlencoded") || subtype.contains("json") || subtype.contains("xml") || subtype.contains("html"))//
? ? ? ? ? ? ? ? return true;
? ? ? ? }
return false;
? ? }
private void bodyToString(Request request) {
try {
Request copy = request.newBuilder().build();
? ? ? ? ? ? RequestBody body = copy.body();
? ? ? ? ? ? if (body ==null)return;
? ? ? ? ? ? Buffer buffer =new Buffer();
? ? ? ? ? ? body.writeTo(buffer);
? ? ? ? ? ? Charset charset =getCharset(body.contentType());
? ? ? ? ? ? log("\tbody:" + buffer.readString(charset));
? ? ? ? }catch (Exception e) {
OkLogger.printStackTrace(e);
? ? ? ? }
}
}