Closed zipswich closed 2 years ago
I am fairly certain the problem stems from upgrading okhttp. I need to check what has changed in the latest version. For now you can work around by downgrading to okhttp 4.7.2
hmm, ran all tests against okhttp 4.9.1 and everything passed. Which okhttp version are you using?
@rburgst Thanks a lot for looking into it. First, I am fairly sure at this point the problem has been resolved by downgrading to io.github.rburgst:okhttp-digest:1.21 from io.github.rburgst:okhttp-digest:2.5 I saw crash reports from Google Play within a few hours after two app releases with io.github.rburgst:okhttp-digest:2.5. The last update using 1.21 was rolled out 16 hours ago and I have not seen a single crash. I will report back if the crash happens. This makes sense because upgrading to 2.5 was the major change after I got rid of jcenter() and started using mavenCentral() exclusively.
I am using api 'com.squareup.okhttp3:okhttp:4.7.2'
I do not know why Android Studio does not prompt me to upgrade okhttp. It usually does when there is a newer version. For example, it now suggests upgrading okhttp-digest:1.21 to 2.5.
I am unable to reproduce this crash. I do not know what circumstances induce this. Here is the code:
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
final Map<String, CachingAuthenticator> authCache = new ConcurrentHashMap<>();
OkHttpClient client;
if (sUser == null) {
client = builder
.addInterceptor(new AuthenticationCacheInterceptor(authCache))
.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0])
.hostnameVerifier((hostname, session) -> true)
.retryOnConnectionFailure(true)
.build();
} else {
Credentials credentials = new Credentials(sUser, sPassword);
final BasicAuthenticator basicAuthenticator = new BasicAuthenticator(credentials);
final DigestAuthenticator digestAuthenticator = new DigestAuthenticator(credentials);
DispatchingAuthenticator authenticator = new DispatchingAuthenticator.Builder()
.with("digest", digestAuthenticator)
.with("basic", basicAuthenticator)
.build();
client = builder
.authenticator(new CachingAuthenticatorDecorator(authenticator, authCache))
.addInterceptor(new AuthenticationCacheInterceptor(authCache))
.sslSocketFactory(sslSocketFactory, (X509TrustManager) trustAllCerts[0])
.hostnameVerifier((hostname, session) -> true)
.retryOnConnectionFailure(true)
.build();
}
Request request = new Request.Builder()
.url(sHTTPURL)
.get()
.build();
Response response = client.newCall(request).execute();
The crash is caused by the last line: Response response = client.newCall(request).execute();
why are you using the api
scope rather than implementation
?
@rburgst This is in a utility library shared by many apps. I use api
in the library generally.
in that case the only thing that might cause this could be proguard?
That crossed my mind too. I use the following in proguard-project.txt:
-keep class com.burgstaller.** { *; }
Any clue why V1.21 works fine?
-keep class com.burgstaller.** { *; }
wont help at all in this case since the missing method is in the okhttp code. Something like that: https://github.com/square/okhttp/blob/master/okhttp/src/main/resources/META-INF/proguard/okhttp3.pro
okhttp-digest 1 depends on okhttp 3 and therefore, this is a quite different code base (they were using java in 3.x and kotlin in 4.x).
The app also has the following that I added a long ago when it started using okhttp3. I probably copied it from somewhere, but I do not remember.
#okhttp3
-keepattributes Signature
-keepattributes Annotation
-keep class okhttp3.** { *; }
-keep interface okhttp3.** { *; }
-dontwarn okhttp3.**
-dontwarn okio.**
since you are now using okhttp4 this will probably no longer be correct
Did you mean api 'com.squareup.okhttp3:okhttp:4.7.2'
is okhttp4?
actually I didnt check yesterday, I just knew that they changed the implmentation to kotlin and that might bring a few changes that need to be done for proguard.
Now that I checked your proguard files look allright.
I do have my own application using these rules (again, I have been using okhttp for a long time and therefore, my rules might not be)
# fix okio / okhttp
-dontwarn okio.**
-dontwarn java.nio.file.Files
-dontwarn java.nio.file.Path
-dontwarn java.nio.file.OpenOption
-dontwarn org.conscrypt.**
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
# Keep until > okhttp 4.7.2
# https://github.com/square/okhttp/issues/6092
-keepnames class okhttp3.OkHttpClient
Since you are not able to reproduce the crash (I am assuming you were using the emulator with the same SDK version where the crash happened). There is not much I can do to support you. You might need to bring this up with the okhttp guys.
The API that okhttp-digest
is using is a public api and AFAICT its being used correctly.
Also, you are the first one to report such an issue, therefore, I somehow doubt that okhttp digest is to blame.
Thanks a lot for looking into it. I have tested on an emulator and on a physical device, but could not reproduce it. However, I saw quite a few crashes from Google's crash reports but it is still rare because the app is active on hundreds of thousands of devices. I will give it another shot to try to reproduce it by testing different scenarios that I can come up. Since io.github.rburgst:okhttp-digest:1.21 works well now, it is not an urgent issue at all.
we've got exactly the same problem:
java.io.IOException: canceled due to java.lang.NoSuchFieldError: INSTANCE
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:185) ~[okhttp-3.14.9.jar:na]
at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) ~[okhttp-3.14.9.jar:na]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) ~[na:na]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) ~[na:na]
at java.base/java.lang.Thread.run(Unknown Source) ~[na:na]
Suppressed: java.lang.NoSuchFieldError: INSTANCE
at com.burgstaller.okhttp.digest.DigestAuthenticator.authenticateWithState(DigestAuthenticator.java:242) ~[okhttp-digest-2.5.jar:na]
at com.burgstaller.okhttp.digest.DigestAuthenticator.authenticate(DigestAuthenticator.java:180) ~[okhttp-digest-2.5.jar:na]
at com.burgstaller.okhttp.DispatchingAuthenticator.authenticate(DispatchingAuthenticator.java:45) ~[okhttp-digest-2.5.jar:na]
at com.burgstaller.okhttp.CachingAuthenticatorDecorator.authenticate(CachingAuthenticatorDecorator.java:35) ~[okhttp-digest-2.5.jar:na]
at okhttp3.internal.http.RetryAndFollowUpInterceptor.followUpRequest(RetryAndFollowUpInterceptor.java:230) ~[okhttp-3.14.9.jar:na]
at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:119) ~[okhttp-3.14.9.jar:na]
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) ~[okhttp-3.14.9.jar:na]
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) ~[okhttp-3.14.9.jar:na]
at com.burgstaller.okhttp.AuthenticationCacheInterceptor.intercept(AuthenticationCacheInterceptor.java:49) ~[okhttp-digest-2.5.jar:na]
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:142) ~[okhttp-3.14.9.jar:na]
at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:117) ~[okhttp-3.14.9.jar:na]
at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:229) ~[okhttp-3.14.9.jar:na]
at okhttp3.RealCall$AsyncCall.execute(RealCall.java:172) ~[okhttp-3.14.9.jar:na]
... 4 common frames omitted
do you have any tip what can be the problem?
one important note that this code in a container within a spring boot service...
The API that
okhttp-digest
is using is a public api and AFAICT its being used correctly. Also, you are the first one to report such an issue, therefore, I somehow doubt that okhttp digest is to blame.
@rburgst so the above statement is not so true:-)
as it can be seen from my trace it's in
DigestAuthenticator.java:248
which line is:
final String uri = RequestLine.INSTANCE.requestPath(request.url());
where the INSTANCE is from:
import okhttp3.internal.http.RequestLine;
and i assume internal not really public api...
IMHO simple delete the INSTANCE from the code solve the problem....and a new release would be nice:-)
Hi, their source is kotlin, and RequestLine
is an object
, this translates into RequestLine.INSTANCE
in java.
thanks!
It worked fine for a long time until I switched to io.github.rburgst:okhttp-digest:2.5 from jcenter recently.
The Android app crashes with the following error despite the code is in a try-catch block.