If you’re an Android developer, there might come a time when you will require a virtual device to test your app on different device setups.

Although you can create an Android emulator quite effortlessly through Android Studio’s graphical user interface, you might also like to create one utilizing the macOS command line interface, Terminal — and this article will tell you exactly how to do that!

Work at Wrike

Step 1: Install Java

Before proceeding, make sure you have Java installed on your system. If you don’t, you can install it using Homebrew by running the following command:

brew install openjdk@11

Step 2: Install the SDK

You can install the SDK using Android Studio by following these instructions.

Step 3: Install Android SDK command line tools

The command line tools can be downloaded from the Android developer website under the “Command line tools only” section.

After downloading the archive, extract its contents and transfer them to the $ANDROID_HOME directory. If the cmdline-tools directory does not contain a latest folder, create one manually and transfer all of its contents to prevent the occurrence of a “Could not determine SDK root” error.

android 1

Step 4: Add to your PATH

You need to add the ANDROID_HOME and cmdline-tools environment variables to your PATH. You can do this by adding the following code to the ~/.zshrc file or any configuration file you use:

export ANDROID_HOME=~/Library/Android/sdk
export PATH=$ANDROID_HOME/emulator/:$PATH
export PATH=$ANDROID_HOME/platform-tools/:$PATH
export PATH=$ANDROID_HOME/cmdline-tools/latest/bin/:$PATH

Step 5: Create an emulator properties template

In order to create a virtual device with specific configuration properties (e.g., screen resolution, RAM, virtual memory size, etc.), you must specify these parameters when creating the emulator. To streamline this process, let’s create a template for these properties.

To obtain the template, you can create a virtual device with the required properties via Android Studio and then copy its configuration. You can then name the created emulator “Test Pixel 2,” for example.

To print the configuration, enter the following command:

cat $HOME/.android/avd/Test_Pixel_2.avd/config.ini

After copying the created emulator properties, save them as a template by creating a new file named pixel_2_API_33_config. Then, you can append the copied configuration to the newly created template using the following command:

touch ~/pixel_2_API_33_config
cat $HOME/.android/avd/Test_Pixel_2.avd/config.ini >> ~/pixel_2_API_33_config

Here is a config example:

AvdId=Test_Pixel_2_API_33
PlayStore.enabled=true
abi.type=arm64-v8a
avd.ini.displayname=Test Pixel 2 API 33
avd.ini.encoding=UTF-8
disk.dataPartition.size=6G
fastboot.chosenSnapshotFile=
fastboot.forceChosenSnapshotBoot=no
fastboot.forceColdBoot=yes
fastboot.forceFastBoot=no
hw.accelerometer=yes
hw.arc=false
hw.audioInput=yes
hw.battery=yes
hw.camera.back=virtualscene
hw.camera.front=emulated
hw.cpu.arch=arm64
hw.cpu.ncore=4
hw.dPad=no
hw.device.hash2=MD5:55acbc835978f326788ed66a5cd4c9a7
hw.device.manufacturer=Google
hw.device.name=pixel_2
hw.gps=yes
hw.gpu.enabled=yes
hw.gpu.mode=auto
hw.initialOrientation=Portrait
hw.keyboard=yes
hw.lcd.density=420
hw.lcd.height=1920
hw.lcd.width=1080
hw.mainKeys=no
hw.ramSize=1536
hw.sdCard=yes
hw.sensors.orientation=yes
hw.sensors.proximity=yes
hw.trackBall=no
image.sysdir.1=system-images/android-33-ext5/google_apis_playstore/arm64-v8a/
runtime.network.latency=none
runtime.network.speed=full
sdcard.path=$HOME/.android/avd/Test_Pixel_2_API_33.avd/sdcard.img
sdcard.size=512 MB
showDeviceFrame=no
skin.dynamic=yes
skin.name=1080x1920
skin.path=_no_skin
skin.path.backup=_no_skin
tag.display=Google Play
tag.id=google_apis_playstore
vm.heapSize=228

By the way, you should make sure to change the AvdId, avd.ini.displayname, and sdcard.path parameters to your desired values.

Step 6: Get a list of available system images

You can get a list of available system images by running the following command:

cd $ANDROID_HOME/tools/bin
sdkmanager --list

Choose an emulator image from the list. In our case, we will choose system-images;android-33-ext5;google_apis_playstore;arm64-v8a.

Step 7: Install the chosen image

Install the chosen image by running the following command:

cd $ANDROID_HOME/tools/bin
yes | sdkmanager --install "system-images;android-33-ext5;google_apis_playstore;arm64-v8a"
yes | sdkmanager --licenses

Step 8: Create the emulator

Here’s how you’ll create the emulator:

name=Test_Pixel_2_API_33
cd $ANDROID_HOME/tools/bin
echo no | avdmanager create avd --force --name $name --abi arm64-v8a --package 'system-images;android-33-ext5;google_apis_playstore;arm64-v8a'

