Android Emulator in 90 seconds

emulator

#1

#Edit
For now it seems like, the new avdmanager breaks this how-to. Please follow the written below if you are still using emulator as executable to create and use your emulator.

#Summary
The two steps Bitrise.io Cache:Pull and Bitrise.io Cache:Push now helps a lot of users to speed up their build times, and caching emulator snapshots seems to be a good idea as it usually takes couple of minutes to boot up an arm Android emulator.

#What to expect
The last try to speed up android emulator was making it’s booting happen in the background while other steps can run with it paralell. (How to speed up Android emulator heavy workflows) It’s result was a great amount of time saved, in my example from the original 581 seconds I’ve managed to successfully decrease it to 432 seconds. Well, that’s not bad but, let’s try now with some caching!

+------------------------------------------------------------------------------+
|                               bitrise summary                                |
+---+---------------------------------------------------------------+----------+
|   | title                                                         | time (s) |
+---+---------------------------------------------------------------+----------+
| ✓ | cache-pull@0.9.2                                              | 11 sec   |
+---+---------------------------------------------------------------+----------+
| ✓ | script@1.1.3                                                  | 2.20 sec |
+---+---------------------------------------------------------------+----------+
| - | create-android-emulator@1.0.0                                 | 1.14 sec |
+---+---------------------------------------------------------------+----------+
| ✓ | start-android-emulator@1.1.1                                  | 43 sec   |
+---+---------------------------------------------------------------+----------+
| - | script@1.1.3                                                  | 0.73 sec |
+---+---------------------------------------------------------------+----------+
| - | cache-push@0.9.4                                              | 1.33 sec |
+---+---------------------------------------------------------------+----------+
| - | start-android-emulator@1.1.1                                  | 0.76 sec |
+---+---------------------------------------------------------------+----------+
| ✓ | git-clone@3.4.2                                               | 5.02 sec |
+---+---------------------------------------------------------------+----------+
| ✓ | nuget-restore@1.0.3                                           | 23 sec   |
+---+---------------------------------------------------------------+----------+
| ✓ | script@1.1.3                                                  | 183 sec  |
+---+---------------------------------------------------------------+----------+
| ✓ | xamarin-archive@1.3.2                                         | 23 sec   |
+---+---------------------------------------------------------------+----------+
| ✓ | wait-for-android-emulator@0.9.0                               | 11 sec   |
+---+---------------------------------------------------------------+----------+
| ✓ | calabash-android-uitest                                       | 98 sec   |
+---+---------------------------------------------------------------+----------+
| Total runtime: 403 sec                                                       |
+------------------------------------------------------------------------------+

It is about 30 seconds less again! :tada:

#More profit
The workflow in (How to speed up Android emulator heavy workflows) works very well, but only if your workflow average full build time is more than 4-5 minutes, because then there is enought time in the background for the emulator to be able to boot. With caching it doesn’t matter how long your workflow will run, android emulator’s boot time always will be the same.

#Workflow structure for caching
I’ve created an environment variable ANDROID_EMULATOR_NAME set it’s value to cachedEmulator and I used it in all the steps, to be easy to change emulator name later on.

Steps for example:

  • Bitrise.io Cache:pull
  • Script to check if avd exists in /Users/vagrant/.android/avd/$ANDROID_EMULATOR_NAME
  • If not exists, Create Android Emulator with an exra option: --snapshot
  • Start Android Emulator
  • _If not exists,_Script: sleep some (for ex.: 10 secs, let emulator to boot fully), then kill emulator (this is when snapshot images are witten)
  • If not exists, Bitrise.io Cache:push
  • If not exists, Start Android Emulator again, to have a running device after the first cache run also

After the first cache the script which checks if the emulator exists, won’t export an environment variable, so the steps starting with If not exists won’t run anymore. This way you always will have a fresh, empty and clean android emulator image. :smirk:

An example workflow (Best if you keep it separated workflow, and add it to your own workflow’s run_before):

---
format_version: 1.3.1
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
trigger_map:
- push_branch: "*"
  workflow: YourWorkflow
- pull_request_source_branch: "*"
  workflow: YourWorkflow
