ExceptionInitializerError with new Android 11 version (DP1)
See original GitHub issueOKHTTP 3.14.4 Retrofit 2.7.1 Device: Pixel 3 XL Android Build: crosshatch-rpp1.200123.016-factory-5808a1e6.zip
Note: Issue is not reproducible on Android 10 or earlier versions.
Found this issue when running my sample app using latest version of Retrofit (2.7.1) and targeting newly released Android 11 (targetSdkVersion = 30).
When attempting to run the app in Android 11, the app immediately crashes with the following exception:
2020-02-20 14:26:08.386 22962-22962/com.my.example.retrofit2 E/AndroidRuntime: FATAL EXCEPTION: main Process: com.my.example.retrofit2, PID: 22962 java.lang.ExceptionInInitializerError at okhttp3.internal.platform.Platform.get(Platform.java:85) at okhttp3.OkHttpClient.newSslSocketFactory(OkHttpClient.java:263) at okhttp3.OkHttpClient.<init>(OkHttpClient.java:229) at okhttp3.OkHttpClient.<init>(OkHttpClient.java:202) at retrofit2.Retrofit$Builder.build(Retrofit.java:614) at com.my.example.retrofit2.network.RetrofitInstance.getRetrofitInstance(RetrofitInstance.java:37) at com.my.example.retrofit2.main.IntractorImpl.getMarsPhotosArrayList(IntractorImpl.java:21) at com.my.example.retrofit2.main.MainPresenterImpl.requestDataFromServer(MainPresenterImpl.java:29) at com.my.example.retrofit2.main.MainActivity.onCreate(MainActivity.java:37) at android.app.Activity.performCreate(Activity.java:7970) at android.app.Activity.performCreate(Activity.java:7959) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3311) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3480) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2041) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:216) at android.app.ActivityThread.main(ActivityThread.java:7472) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:578) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:956) Caused by: java.lang.IllegalStateException: Expected Android API level 21+ but was 29 at okhttp3.internal.platform.AndroidPlatform.buildIfSupported(AndroidPlatform.java:238) at okhttp3.internal.platform.Platform.findPlatform(Platform.java:202) at okhttp3.internal.platform.Platform.<clinit>(Platform.java:79) at okhttp3.internal.platform.Platform.get(Platform.java:85) at okhttp3.OkHttpClient.newSslSocketFactory(OkHttpClient.java:263) at okhttp3.OkHttpClient.<init>(OkHttpClient.java:229) at okhttp3.OkHttpClient.<init>(OkHttpClient.java:202) at retrofit2.Retrofit$Builder.build(Retrofit.java:614) at com.my.example.retrofit2.network.RetrofitInstance.getRetrofitInstance(RetrofitInstance.java:37) at com.my.example.retrofit2.main.IntractorImpl.getMarsPhotosArrayList(IntractorImpl.java:21) at com.my.example.retrofit2.main.MainPresenterImpl.requestDataFromServer(MainPresenterImpl.java:29) at com.my.example.retrofit2.main.MainActivity.onCreate(MainActivity.java:37) at android.app.Activity.performCreate(Activity.java:7970) at android.app.Activity.performCreate(Activity.java:7959) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1309) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3311) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3480) at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2041) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:216) at android.app.ActivityThread.main(ActivityThread.java:7472) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:578) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:956)
My retrofit code is very simple and not attempting to do any custom initialization or setting a different OKHTTP client (see code for reference below):
` public static Retrofit getRetrofitInstance(){
if(retrofit == null){
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}`
After doing some digging into the OKHTTP code, noticed the following warning coming from adb logcat:
2020-02-20 14:26:08.382 22962-22962/com.my.example.retrofit2 D/NetworkSecurityConfig: No Network Security Config specified, using platform default 2020-02-20 14:26:08.384 22962-22962/com.my.example.retrofit2 W/DebugTag: Accessing hidden method Lcom/android/org/conscrypt/OpenSSLSocketImpl;->setUseSessionTickets(Z)V (greylist-max-q,core-platform-api, reflection, denied)
Per official documentation found here, Android 11 no longer allows Reflection API calls to setUseSessionTickets, which appears to be used in a few places when initializing AndroidSocketAdapter:
Looking at the other reflection calls done in the AndroidSocketAdapter, the following methods have also been blacklisted in Android 11 and will cause exceptions to be thrown:
1. private val getAlpnSelectedProtocol = sslSocketClass.getMethod("getAlpnSelectedProtocol")
2. private val setHostname = sslSocketClass.getMethod("setHostname", String::class.java)
Looks like OKHTTP will need to avoid these reflection calls and instead use available public APIs in Android 11 where applicable. Until then, applications may experience Fatal Runtime Exceptions when initializing OKHTTP. I noticed there is an Android10SocketAdapter, perhaps whats needed here would be an Android11SocketAdapter with specific implementation around these changes?
Let me know if more information is needed.
Best, Alex
Issue Analytics
- State:
- Created 4 years ago
- Reactions:4
- Comments:18 (7 by maintainers)
Top GitHub Comments
@JakeWharton I don’t think setHostname is required in Android 11.
Compare 4.4
https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/internal/platform/android/Android10SocketAdapter.kt
https://github.com/square/okhttp/blob/master/okhttp/src/main/java/okhttp3/internal/platform/android/AndroidSocketAdapter.kt
In addition to the two others mentioned
setHostname
andgetAlpnSelectedProtocol
,setAlpnProtocols
is used which is also on the list.Their replacements are:
The ALPN ones are a direct replacement, the
setHostname
one is a bit more complicated.