Reason for app rejection on Play Store:
Your app(s) are using an unsafe implementation of the HostnameVerifier interface. You can find more information about how to resolve the issue in this Google Help Center article.
Hello All,
I'm getting a HostnameVerifier issue by google play console when I upload the app to the play store. I've tried each and every solution that I've found on StackOverflow, but still, the issue is the same i.e Your app(s) are using an unsafe implementation of the HostnameVerifier interface.
Also, I've gone through the google documentation for this issue but didn't get any luck. Does anyone have a solution regarding this? Every help is appreciated
Below is my ServiceGenerator
class
public class ServiceGenerator {
private static final String KEY_AUTH_HEADER = "Authorization";
private Context context;
private Retrofit.Builder builder;
private OkHttpClient.Builder httpClient;
HandshakeCertificates certificates;
ServiceGenerator(Context context) {
this.context = context;
final String dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'";
httpClient = new OkHttpClient.Builder();
certificates = new HandshakeCertificates.Builder()
.addTrustedCertificate(AppConstants.SSL_CERTIFICATE_DEMO)
.addTrustedCertificate(AppConstants.SSL_CERTIFICATE_LIVE)
// Uncomment if standard certificates are also required.
.addPlatformTrustedCertificates()
.build();
// Install the all-trusting trust manager
final SSLContext sslContext;
try {
sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new X509TrustManager[]{certificates.trustManager()}, new java.security.SecureRandom());
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
httpClient.sslSocketFactory(sslSocketFactory, certificates.trustManager());
httpClient.hostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});
} catch (NoSuchAlgorithmException | KeyManagementException e) {
e.printStackTrace();
}
httpClient.connectTimeout(60, TimeUnit.SECONDS);
httpClient.readTimeout(60, TimeUnit.SECONDS);
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
int cacheSize = 20 * 1024 * 1024; // 20 MB
Cache cache = new Cache(context.getCacheDir(), cacheSize);
logging.level(HttpLoggingInterceptor.Level.BASIC);
httpClient.cache(cache);
httpClient.addNetworkInterceptor(new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
if (Functions.isConnected(context)) {
int maxAge = 60 * 2; // read from cache for 2 minute
return originalResponse.newBuilder()
.header("Cache-Control", "public, max-age=" + maxAge)
.build();
} else {
int maxStale = 60 * 60 * 24 * 28; // tolerate 4-weeks stale
return originalResponse.newBuilder()
.header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
.build();
}
}
});
httpClient.addInterceptor(logging);
httpClient.addInterceptor(new HeaderInterceptor());
Gson gson = new GsonBuilder()
.setDateFormat(dateFormat)
.create();
builder = new Retrofit.Builder()
.baseUrl(Apis.HOST);
builder.addConverterFactory(GsonConverterFactory.create(gson));
}
class HeaderInterceptor implements Interceptor {
@Override
public Response intercept(Chain chain) throws IOException {
String authKey = "authKey";
if (PrefUtils.isUserLoggedIn(context) && PrefUtils.getUserFullProfileDetails(context) != null) {
authKey = PrefUtils.getUserFullProfileDetails(context).getAuthKey();
}
Request newRequest = chain.request().newBuilder()
.addHeader("auth-key", authKey)
.build();
return chain.proceed(newRequest);
}
}
public <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient.build()).build();
return retrofit.create(serviceClass);
}
}