Open Source

Android (native) targets

Requirements

All the requirements for running Android JVM targets apply.

In addition, it is highly recommended to use a X64 host machine, especially to be able to test all four architectures (x86, x86_64, armeabi-v7a, arm64-v8a). The plugin might work on ARM hosts but this has not been tested, and anyway ARM emulators would not be able to run non-ARM binaries, while x86-based hosts can run ARM code through binary translation.

How it works

Running Android Native tests is a multi-step process and between these steps, the plugin applies workarounds to known issues to make testing as smooth and fast as possible.

  1. A K/N test executable is built. These executables are built by the Kotlin compiler with the -tr option and automatically run all test suites and print logs to Android logcat.
  2. K/N test executables are currently broken. The plugin workarounds this issue by treating them as shared libraries and loading them at runtime using dlopen() and passing appropriate arguments to trick the Kotlin runtime launcher.
  3. The plugin looks for a connected device (real device or emulator) that is able to run the architecture.
  4. If not found, the plugin looks for existing AVDs and starts the first one that would work.
  5. If not found, the plugin downloads the needed packages from sdkmanager, creates an AVD and starts it.
  6. The runner executable is executed using adb shell. This makes a huge difference with respect to e.g. JNI-based tests, as we don't have to wait for the emulator to be completely booted and care about all details (unlock, avoid welcome screens, animations...) that make testing hard in a JVM process.
  7. Interesting logcat logs are printed to the host stdout.

Tasks

⚠️

Use ./gradlew tasks --group='Multiplatform Testing' to list all testing tasks.

The plugin provides three types of tasks:

  • runAllAndroidNativeTests task: runs tests for all androidNative* targets.
  • run<TargetName>Tests tasks: runs tests for the specified target, e.g. runAndroidNativeX86Tests
  • killAndroidEmulators task: kills all currently running emulators. Can be used to cleanup.

Using the runAllAndroidNativeTests tasks is recommended, because it ensures the most efficient emulator installation. This is because emulator images can run multiple architectures (for example: 64bit images might run 32bit binaries, and X86/64 images might run ARM binaries through binary translation). The plugin is aware of this and, if runAllAndroidNativeTests is used, is able to pick up the best emulator for the job, saving time and resources.

This means that the typical command will be:

./gradlew app:runAllAndroidNativeTests app:killAndroidEmulators