Skip to content

Animalsniffer signatures for Android APIs with support for desugaring

License

Notifications You must be signed in to change notification settings

open-toast/gummy-bears

Repository files navigation

Gummy Bears

Github Actions Maven Central

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.

Background

Animal Sniffer

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.

Android

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.

Gummy Bears

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.

Core library desugaring

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.

How to use

Specify the latest version com.toasttab.android:gummy-bears-api-${api} as the set of signatures for Animal Sniffer.

Gradle

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')
}

Gradle Kotlin DSL

plugins {
    id("ru.vyarus.animalsniffer") version "1.7.1"
}

dependencies {
    add("signature", "com.toasttab.android:gummy-bears-api-24:0.8.0@signature")
}

Maven

<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>

Expediter

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.

License

This project is licensed under the Apache 2 License - see the LICENSE file for details.

Acknowledgments

👍 to the authors of Animal Sniffer, gradle-animalsniffer-plugin, R8 and D8.