Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android | Get OkHTTP Library version at runtime

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

  1. com.squareup.okhttp.internal.Version
  2. 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

  1. Class.forName("com.android.okhttp.internal.Version") -> java.lang.ClassNotFoundException
  2. Class.forName("com.squareup.okhttp.internal.Version") -> java.lang.ClassNotFoundException
  3. Class.forName("okhttp3.internal.Version") -> java.lang.ClassNotFoundException
  4. Class.forName("com.android.okhttp.internal.http.HttpURLConnectionImpl") -> success

Can 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

like image 424
CAMOBAP Avatar asked Mar 24 '16 08:03

CAMOBAP


People also ask

What is OkHttp library in Android?

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.

What is the difference between retrofit and OkHttp?

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.

Is OkHttp fast?

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.


1 Answers

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:

  • every class is treated the same way - > as equals ( no versioning - u can only check magic minor major number - java compiler version from class)
  • manifest of /system/framework/okhttp.jar doesn't contain version properties

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

like image 131
ceph3us Avatar answered Oct 13 '22 01:10

ceph3us