Skip to main content

Managing Android emulator in .NET

Automated coded UI testing become very popular in the past few years. Its allow developers to create tests which are executed directly on UI level and simulate user actions. At the same time HTML5 become a standard for creating universal modern applications which can be hosts in a native browser controls.

New model of creating applications brings a new challenges in the testing fields that's why in this post I want to present my solution (it takes me almost two days to get this working!) which is first step in the process of creation an end-to-end test automation for mobile applications. My solution is prototype of a .NET console application which can be use to control Android emulator and simulate user standard operation like installing app, typing and rotating. This prototype can be use as 'emulator manager' which controls device emulator on which tests are performed - for example by using  Selenium.

As initial requirements to run the project:
1) Install the latest Java build :(  (sorry .NET geeks but it`s required)
2) Install Android SDK

Now we have all environment in place so we can create our emulator device. To do that we need to use Android Virtual Devices Manager tool which is located in the '..\\sdk\tools\' path inside Android SDK folder. To run this tool we need start cmd, navigate to the SDK tools folder and type 'android avd'. Now we can create a new emulator by specifying all setting we need - in the picture below I presented settings for my AVD called 'nexus'. To make sure that all configuration if correct we should run out AVD by calling emulator.exe  from  '..\\sdk\tools\'  for example 'emulator -avd nexus' - this cause our emulator start running and first run might take some time so be patient.

Picture 1. Configuration of a new  device emulator.
Now its time to back to the C# code a present solution which can manage Android emulator through .NET code. Basically solution based on the simple console application which is calling externals console applications:

  • emulator.exe - console application which allow to start device emulator by device name with specific parameters.
  • adb.exe - console application which allow communication with device emulator; allow to run shell mode directly on the emulator.
Picture 2. Application architecture.

There is two very important parts inside this solution. First one is the IEmulator interface which expose all functions which are currently supported by the program. The idea is that this solution can be extended to all main three mobile platforms (iOS, Android, Windows) and the IEmulator interface will remain common an contract for all of them so just implementation of each emulator will be different (now only AndroidEmulator class is implemented). IEmulator interface implementation is as follow:

Code Snippet
  1. /// <summary>
  2. /// Expose all emulator tasks.
  3. /// </summary>
  4. public interface IEmulator
  5. {
  6.     /// <summary>
  7.     /// Starts the emulator.
  8.     /// </summary>
  9.     /// <returns>Value which determines emulator is ready for use.</returns>
  10.     bool Initialize();
  11.  
  12.     /// <summary>
  13.     /// Enable shell mode on the emulator.
  14.     /// </summary>
  15.     void StartShell();
  16.  
  17.     /// <summary>
  18.     /// Checks the emulator is running.
  19.     /// </summary>
  20.     bool IsRunning();
  21.  
  22.     /// <summary>
  23.     /// Install app on the emulator.
  24.     /// </summary>
  25.     /// <param name="packagePath">Path to the apk package to intsall.</param>
  26.     /// <returns>True if application installed correctly.</returns>
  27.     bool InstallApp(string packagePath = null);
  28.  
  29.     /// <summary>
  30.     /// Uninstall specyfic package from emulator.
  31.     /// </summary>
  32.     /// <param name="packageName">Specyfic package name to uninstall.</param>
  33.     void UninstallApp(string packageName = null);
  34.  
  35.     /// <summary>
  36.     /// Run monkey on package.
  37.     /// </summary>
  38.     /// <param name="activitiesCount">Action count.</param>
  39.     void RunMonkey(int activitiesCount = 500);
  40.  
  41.     /// <summary>
  42.     /// Simulating keypress events on emulator.
  43.     /// </summary>
  44.     /// <param name="codes">Hardware codes array.</param>
  45.     void TypeAsHardwareInput(int[] codes);
  46.  
  47.     /// <summary>
  48.     /// Change orientation of the emulator.
  49.     /// </summary>
  50.     void ChangeOrientation();
  51. }

As you can see here, not all options are implemented but the most important functions are on place so let`s have a quick look on its:
  • Initialize: function which starts device emulator by calling emulator.exe as separate process and pass AVD name from the configuration file.
  • StartShell:  using 'adb shell' command from adb.exe tool in separated process to start shell mode on the currently running AVD. Process which hosts shell will remain active until application close.
  • IsRunning: function which call  'adb devices'  command  in separated process from adb.exe tool to check if AVD  is currently running.
  • InstallApp: install APK file from specific path in local PC by calling 'adb wait-for-device install <apk full-path>' command from adb.exe as separated process. Additional wait-for-device command ensure that emulator is ready to install app. 
  • UninstalApp: uninstall app from shell level by using package name (ex. com.android.tools.sdkcontroller stored in AndroidInstalledAppName App.config)
  • RunMonkey: from shell mode run monkey random actions on the installed package by executing N (activitiesCount) random activities.
  • TypeAsHardwareInput: allow to use simulate hardware keys to input any supported input. Under the hood its calling shell command 'input keyevent <key_code>' with key code specified for the platform. Key-codes list is available here.
Last function I want to describe in not supported by the Android SDK and from testing point of view it`s crucial -I mean here changing emulator orientation during the run-time. I spent a lot of time reading and investigating any potential possibility of changing emulator orientation by no of solutions I`ve found  was working for me. There is only one official way to switch emulator orientation - by pressing CTRL+F11, and I`m implemented it. Source code for this using  an external library called InuputSimulator (thank you Michael) to simulate keystroke. Additionally I used emulator process  name to find exact process and get focus on their main window before simulate keystroke.   

Code Snippet
  1. [DllImport("user32.dll")]
  2.         static extern bool SetForegroundWindow(IntPtr hWnd);
  3.  
  4.         /// <summary>
  5.         /// Change orientation of the emulator.
  6.         /// </summary>
  7.         public void ChangeOrientation()
  8.         {
  9.             var emulatorProcess = Process.GetProcessesByName("emulator-arm");
  10.             if (emulatorProcess.Count() == 0)
  11.             {
  12.                 throw new InvalidOperationException("Unable to find emulator process.");
  13.             }
  14.  
  15.             BringToFront(emulatorProcess[0]);
  16.             WindowsInput.InputSimulator.SimulateModifiedKeyStroke(WindowsInput.VirtualKeyCode.CONTROL, WindowsInput.VirtualKeyCode.F11);
  17.         }
  18.         
  19.         /// <summary>
  20.         /// Set focus on the process.
  21.         /// </summary>
  22.         /// <param name="pTemp">Process to be focused.</param>
  23.         private void BringToFront(Process pTemp)
  24.         {
  25.             SetForegroundWindow(pTemp.MainWindowHandle);
  26.         }

Now when all functions are on place we can call them in logical order.

Code Snippet
  1. class Program
  2. {
  3.     static void Main(string[] args)
  4.     {
  5.         var emulator = EmulatorFactory.GetEmulator(EmulatorType.Android);
  6.  
  7.         emulator.Initialize();
  8.  
  9.         emulator.InstallApp();
  10.  
  11.         emulator.StartShell();
  12.  
  13.         emulator.ChangeOrientation();
  14.         emulator.ChangeOrientation();
  15.  
  16.         emulator.RunMonkey();
  17.         emulator.UnistallApp();
  18.     }
  19. }

I can`t guarantee but I hope that soon I will add next emulator - keep your fingers crossed!

Whole source code of the project is available here.

Thank you

More info:

Popular posts from this blog

Multithread processing of the SqlDataReader - Producer/Consumer design pattern

In today post I want to describe how to optimize usage of a ADO.NET SqlDataReader class by using multi-threading. To present that lets me introduce a problem that I will try to solve.  Scenario : In a project we decided to move all data from a multiple databases to one data warehouse. It will be a good few terabytes of data or even more. Data transfer will be done by using a custom importer program. Problem : After implementing a database agnostic logic of generating and executing a query I realized that I can retrieve data from source databases faster that I can upload them to big data store through HTTP client -importer program. In other words, data reader is capable of reading data faster then I can process it an upload to my big data lake. Solution : As a solution for solving this problem I would like to propose one of a multi-thread design pattern called Producer/Consumer . In general this pattern consists of a two main classes where: Producer class is respons

Full-Text Search with PDF in Microsoft SQL Server

Last week I get interesting task to develop. The task was to search input text in PDF file stored in database as FileStream. The task implementation took me some time so I decided to share it with other developers. Here we are going to use SQL Server 2008 R2 (x64 Developers Edition), external driver from Adobe, Full-Text Search technology and FileStream technology.Because this sems a little bit comlicated let`s make this topic clear and do it step by step. 1) Enable FileStream - this part is pretty easy, just check wheter You already have enabled filestream on Your SQL Server instance - if no simply enable it as in the picture below. Picture 1. Enable filestream in SQL Server instance. 2) Create SQL table to store files  - mainly ther will be PDF file stored but some others is also be allright. Out table DocumentFile will be created in dbo schema and contain one column primary key with default value as sequential GUID. Important this is out table contains FileStream

MVC 3 Reload PartialView by using jQuery and AJAX

Sometimes it`s easier to reaload only part of the website witout reloading whole page. Thanks to AJAX technology such aproach is possible and easy to code. Let`s begin. Firstly we need to configure our environment so we must have a Visual Studio with MVC 3  Razor isntalled on it. Razor can be obtained from here . After installation process completed , the second step is to set up a new WebStie project (Picture 1.) Picture 1. After you confirm Your project type choise, next window starts. On it You should select the second web project type (with Forms autentication method)  and than choose RAZOR form dropdown (Picture 2.). Picture 2. Now You new web solution contains several folders and files by default. Their description is not a point of this article so allow myself to continue. Next step is to create a simple model for our PartialView. As an example I  created a simple _UserModel.cs in Models folder. The source code for this model is:  public class _UserModel     {