workflows:
  YourWorkflow:
    steps:
    - git-clone@3.4.2: {}
    before_run:
    - _startemulator
    after_run: 
  _startemulator:
    steps:
    - cache-pull@0.9.2:
        inputs:
        - workdir: "/Users/vagrant/.android/avd/"
    - script@1.1.3:
        inputs:
        - content: |-
            #!/bin/bash
            # fail if any commands fails
            set -e
            # debug log
            set -x

            if [ ! -f "/Users/vagrant/.android/avd/$ANDROID_EMULATOR_NAME.ini" ]; then
               envman add --key ANDROID_EMULATOR_EXISTS --value "false"
            fi
    - create-android-emulator@1.0.0:
        run_if: '{{enveq "ANDROID_EMULATOR_EXISTS" "false"}}'
        inputs:
        - name: "$ANDROID_EMULATOR_NAME"
        - options: "--snapshot"
        - custom_hardware_profile_content: ''
    - start-android-emulator@1.1.1:
        inputs:
        - emulator_name: "$ANDROID_EMULATOR_NAME"
    - script@1.1.3:
        run_if: '{{enveq "ANDROID_EMULATOR_EXISTS" "false"}}'
        inputs:
        - content: |-
            #!/bin/bash
            # fail if any commands fails
            set -e
            # debug log
            set -x

            sleep 10
            adb -s $BITRISE_EMULATOR_SERIAL emu kill
    - cache-push@0.9.4:
        run_if: '{{enveq "ANDROID_EMULATOR_EXISTS" "false"}}'
        inputs:
        - cache_paths: |-
            ./${ANDROID_EMULATOR_NAME}.avd/
            ./${ANDROID_EMULATOR_NAME}.ini
        - workdir: "/Users/vagrant/.android/avd/"
    - start-android-emulator@1.1.1:
        run_if: '{{enveq "ANDROID_EMULATOR_EXISTS" "false"}}'
        inputs:
        - emulator_name: "$ANDROID_EMULATOR_NAME"
    before_run: 
    after_run: 
app:
  envs:
  - opts:
      is_expand: true
    ANDROID_EMULATOR_NAME: cachedEmulator

#Warnings
I’ve seen so far…

  • Unexpected crash of the emulator can happen (I’ve read on sites, but didn’t happen in my tests)
  • The first run will take more time (When the emulator images are not cached yet)
  • WARNING: Force to use classic engine to support snapshot.
  • WARNING: Classic qemu does not support SMP. The hw.cpu.ncore option from your config file is ignored.
  • WARNING: opening audio output failed - Seems like audio device won’t be available

Feel free to ask any questions! :wink:


#2

@tamaspapik should we delete this guide? Re: https://github.com/bitrise-steplib/steps-create-android-emulator/issues/18#issuecomment-303428198


#3

This still need further investigation. We should keep it, but I’ll mark now the OP.


#4

Perfect, thank you!


#5

Hello guys, i’m getting this error on my cache-push step:
$ cd /Users/vagrant/.android/avd/
/tmp/bitrise891227701/step_src/step.sh: line 12: cd: /Users/vagrant/.android/avd/: No such file or directory
I made my workflow based on @tamaspapik workflow to open emulator in 90 seconds
Anyone can help me please?


#6

Hello there! Could you please send us the url of this build, so we can check out the logs for some more details?


#7

Hi @fehersanyi-bitrise thanks for answer, here’s my url for this build: /build/32086b7a740af633


#8

Hy there!

there are some issues with these steps, I would recommend you change the stac to the LTS ubuntu one, remove the emulator steps and add a script with this in it:

#!/usr/bin/env bash
# fail if any commands fails
set -e
# debug log
#set -x

cd $ANDROID_HOME/emulator

echo no | avdmanager create avd -n Nexus_5X_API_26 -k "system-images;android-26;google_apis;x86" --force

emulator -avd Nexus_5X_API_26 -no-window -no-audio -debug-init > /dev/null 2>&1 &

echo "Waiting emulator is ready..."

adb wait-for-device shell 'while [[ -z $(getprop sys.boot_completed) ]]; do sleep 1; done; input keyevent 82'

echo "Emulator is ready!"

please get back with the results! :upside_down_face:


Screenshots on Ionic Build & Deploy to iTunes Connect / Google Play
AVD Manager and Wait for Android Emulator