Search code examples
javaandroidgradleandroid-version

How does sourceCompatibility and targetCompatibility impact number of supported devices?


What I understand so far

minSdkVersion 21 - means that the device must have at least Android API level 21 or higher installed in order to install the app. (This value should be set as low as possible to help reach the largest number of users while still maintaining all critical app functionality.)

targetSdkVersion 26 - means that it was developed for the Android API version 26, allowing the device to determine if compatibility mode or optional features should be enabled. (This value should be set as high as possible to allow developers to access new features and manage any deprecated API calls.)

What I am confused about

But what about the configurations sourceCompatibility and targetCompatibility? I have been receiving conflicting information about which JDK version should be used.

An example of this is seen in the project structure settings in Android Studio, where using the default JDK version that comes with Android Studio (version 1.8) is recommended by the tooltips.

enter image description here

However, when I read other online sources such as the following:

It appears that Android primarily runs on Java version 1.7, with only limited support for some features of version 1.8. This suggests that using version 1.7 would be the more logical choice.

Questions that I have

Question 1) Which JDK version, 1.7 or 1.8, should I choose for maximum compatibility with both new and old Android devices? Does this configuration even make a difference in terms of reachable market size?

Question 2) Is the choice of sourceCompatibility and targetCompatibility (and JDK version) only relevant during the compilation of .java files to .class files and have no effect once the Java bytecode is generated? Or does the chosen JDK version affect the end user's experience, for example if their device's JVM can't interpret version 1.8 bytecode, causing the app to crash during runtime?

Question 3) What are the consequences of setting minSdkVersion to a low value (e.g. 10) and sourceCompatibility and targetCompatibility to a high value (e.g. 1.8)? Can I trust that Android Studio will detect all compatibility issues and if it builds an APK, it will function properly? Or can it still be built and installed on devices with API level >= 10, but crash at runtime if the device's JVM can't handle version 1.8?


Solution

  • The android toolchain does some extra steps before the code is run on your device:

    .java -> .class -> .class (desugared) -> .dex

    This is described here: https://developer.android.com/studio/write/java8-support

    The desugaring step is responsible for turning your modern bytecode into something that works on older VMs.

    How backwards compatible the desugaring makes your code depends on the minSdkVersion. If your project makes a combination of sourceCompatibility/targetCompatibility and minSdkVersion that isn't possible, the compiler will tell you.

    This also goes for byte code from 3rd party libraries. Errors look like this:

    Error: Static interface methods are only supported starting with Android N (--min-api 24): okhttp3.Request
    

    (this specific problem came from using 1.7 source compatibility with okhttp3 4.0.1 and went away by using target 1.8)