Step 9: Change the emulator configuration

Change the emulator configuration by replacing the properties from the template with the emulator config file, as shown below:

cat ~/pixel_2_API_33_config >> $HOME/.android/avd/$name.avd/config.ini

Step 10: Verify the created emulator

In order to verify that the created emulator is displayed in the emulator list, run the following command:

cd $ANDROID_HOME/emulator
./emulator -list-avds

Step 11: Run the emulator

Use the given name from the previous step to run the created emulator via the following command:

cd $ANDROID_HOME/emulator;
nohup ./emulator -avd Test_Pixel_2_API_33 -no-snapshot -no-boot-anim -wipe-data &

Pro tip: Add & to the end of the code to run the process in the background.

You can also run all the created emulators like so:

cd $ANDROID_HOME/emulator; 
./emulator -list-avds | cut -f1 | while read line 
do 
nohup ./emulator -avd $line -no-snapshot -no-boot-anim -wipe-data & 
sleep 20 
done

Usage example

To illustrate how our emulator can be used, I’ll show you the code that I utilized to run a build on a specific emulator. The code terminates any existing emulators, creates a new emulator instance, does some work, and ultimately removes the emulator. Check it out:

# Kill all running emulators
adb devices | grep emulator | cut -f1 | while read line; do adb -s $line emu kill; done
# Install the emulator system image if not
cd $ANDROID_HOME/tools/bin
sdk="system-images;android-33;google_apis_playstore;arm64-v8a"
installedImage=$(sdkmanager --list_installed | grep -o $sdk)
if [[ $installedImage = $sdk ]]; then 
echo "The required SDK is already installed"; 
else 
yes | sdkmanager --install $sdk
yes | sdkmanager --licenses

fi

name=Test_Pixel_2_API_33
cd $ANDROID_HOME/tools/bin
echo no | avdmanager create avd --force --name $name --abi arm64-v8a --package $sdk

sysDir=$(cat $HOME/.android/avd/$name.avd/config.ini | grep "image.sysdir.1=")

# Edit the created emulator config 
tee $HOME/.android/avd/$name.avd/config.ini END
AvdId=$name
PlayStore.enabled=true
abi.type=arm64-v8a
avd.ini.displayname=$name
avd.ini.encoding=UTF-8
disk.dataPartition.size=6G
fastboot.chosenSnapshotFile=
fastboot.forceChosenSnapshotBoot=no
fastboot.forceColdBoot=yes
fastboot.forceFastBoot=no
hw.accelerometer=yes
hw.arc=false
hw.audioInput=yes
hw.battery=yes
hw.camera.back=virtualscene
hw.camera.front=emulated
hw.cpu.arch=arm64
hw.cpu.ncore=4
hw.dPad=no
hw.device.hash2=MD5:55acbc835978f326788ed66a5cd4c9a7
hw.device.manufacturer=Google
hw.device.name=pixel_2
hw.gps=yes
hw.gpu.enabled=yes
hw.gpu.mode=auto
hw.initialOrientation=Portrait
hw.keyboard=yes
hw.lcd.density=420
hw.lcd.height=1920
hw.lcd.width=1080
hw.mainKeys=no
hw.ramSize=1536
hw.sdCard=yes
hw.sensors.orientation=yes
hw.sensors.proximity=yes
hw.trackBall=no
$sysDir
runtime.network.latency=none
runtime.network.speed=full
sdcard.path=$HOME/.android/avd/$name.avd/sdcard.img
sdcard.size=512 MB
showDeviceFrame=no
skin.dynamic=yes
skin.name=1080x1920
skin.path=_no_skin
skin.path.backup=_no_skin
tag.display=Google Play
tag.id=google_apis_playstore
vm.heapSize=228
END
cd $ANDROID_HOME/emulator
./emulator -list-avds

cd $ANDROID_HOME/emulator;
nohup ./emulator -avd $name -no-snapshot -no-boot-anim -wipe-data & 
sleep 40

# Do
# Some
# Code
# Kill and delete the created emulator
adb devices
adb devices | grep emulator | cut -f1 | while read line; do adb -s $line emu kill && sleep 10; done

avdmanager delete avd -n $name

In conclusion

To sum up, generating a new Android emulator via Terminal is a relatively straightforward task. It may appear to have a lot of steps, but trust me: Using Terminal to create emulators offers greater flexibility and control than using Android Studio’s graphical user interface does. Moreover, it can also be a lifesaver if you need to perform this task on CI. Good luck!

This article was written by a Wriker, in Wrike. See what it’s like to work with us and what career development opportunities we offer here.

Also, hear from our founder, Andrew Filev, about Wrike’s culture and values, the ways we work and appreciate Wrikers, and more here.

Work at Wrike