Retrofit 2 无法解析主机
Retrofit 2 unable to resolve host
在我以前的应用程序版本中,我使用了 Apache 客户端,并且一切正常并且仍然有效。但我们决定转向 Retrofit 是因为获得了一些性能提升。问题是我每次都得到 "Unable to resolve host "xxxxxx": No address associated with hostname"。
我把这个放在清单里面
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
还有什么我忘了的吗?
这是url:https://www.hbapimanager.azure-api.net/Wallet/CheckNumber
P.S。我已经为此苦苦挣扎了将近一个星期
已编辑:这是我的 retrofitFactory class:
private static HttpLoggingInterceptor logging = new HttpLoggingInterceptor()
.setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE);
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder()
.addInterceptor(logging);
private static HttpUrl url = new HttpUrl.Builder()
.scheme("https")
.host(Constants.Network.HOST)
.build();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create());
public static <T> T createRetrofitService(final Class<T> clazz) {
Retrofit retrofit = builder.client(httpClient.build()).build();
return retrofit.create(clazz);
}
这是请求的接口
@Headers({
Constants.Network.HEADER_TYPE,
Constants.Network.HEADER_KEY
})
@POST(Constants.Network.CHECK_NUMBER)
Call<StatusData> postCheckNumber(@Body CheckNumberPoRD checkNumberPoRD);
@Headers({
Constants.Network.HEADER_TYPE,
Constants.Network.HEADER_KEY
})
@GET(Constants.Network.CHECK_NUMBER)
Call<CheckNumberGRD> getCheckNumber(
@Query("PrimaryKey") String primaryKey,
@Query("RowKey") String rowKey
);
然后我得到
09-06 16:58:50.958 7229-7283/kz.halykbank.halykewallet D/OkHttp: --> POST https://www.hbapimanager.azure-api.net/Wallet/CheckNumber http/1.1
09-06 16:58:50.959 7229-7283/kz.halykbank.halykewallet D/OkHttp: Content- Type: application/json
09-06 16:58:50.959 7229-7283/kz.halykbank.halykewallet D/OkHttp: Content-Length: 27
09-06 16:58:50.959 7229-7283/kz.halykbank.halykewallet D/OkHttp: Ocp-Apim-Subscription-Key: xxxxxxxxxxxxxxxxxxxxxxxxx
09-06 16:58:50.959 7229-7283/kz.halykbank.halykewallet D/OkHttp: {"phone":"x(xxx)xxx-xx-xx"}
09-06 16:58:50.959 7229-7283/kz.halykbank.halykewallet D/OkHttp: --> END POST (27-byte body)
09-06 16:58:51.666 7229-7283/kz.halykbank.halykewallet D/OkHttp: <-- HTTP FAILED: java.net.UnknownHostException: Unable to resolve host "www.hbapimanager.azure-api.net": No address associated with hostname
你肯定 运行 认为你的基础 URL 看起来像这样:
http://blah.com/v1/blah
你的服务看起来像
@GET("/blah/blah/blah")
但实际上你必须让它看起来像这样:
http://blah.com/v1/blah/
并且您的服务需要看起来像
@GET("blah/blah/blah")
HttpUrl baseUrl = new HttpUrl.Builder()
.scheme("https")
.host("www.hbapimanager.azure-api.net")
.encodedPath("/Wallet/")
.build();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new AdditionalHttpHeadersInterceptor(headersProvider))
.addInterceptor(httpLoggingInterceptor)
.build();
ApiService apiService = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
.create(ApiService.class);
ApiService.java
@Headers({
Constants.Network.HEADER_TYPE,
Constants.Network.HEADER_KEY
})
@GET(Constants.Network.CHECK_NUMBER)
Call<CheckNumberGRD> getCheckNumber(
@Query("PrimaryKey") String primaryKey,
@Query("RowKey") String rowKey
);
其中 Constants.Network.CHECK_NUMBER
是没有斜线的 "CheckNumber"
但是,由于 https,您可能必须设置自定义 ssl 套接字工厂。接下来是最简单的方法:
创建您的自定义 SSL 工厂class
public class TLSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory internalSSLSocketFactory;
public TLSSocketFactory() {
SSLContext context = null;
try {
context = SSLContext.getInstance("TLS");
context.init(null, null, null);
} catch (NoSuchAlgorithmException | KeyManagementException e) {
//TODO check it and fix
throw new RuntimeException(e);
}
internalSSLSocketFactory = context.getSocketFactory();
}
@Override
public String[] getDefaultCipherSuites() {
return internalSSLSocketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return internalSSLSocketFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSOnSocket(Socket socket) {
if (socket != null && (socket instanceof SSLSocket)) {
((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.1", "TLSv1.2"});
}
return socket;
}
}
和您的自定义 X509 信任管理器 class
public class CustomX509TrustManager implements X509TrustManager {
@SuppressLint("TrustAllX509TrustManager")
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@SuppressLint("TrustAllX509TrustManager")
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
并创建您的 http 客户端
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.sslSocketFactory(new CustomX509TrustManager(), new TLSSocketFactory())
.addInterceptor(new AdditionalHttpHeadersInterceptor(headersProvider))
.addInterceptor(httpLoggingInterceptor)
.build();
我的问题是我试图向 https://www.example.com 发送请求。但是,服务器的主机中没有www.example.com,只有example.com。
在我以前的应用程序版本中,我使用了 Apache 客户端,并且一切正常并且仍然有效。但我们决定转向 Retrofit 是因为获得了一些性能提升。问题是我每次都得到 "Unable to resolve host "xxxxxx": No address associated with hostname"。
我把这个放在清单里面
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
还有什么我忘了的吗?
这是url:https://www.hbapimanager.azure-api.net/Wallet/CheckNumber
P.S。我已经为此苦苦挣扎了将近一个星期
已编辑:这是我的 retrofitFactory class:
private static HttpLoggingInterceptor logging = new HttpLoggingInterceptor()
.setLevel(BuildConfig.DEBUG ? HttpLoggingInterceptor.Level.BODY : HttpLoggingInterceptor.Level.NONE);
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder()
.addInterceptor(logging);
private static HttpUrl url = new HttpUrl.Builder()
.scheme("https")
.host(Constants.Network.HOST)
.build();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(url)
.addConverterFactory(GsonConverterFactory.create());
public static <T> T createRetrofitService(final Class<T> clazz) {
Retrofit retrofit = builder.client(httpClient.build()).build();
return retrofit.create(clazz);
}
这是请求的接口
@Headers({
Constants.Network.HEADER_TYPE,
Constants.Network.HEADER_KEY
})
@POST(Constants.Network.CHECK_NUMBER)
Call<StatusData> postCheckNumber(@Body CheckNumberPoRD checkNumberPoRD);
@Headers({
Constants.Network.HEADER_TYPE,
Constants.Network.HEADER_KEY
})
@GET(Constants.Network.CHECK_NUMBER)
Call<CheckNumberGRD> getCheckNumber(
@Query("PrimaryKey") String primaryKey,
@Query("RowKey") String rowKey
);
然后我得到
09-06 16:58:50.958 7229-7283/kz.halykbank.halykewallet D/OkHttp: --> POST https://www.hbapimanager.azure-api.net/Wallet/CheckNumber http/1.1
09-06 16:58:50.959 7229-7283/kz.halykbank.halykewallet D/OkHttp: Content- Type: application/json
09-06 16:58:50.959 7229-7283/kz.halykbank.halykewallet D/OkHttp: Content-Length: 27
09-06 16:58:50.959 7229-7283/kz.halykbank.halykewallet D/OkHttp: Ocp-Apim-Subscription-Key: xxxxxxxxxxxxxxxxxxxxxxxxx
09-06 16:58:50.959 7229-7283/kz.halykbank.halykewallet D/OkHttp: {"phone":"x(xxx)xxx-xx-xx"}
09-06 16:58:50.959 7229-7283/kz.halykbank.halykewallet D/OkHttp: --> END POST (27-byte body)
09-06 16:58:51.666 7229-7283/kz.halykbank.halykewallet D/OkHttp: <-- HTTP FAILED: java.net.UnknownHostException: Unable to resolve host "www.hbapimanager.azure-api.net": No address associated with hostname
你肯定 运行 认为你的基础 URL 看起来像这样:
http://blah.com/v1/blah
你的服务看起来像
@GET("/blah/blah/blah")
但实际上你必须让它看起来像这样:
http://blah.com/v1/blah/
并且您的服务需要看起来像
@GET("blah/blah/blah")
HttpUrl baseUrl = new HttpUrl.Builder()
.scheme("https")
.host("www.hbapimanager.azure-api.net")
.encodedPath("/Wallet/")
.build();
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(new AdditionalHttpHeadersInterceptor(headersProvider))
.addInterceptor(httpLoggingInterceptor)
.build();
ApiService apiService = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
.create(ApiService.class);
ApiService.java
@Headers({
Constants.Network.HEADER_TYPE,
Constants.Network.HEADER_KEY
})
@GET(Constants.Network.CHECK_NUMBER)
Call<CheckNumberGRD> getCheckNumber(
@Query("PrimaryKey") String primaryKey,
@Query("RowKey") String rowKey
);
其中 Constants.Network.CHECK_NUMBER
是没有斜线的 "CheckNumber"
但是,由于 https,您可能必须设置自定义 ssl 套接字工厂。接下来是最简单的方法:
创建您的自定义 SSL 工厂class
public class TLSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory internalSSLSocketFactory;
public TLSSocketFactory() {
SSLContext context = null;
try {
context = SSLContext.getInstance("TLS");
context.init(null, null, null);
} catch (NoSuchAlgorithmException | KeyManagementException e) {
//TODO check it and fix
throw new RuntimeException(e);
}
internalSSLSocketFactory = context.getSocketFactory();
}
@Override
public String[] getDefaultCipherSuites() {
return internalSSLSocketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return internalSSLSocketFactory.getSupportedCipherSuites();
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSOnSocket(Socket socket) {
if (socket != null && (socket instanceof SSLSocket)) {
((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1.1", "TLSv1.2"});
}
return socket;
}
}
和您的自定义 X509 信任管理器 class
public class CustomX509TrustManager implements X509TrustManager {
@SuppressLint("TrustAllX509TrustManager")
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@SuppressLint("TrustAllX509TrustManager")
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[]{};
}
}
并创建您的 http 客户端
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.sslSocketFactory(new CustomX509TrustManager(), new TLSSocketFactory())
.addInterceptor(new AdditionalHttpHeadersInterceptor(headersProvider))
.addInterceptor(httpLoggingInterceptor)
.build();
我的问题是我试图向 https://www.example.com 发送请求。但是,服务器的主机中没有www.example.com,只有example.com。