Recently I analyzed crash reports form my app and found several stack traces which points to okhttp
My app doesn't depend on okhttp
explicitly.
AFAIK okhttp
version depends on Android OS version, and okhttp
library by itself placed on device
To help with troubleshooting I decided to log okhttp
library version, and looks like I found several useful classes for this
com.squareup.okhttp.internal.Version
okhttp3.internal.Version
Just to make sure that I didn't mistake I took com.android.okhttp.internal.http.HttpURLConnectionImpl
class form stack-trace and tried to Class.forName
it - success
Also I noticed that com.squareup.okhttp
transformed to com.android.okhttp
looks like at build-time, so totally I tried such variants
Class.forName("com.android.okhttp.internal.Version")
-> java.lang.ClassNotFoundException
Class.forName("com.squareup.okhttp.internal.Version")
-> java.lang.ClassNotFoundException
Class.forName("okhttp3.internal.Version")
-> java.lang.ClassNotFoundException
Class.forName("com.android.okhttp.internal.http.HttpURLConnectionImpl")
-> successCan anyone explain why? What I missed?
Update
I have pulled okhttp.jar from my device adb pull /system/framework/okhttp.jar
but it contains MANIFEST.MF
only
OkHttp is a third-party library developed by Square for sending and receive HTTP-based network requests. It is built on top of the Okio library, which tries to be more efficient about reading and writing data than the standard Java I/O libraries by creating a shared memory pool.
OkHttp is a pure HTTP/SPDY client responsible for any low-level network operations, caching, requests and responses manipulation. In contrast, Retrofit is a high-level REST abstraction build on top of OkHttp. Retrofit is strongly coupled with OkHttp and makes intensive use of it.
Results show that OkHttp achieves slightly better performance when compared with HttpURLConnection for transfers of larger files, by transferring the same file almost 100ms faster on a smartphone and 500ms faster in the emulator.
from 4.xx google is using okhttp part of squareup
/**
* This implementation uses HttpEngine to send requests and receive responses. This class may use
* multiple HttpEngines to follow redirects, authentication retries, etc. to retrieve the final
* response body.
*
* <h3>What does 'connected' mean?</h3> This class inherits a {@code connected} field from the
* superclass. That field is <strong>not</strong> used to indicate whether this URLConnection is
* currently connected. Instead, it indicates whether a connection has ever been attempted. Once a
* connection has been attempted, certain properties (request header fields, request method, etc.)
* are immutable.
*/
public class HttpURLConnectionImpl extends HttpURLConnection {
private String defaultUserAgent() {
String agent = System.getProperty("http.agent");
return agent != null ? Util.toHumanReadableAscii(agent) : Version.userAgent();
}
https://github.com/square/okhttp/blob/master/okhttp-urlconnection/src/main/java/okhttp3/internal/huc/HttpURLConnectionImpl.java
http://square.github.io/okhttp/
everything depends on device - what os version u using because api is evolving, u can use reflections but u need know what field is on specific api
see https://github.com/square/okhttp/blob/master/CHANGELOG.md
to compare diffrent api versions use: https://android.googlesource.com/platform/external/okhttp/
u can try at the beginning
System.getProperty("http.agent");
edit:
via reflections
HttpURLConnection connection = (HttpURLConnection) new URL("http://google.com")
.openConnection();
Method method = connection.getClass().getDeclaredMethod("defaultUserAgent");
method.setAccessible(true);
String okEngineVersion = (String) method.invoke(connection, new Object[]{});
same as
String okEngineVersion = System.getProperty("http.agent");
and if u want to bother:
if u want okhttp.internal.Version class then:
File file = new File("/system/framework/okhttp.jar");
// using javaxt-core lib
Jar jar = new Jar(file);
jar.getVersion();
// load dex
DexFile dexfile = DexFile.loadDex(file.getAbsolutePath(),
File.createTempFile("opt", "dex", _context.getCacheDir()).getPath(), 0);
Enumeration<String> dexEntries = dexfile.entries();
ClassLoader systemClassLoader = DexClassLoader.getSystemClassLoader();
while (dexEntries.hasMoreElements()) {
String className = dexEntries.nextElement();
Class<?> aClass = systemClassLoader.loadClass(className);
}
conclusion: If you want to avoid crash of app from library changes delivery own version of library and load classes on the fly or compile with apk
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With