package me.qixingchen.mdbilibili.network; import com.squareup.okhttp.Interceptor; import com.squareup.okhttp.OkHttpClient; import com.squareup.okhttp.Request; import com.squareup.okhttp.Response; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URL; import java.net.URLDecoder; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Map; import java.util.TreeMap; import java.util.concurrent.TimeUnit; import me.qixingchen.mdbilibili.app.Secret; import me.qixingchen.mdbilibili.utils.Log; import retrofit.GsonConverterFactory; import retrofit.Retrofit; import retrofit.RxJavaCallAdapterFactory; /** * Created by Yulan on 2015/9/22. * Retrofit 网络 */ public class RetrofitNetwork { private final static String TAG = RetrofitNetwork.class.getSimpleName(); private static String APIURL = "http://api.bilibili.cn"; /** * API 接口 */ public static Retrofit retrofitAPI = new Retrofit.Builder() .baseUrl(APIURL) .client(getClient()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build(); private static String MAIN_URL = "http://www.bilibili.com/"; /** * 主站 */ public static Retrofit retrofitMain = new Retrofit.Builder() .baseUrl(MAIN_URL) .client(getClient()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build(); /** * 没有写入BaseUri的Retrofit * 需要使用 .baseUrl(BASE_URI).build(); */ public static Retrofit.Builder getRetrofitNoBaseUri() { return new Retrofit.Builder() .client(getClient()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()); } /** * 获取 OkHttpClinet */ private static OkHttpClient getClient() { OkHttpClient client = new OkHttpClient(); client.setConnectTimeout(HttpCommon.OKHTTP_CLIENT_CONNECT_TIMEOUT, TimeUnit.SECONDS); client.setWriteTimeout(HttpCommon.OKHTTP_CLIENT_WRITE_TIMEOUT, TimeUnit.SECONDS); client.setReadTimeout(HttpCommon.OKHTTP_CLIENT_READ_TIMEOUT, TimeUnit.SECONDS); client.networkInterceptors().add(new LoggingInterceptor()); client.networkInterceptors().add(new SignInterceptor()); client.networkInterceptors().add(new UserAgentInterceptor()); return client; } /** * 获取签名串 */ private static String getSign(String paraUri) { MessageDigest md = null; paraUri += Secret.App_Secret; try { md = MessageDigest.getInstance("MD5"); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } assert md != null; byte[] Md5 = md.digest(paraUri.getBytes()); StringBuffer stringBuffer = new StringBuffer(); for (byte b : Md5) { int bt = b & 0xff; if (bt < 16) { stringBuffer.append(0); } stringBuffer.append(Integer.toHexString(bt)); } String sign = stringBuffer.toString(); return sign; } /** * 从 URL 获取参数 * * @param url URL * * @return 参数MAP */ public static Map<String, String> splitQuery(URL url) throws UnsupportedEncodingException { Map<String, String> query_pairs = new TreeMap<>(); String query = url.getQuery(); String[] pairs = query.split("&"); for (String pair : pairs) { int idx = pair.indexOf("="); query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8")); } return query_pairs; } /** * A combination of request parameters,added App_Key * see {@link RetrofitNetwork getSign(String paraUri)} */ private static String getParaUriNoSigned(Map<String, String> para) { para.put("ts", String.valueOf(System.currentTimeMillis() / 1000L)); para.put("appkey", Secret.App_Key); String paraUri = ""; for (Map.Entry<String, String> entry : para.entrySet()) { paraUri += entry.getKey() + "=" + entry.getValue() + "&"; } paraUri = paraUri.substring(0, paraUri.length() - 1); return paraUri; } public interface HttpCommon { int OKHTTP_CLIENT_CONNECT_TIMEOUT = 10; int OKHTTP_CLIENT_WRITE_TIMEOUT = 20; int OKHTTP_CLIENT_READ_TIMEOUT = 20; } /** * OKHttp log接口 */ static class LoggingInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); long t1 = System.nanoTime(); Log.i(TAG, String.format("Sending request %s", request.url())); Response response = chain.proceed(request); long t2 = System.nanoTime(); Log.i(TAG, String.format("Received response for %s in %.1fms%n", response.request().url(), (t2 - t1) / 1e6d)); return response; } } /** * 签名接口 */ static class SignInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); if (request != null) { URL requestURL = request.url(); if (!requestURL.getHost().contains("api")) { return chain.proceed(request); } String baseURL = requestURL.getProtocol() + "://" + requestURL.getHost() + requestURL.getPath(); Map<String, String> queryMap = splitQuery(requestURL); String paraUri = getParaUriNoSigned(queryMap); paraUri += "&sign=" + getSign(paraUri); Request.Builder signedRequestBuilder = request.newBuilder(); signedRequestBuilder.url(baseURL + "?" + paraUri); request = signedRequestBuilder.build(); } return chain.proceed(request); } } /** * 设置UA */ static class UserAgentInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request originalRequest = chain.request(); Request requestWithUserAgent = originalRequest.newBuilder() .removeHeader("User-Agent") .addHeader("User-Agent", Secret.User_Agent) .build(); return chain.proceed(requestWithUserAgent); } } }