D8 sugar for all of your animal sniffing needs.
This project provides Animal Sniffer signatures that account for desugared APIs for Android 4.4 and above (API level 19+). Read the Background section below if none of this makes sense.
Animal Sniffer checks your project's binary compatibility with a specific version of a java library. At Toast, we use Animal Sniffer to ensure that libraries consumed by our Android apps do not use any APIs unavailable on our oldest supported devices.
Animal Sniffer works by introspecting your project's bytecode and matching it against a set of field and method signatures. Conveniently, standard sets of signatures for all JDKs and Android SDKs are available on Maven Central. Standard signatures are generated by introspecting the classfiles (i.e. android.jar for Android SDK) and recording all public binary interfaces they expose.
The above, however, does not produce an accurate set of signatures for Android. Let's look at Integer.hashCode(int). Per documentation, it was Added in API level 24
. Yet it works perfectly fine on API 19
. Moreover, when targeting Java 8+, the Kotlin compiler will generate calls to this method to compute the hash code of Int
fields in a data class
.
When the APK is assembled, D8 (the Android Dexer) transforms java bytecode into Android (Dalvik/Art) bytecode. As part of that transformation, it rewrites (or desugars) some instructions and API calls. For example, lambdas are desuraged into anonymous classes, try-with-resources
is desugared into a Dalvik-compatible set of instructions that matches the semantics of the regular Java try-with-resources
, and Integer.hashCode(int)
is rewritten into a call to a synthetic class which is then added to the APK by D8.
This article explains desugaring in detail.
This project provides a safe and more accurate set of signatures for Android 4.4-13 (API 19-34). The additional sugary signatures are generated from hand-written stubs. The reference for the stubs is the D8 source code.
This project also provides experimental sets of signatures for APIs available via core library desugaring, including java.time
, ConcurrentHashMap
, etc.
Two versions of core library desugaring signatures are provided: v1, which requires desugar_jdk_libs:1.2.3
or above and is published under the coreLib
classifier, and v2, which requires desugar_jdk_libs:2.0.4
and is published under the coreLib2
classifier. Note that desugar_jdk_libs
version 2
comes in three flavors: minimal, nio, and full. Currently, only the full flavor is supported.
Using signatures with core library desugaring to validate a library effectively implies that all Android projects consuming the library
must have core library desugaring enabled at build time and bring in the appropriate version of desugar_jdk_libs
.
Specify the latest version com.toasttab.android:gummy-bears-api-${api}
as the set of signatures for Animal Sniffer.
plugins {
id 'ru.vyarus.animalsniffer' version '1.7.1'
}
dependencies {
signature('com.toasttab.android:gummy-bears-api-24:0.8.0@signature')
}
With core library desugaring:
dependencies {
signature('com.toasttab.android:gummy-bears-api-24:0.8.0:coreLib@signature')
}
With core library desugaring v2:
dependencies {
signature('com.toasttab.android:gummy-bears-api-24:0.8.0:coreLib2@signature')
}
plugins {
id("ru.vyarus.animalsniffer") version "1.7.1"
}
dependencies {
add("signature", "com.toasttab.android:gummy-bears-api-24:0.8.0@signature")
}
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.23</version>
<configuration>
<signature>
<groupId>com.toasttab.android</groupId>
<artifactId>gummy-bears-api-21</artifactId>
<version>0.8.0</version>
</signature>
</configuration>
</plugin>
As of version 0.6.0, this project also publishes native Expediter type descriptors. Expediter provides a superset of the Animal Sniffer binary compatibility checks and comes with its own Gradle plugin.
This project is licensed under the Apache 2 License - see the LICENSE file for details.
👍 to the authors of Animal Sniffer, gradle-animalsniffer-plugin, R8 and D8.