Tuesday, April 2, 2024

Eclipse ADT plugin with D8 dexer

If still developing with Eclipse for Android using Google ADT plugin you may encounter the error below when dexing some newer libraries:

processing archive U:\Workspaces\AndroidX Browser\github\android-androidx-browser\libs\androidx-browser.jar...
processing META-INF/androidx.browser_browser.version...
processing androidx/browser/trusted/splashscreens/SplashScreenVersion.class...
... Uncaught translation error: com.android.dx.cf.code.SimException: ERROR in androidx.browser.customtabs.CustomTabsService$1.newSessionInternal:(Landroid/support/customtabs/ICustomTabsCallback;Landroid/app/PendingIntent;)Z: invalid opcode ba - invokedynamic requires --min-sdk-version >= 26 (currently 13) Uncaught translation error: com.android.dx.cf.code.SimException: ERROR in androidx.browser.trusted.ConnectionHolder.getServiceWrapper:()Lcom/google/common/util/concurrent/ListenableFuture;: invalid opcode ba - invokedynamic requires --min-sdk-version >= 26 (currently 13) Uncaught translation error: com.android.dx.cf.code.SimException: ERROR in androidx.browser.trusted.TokenContents.createToken:(Ljava/lang/String;Ljava/util/List;)[B: invalid opcode ba - invokedynamic requires --min-sdk-version >= 26 (currently 13) Uncaught translation error: com.android.dx.cf.code.SimException: ERROR in androidx.browser.trusted.TrustedWebActivityServiceConnectionPool.connect:(Landroid/net/Uri;Ljava/util/Set;Ljava/util/concurrent/Executor;)Lcom/google/common/util/concurrent/ListenableFuture;: invalid opcode ba - invokedynamic requires --min-sdk-version >= 26 (currently 13)

Let's try to understand how Google ADT plugin works:
DexWrapper.java (ADT plugin) looks for ANDROID_SDK\build-tools\xx.yy.zz\lib\dx.jar and loads it, then calls run(Arguments) method in com.android.dx.command.dexer.Main through reflection.

Since those classes do not exist in newer D8 dexer you won't be able to use directly ADP with D8.

Unknown error: Unable to build: the file dx.jar was not loaded from the SDK folder!

But what if we create an adapter that sits in between and knows how to receive the dx.jar call and transfer it to d8.jar?
And that is exactly what dandar3/android-dx-d8-adapter does. 

1. Install `build-tools` version 33.0.3, that will come with D8 (and without DX) and is the last version that is built with Java 8 (runtime version used to run Eclipse and JDT):

> tools\bin\sdkmanager "build-tools;33.0.3"
done
> dir build-tools\33.0.3\lib\d*.jar
03.04.2024 00:03 8.190.549 d8.jar

2. Clone dandar3/android-dx-d8-adapter and build from sources (see README.md) or download the latest build from Releases page (right side).

3. Save as `dx.jar` next to `d8.jar` in build-tools\33.0.0\lib\

4. Restart Eclipse.

5. Rebuild your project, look in `Console` > `Android` view:

Android DX to D8 adapter
Version 1.0 (Feb 2023
https://github.com/dandar3/android-dx-d8-adapter

DX called with:
 verbose    = false
 forceJumbo = false
 jarOutput  = true
 outName    = U:\Workspaces\Android\[...]\demo\bin\dexedLibs\androidx-arch-core-common-95b383e1e508bb35b6c34b9ff46ba8ce.jar
 fileNames  = [U:\Workspaces\Android\[...]\android-androidx-arch-core-common\bin\androidx-arch-core-common.jar]

D8 called with:
  jar       = U:\Android\android-sdk-eclipse\build-tools\33.0.3\lib\d8.jar
  arguments = [--output, U:\Workspaces\Android\Eclipse [ADT]\__TESTS\AndroidX Browser\demo\bin\dexedLibs\androidx-arch-core-common-95b383e1e508bb35b6c34b9ff46ba8ce.jar, U:\Workspaces\Android\Eclipse [ADT]\__TESTS\AndroidX Browser\github\android-androidx-arch-core-common\bin\androidx-arch-core-common.jar]
  elapsed  = 00:00:00.794

Thanks to iRootS and Bolfish.