最近在寫(xiě)做一個(gè)Android TV的項(xiàng)目,其中有一個(gè)功能是獲取天氣。在模擬器上測(cè)試時(shí),是可用的。但當(dāng)我在電視盒子上運(yùn)行時(shí)出現(xiàn)了問(wèn)題(報(bào)了SSLHandshakeExceptiion)。這里我訪(fǎng)問(wèn)網(wǎng)絡(luò)用的是zhy的OKHttpUtils,于是我查閱了許多資料。發(fā)現(xiàn)是證書(shū)沒(méi)有被信任的原因,但是我所訪(fǎng)問(wèn)的是心知天氣的接口,所以應(yīng)該不是接口問(wèn)題。而且我是通過(guò)ip去獲取本地天氣的(在之前通過(guò)網(wǎng)絡(luò)訪(fǎng)問(wèn)獲取的網(wǎng)絡(luò)ip)。在我一籌莫展的時(shí)候,我發(fā)現(xiàn)了這篇文章:
http://blog.csdn.net/Kenway090704/article/details/73817700
這里面提到,出現(xiàn)問(wèn)題的可能有兩種:
1,時(shí)間問(wèn)題。
2,證書(shū)不被信任。
于是我查看了電視盒子的時(shí)間,時(shí)2016年的某一天,所以我判斷是時(shí)間問(wèn)題。但是,盒子的時(shí)間是通過(guò)網(wǎng)絡(luò)獲取的,而且我無(wú)法修改。像我這種碼農(nóng),人微言輕的,也不方便讓公司換個(gè)盒字給我測(cè)試。于是我使用了上文中的第二個(gè)辦法,修改OKHttpClient的創(chuàng)建方式信任該證書(shū),以得到天氣情況。這里我做了簡(jiǎn)單的封裝。
下面是代碼:
**
* 網(wǎng)絡(luò)獲取中證書(shū)出現(xiàn)問(wèn)題時(shí),無(wú)法正常返回?cái)?shù)據(jù)。(有可能是因?yàn)闀r(shí)間問(wèn)題)
* Created by sjw on 2017/10/24.
*/
public class OkHttpHelper implements Runnable {
private OkHttpClient okHttpClient;
private WeatherBackListener weatherBackListener;
private String url;
private String response;
private Handler handler = new Handler(new Handler.Callback() {
@Override
public boolean handleMessage(Message msg) {
weatherBackListener.onWeatherBack(response);
return false;
}
});
@Override
public void run() {
okHttpClient = getUnsafeOkHttpClient();
Request request = new Request.Builder().url(url).build();
try {
Response response = okHttpClient.newCall(request).execute();
if (response.isSuccessful()) {
this.response = response.body().string();
handler.sendEmptyMessage(1);
} else {
this.response="失敗";
}
} catch (IOException e) {
this.response="失敗";
e.printStackTrace();
}
}
public interface WeatherBackListener {
void onWeatherBack(String response);
}
public void getWeather(String url, WeatherBackListener weatherBackListener) {
this.url = url;
this.weatherBackListener = weatherBackListener;
new Thread(this).start();
}
private static OkHttpClient getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new java.security.cert.X509Certificate[]{};
}
}
};
// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.sslSocketFactory(sslSocketFactory);
builder.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
OkHttpClient okHttpClient = builder.build();
return okHttpClient;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
這里是調(diào)用代碼的方法:
OkHttpHelper okHttpHelper = new OkHttpHelper();
okHttpHelper.getWeather(url, weatherBackListener);