#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!
#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.
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!