├── README.md ├── emulators.rb └── emulators.yml /README.md: -------------------------------------------------------------------------------- 1 | # Android Emulator Builder 2 | 3 | Android Emulator Builder is a ruby script designed to quickly install a set of pre-configured emulators of popular Android devices. 4 | 5 | Created emulators match the screen size and pixel density of their target devices based on device information available on Wikipeda. 6 | 7 | - [List of displays by pixel density](http://en.wikipedia.org/wiki/List_of_displays_by_pixel_density) 8 | - [Comparison of Android devices](http://en.wikipedia.org/wiki/Comparison_of_Android_devices) 9 | 10 | Other hardware settings are based on common configuration. The reasoning behind this is to create emulators with tolerable performance and still be reasonably useful for testing web and app UIs. 11 | 12 | ##Requirments: 13 | Running this script requires: 14 | 15 | - Mac OS X 16 | - Ruby 1.9.x or later 17 | - An internet connection. 18 | - An installed copy of the [Android SDK](http://developer.android.com/sdk/index.html) 19 | 20 | ##Usage 21 | 22 | 1. Download and unzip this project or clone the repo 23 | 2. Launch a terminal window 24 | 3. cd to where the script is located 25 | 4. Run the script in a terminal window by typing 26 | 27 | $> ruby emulators.rb 28 | 29 | ###Configuring Emulators 30 | 31 | The normal operation of the script is to configure a stock set of emulators. You will be prompted to confirm this action. The script will inspect your local copy of the Android SDK and attempt to install any missing packages. Finally it will configure the emulators, and launch the Android Virtual Device manager. 32 | Note that running this script will overwrite any previously created emulators with the same name. 33 | 34 | ###Installing WordPress for Android 35 | 36 | If you run this script while there is a running emulator, you will be prompted to install the latest copy of WordPress for Android. If you answer (y) the application .apk will be downloaded to your working directory and installed in the running emulator. Once its installed it will be launched automatically. 37 | 38 | 39 | ##Wish List 40 | Somethings that might be nice to have in future versions. 41 | 42 | - Build a single, specific emulator and install its apps. 43 | - Install Simplenote for Mac 44 | - Support for x86 architecture (once its fixed for Mavericks) 45 | - Automagically install the Android SDK if its missing and a package manager like Brew is available. 46 | -------------------------------------------------------------------------------- /emulators.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'yaml' 3 | 4 | # Configure a stock set of Android Emulators based on settings defined in emulators.yml. 5 | # Emulators use the same hardware settings with the exception of screen size, and density. 6 | class EmulatorBuilder 7 | 8 | @@packages = [ 9 | 'Android SDK Tools, revision 22.2.1', 10 | 'Android SDK Platform-tools, revision 18.0.1', 11 | 'Android SDK Build-tools, revision 18.1.1', 12 | 'SDK Platform Android 4.3, API 18, revision 2', 13 | 'Google APIs, Android API 18, revision 3', 14 | 'SDK Platform Android 4.0.3, API 15, revision 3', 15 | 'Google APIs, Android API 15, revision 2', 16 | 'SDK Platform Android 2.3.3, API 10, revision 2', 17 | 'Google APIs, Android API 10, revision 2' 18 | ] 19 | 20 | 21 | @@config = [ 22 | 'skin.dynamic=yes', 23 | 'hw.accelerometer=yes', 24 | 'hw.audioInput=yes', 25 | 'hw.battery=yes', 26 | 'hw.camera.back=none', 27 | 'hw.camera.front=none', 28 | 'hw.dPad=yes', 29 | 'hw.gps=yes', 30 | 'hw.keyboard=yes', 31 | 'hw.mainKeys=yes', 32 | 'hw.ramSize=1024', 33 | 'hw.sensors.orientation=yes', 34 | 'hw.sensors.proximity=yes', 35 | 'hw.trackBall=no', 36 | 'vm.heapSize=128' 37 | ] 38 | 39 | 40 | def init 41 | check_sdk 42 | 43 | # If an emulator is running prompt to install the latest apk. 44 | if @adb_path 45 | str = `#{@adb_path} devices` 46 | str = str.strip.split("\n").pop 47 | if str.include?("emulator") 48 | install 49 | return 50 | end 51 | end 52 | 53 | build 54 | end 55 | 56 | 57 | def build 58 | puts "\n\nHi there!\n\n" 59 | puts "Running this script will set up some preconfigured Android emulators." 60 | puts "Any required components (like the Android SDK) will also be downloaded and configured." 61 | puts "It might take a while. ;)\n\n" 62 | puts "Do you want to continue? y/n :" 63 | 64 | proceed = gets.strip 65 | if proceed != "y" 66 | puts "\nBye\n\n" 67 | return 68 | end 69 | 70 | puts "\nGreat! Getting started.\n\n" 71 | 72 | if @sdk_path.nil? 73 | puts "\nAndroid SDK missing. Please install the Android SDK." 74 | return 75 | # TODO 76 | # install_sdk 77 | end 78 | 79 | packages = check_missing_components 80 | if (packages.length > 0) 81 | install_missing_components(packages) 82 | end 83 | 84 | puts "Configuring Virtual Devices..." 85 | configure_emulators 86 | 87 | puts "Finished" 88 | spawn "#{@sdk_path} avd" #launch the virtual device manager 89 | 90 | end 91 | 92 | 93 | # Check the specified path for the location of the Android SDK. 94 | def check_android_path(path) 95 | if path.nil? || path.length == 0 96 | return 97 | end 98 | 99 | android_path = '/tools/android' 100 | adb_path = '/platform-tools/adb' 101 | 102 | if File.exists?(path) 103 | @sdk_path = path 104 | end 105 | 106 | path = path[0, path.index(android_path)] 107 | path = path + adb_path 108 | 109 | if File.exists?(path) 110 | @adb_path = path 111 | end 112 | 113 | end 114 | 115 | 116 | # Look for the SDKs Android tool 117 | def check_sdk 118 | puts "Looking for the Android SDK" 119 | 120 | # Look for the Android SDK. If we can't find it, ask for one. 121 | puts " Trying which" 122 | check_android_path(`which android`) 123 | 124 | if @sdk_path.nil? 125 | puts " Trying locate" 126 | locations = `locate "/tools/android"` 127 | if locations.length > 0 128 | check_android_path(locations.split("\n").pop) 129 | end 130 | end 131 | 132 | if @sdk_path.nil? 133 | puts " Trying find" 134 | locations = `find ~ -type f -maxdepth 6 -name android` 135 | if locations.length > 0 136 | check_android_path(locations.split("\n").pop) 137 | end 138 | end 139 | 140 | if @sdk_path.nil? 141 | locations = `find / -type f -maxdepth 6 -name android` 142 | if locations.length > 0 143 | check_android_path(locations.split("\n").pop) 144 | end 145 | end 146 | 147 | if @sdk_path 148 | puts " Found #{@sdk_path}" 149 | end 150 | 151 | end 152 | 153 | 154 | # Check installed packages an confirm we have everything we need to build our emulators. 155 | def check_missing_components 156 | puts "Checking installed components... \n" 157 | 158 | arr = [] 159 | unpkgs = `#{@sdk_path} list sdk -u` 160 | unpkgs = unpkgs[unpkgs.index('Packages available for installation'), unpkgs.length] 161 | pkgs = unpkgs.split("\n") 162 | 163 | # for each uninstalled package, check it against our list of required packages. 164 | # if found, save its id, we need to install it 165 | for item in pkgs 166 | for pkg in @@packages 167 | if item.index(pkg) 168 | arr << item.strip.to_i.to_s 169 | break 170 | end 171 | end 172 | end 173 | 174 | arr 175 | end 176 | 177 | 178 | # Try to install any missing packages 179 | def install_missing_components(packages) 180 | puts "Installing missing packages...\n\n" 181 | packages = packages.join(",") 182 | system("#{@sdk_path} update sdk --no-ui --filter #{packages}") 183 | end 184 | 185 | 186 | # Configure emulators. Overwrites existing emulators with the same name. 187 | def configure_emulators 188 | emulators = YAML::load_file(File.join(File.dirname(File.expand_path(__FILE__)), 'emulators.yml')) 189 | # create each emulator in the list 190 | # after the emulator is created, edit its config to use our desired settings 191 | for emulator in emulators 192 | puts "Configuring : #{emulator['name']}\n" 193 | args = " --abi #{emulator['abi']} --skin #{emulator['skin']} --target #{emulator['target']} --name #{emulator['name']}" 194 | # Echo no, to decline setting up a custom hardware profile. 195 | `echo no | #{@sdk_path} create avd --force --sdcard 10M #{args}` 196 | update_emulator_config(emulator) 197 | end 198 | end 199 | 200 | 201 | # Updates the emulator's config.ini with the desired settings. 202 | def update_emulator_config(emulator) 203 | # find the config file for the emulator 204 | path = ENV['HOME'] + '/.android/avd/' + emulator['name'] + '.avd/config.ini' 205 | if !File.exists?(path) 206 | return 207 | end 208 | 209 | # prep the config 210 | str = '' 211 | config = emulator['config'] 212 | config.each {|k,v| 213 | str = str + "\n#{k}=#{v}" 214 | } 215 | 216 | doc = @@config.join("\n") 217 | doc = doc + str 218 | 219 | # open for appending 220 | File.open(path, 'a') { |f| 221 | f.write(doc) 222 | } 223 | end 224 | 225 | 226 | # Install the latest version of WordPress for Android on a running emulator 227 | def install 228 | puts "\n\nHi there!\n\n" 229 | puts "I've detected a running emulator." 230 | puts "Would you like to install the latest version of WordPress or Android? y/n" 231 | 232 | proceed = gets.strip 233 | if proceed != 'y' 234 | puts "\nBye\n\n" 235 | return 236 | end 237 | 238 | puts "Downloading WordPress for Android \n" 239 | system("curl -o wpandroid.apk http://iosbuilds.automattic.com/builds/android/latest.apk") 240 | 241 | puts "Installing WordPress for Android \n" 242 | system("#{@adb_path} install wpandroid.apk") 243 | 244 | system("#{@adb_path} shell am start -n org.wordpress.android/org.wordpress.android.ui.posts.PostsActivity") 245 | puts "Finished" 246 | end 247 | 248 | end 249 | 250 | builder = EmulatorBuilder.new 251 | builder.init 252 | -------------------------------------------------------------------------------- /emulators.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Nexus.7.Gen.2.Jellybean.4.3 3 | target: android-18 4 | abi: armeabi-v7a 5 | skin: 1920x1200 6 | config: 7 | hw.lcd.density: 323 8 | hw.gpu.enabled: yes 9 | 10 | - name: Nexus.7.Gen.1.Jellybean.4.3 11 | target: android-18 12 | abi: armeabi-v7a 13 | skin: 1280x800 14 | config: 15 | hw.lcd.density: 216 16 | hw.gpu.enabled: yes 17 | 18 | - name: Nexus.7.Gen.1.ICS.4.0.3 19 | target: android-15 20 | abi: armeabi-v7a 21 | skin: 1280x800 22 | config: 23 | hw.lcd.density: 216 24 | hw.gpu.enabled: yes 25 | 26 | - name: Nexus.4.Jellybean.4.3 27 | target: android-18 28 | abi: armeabi-v7a 29 | skin: 768x1280 30 | config: 31 | hw.lcd.density: 320 32 | hw.gpu.enabled: yes 33 | 34 | - name: Nexus.4.ICS.4.0.3 35 | target: android-15 36 | abi: armeabi-v7a 37 | skin: 768x1280 38 | config: 39 | hw.lcd.density: 320 40 | hw.gpu.enabled: yes 41 | 42 | - name: Nexus.One.Gingerbread.2.3.3 43 | target: android-10 44 | abi: armeabi 45 | skin: 480x800 46 | config: 47 | hw.lcd.density: 240 48 | 49 | - name: Nexus.10.Jellybean.4.3 50 | target: android-18 51 | abi: armeabi-v7a 52 | skin: 2560x1600 53 | config: 54 | hw.lcd.density: 320 55 | hw.gpu.enabled: yes 56 | 57 | - name: Droid.X.Gingerbread.2.3.3 58 | target: android-10 59 | abi: armeabi 60 | skin: 480x854 61 | config: 62 | hw.lcd.density: 228 63 | 64 | - name: Droid.RAZR.ICS.4.0.3 65 | target: android-15 66 | abi: armeabi-v7a 67 | skin: 540x960 68 | config: 69 | hw.lcd.density: 256 70 | hw.gpu.enabled: yes 71 | 72 | - name: Droid.RAZR.Gingerbread.2.3.3 73 | target: android-10 74 | abi: armeabi 75 | skin: 540x960 76 | config: 77 | hw.lcd.density: 256 78 | 79 | - name: Kindle.Fire.HD.8.9.ICS.4.0.3 80 | target: android-15 81 | abi: armeabi-v7a 82 | skin: 1920x1200 83 | config: 84 | hw.lcd.density: 254 85 | hw.gpu.enabled: yes 86 | 87 | - name: Kindle.Fire.HD.7.ICS.4.0.3 88 | target: android-15 89 | abi: armeabi-v7a 90 | skin: 1280x800 91 | config: 92 | hw.lcd.density: 216 93 | hw.gpu.enabled: yes 94 | 95 | - name: Kindle.Fire.Gingerbread.2.3.3 96 | target: android-10 97 | abi: armeabi 98 | skin: 1024x600 99 | config: 100 | hw.lcd.density: 169 101 | 102 | - name: Galaxy.S2.Jellybean.4.3 103 | target: android-18 104 | abi: armeabi-v7a 105 | skin: 480x800 106 | config: 107 | hw.lcd.density: 219 108 | hw.gpu.enabled: yes 109 | 110 | - name: Galaxy.S2.ICS.4.0.3 111 | target: android-15 112 | abi: armeabi-v7a 113 | skin: 480x800 114 | config: 115 | hw.lcd.density: 219 116 | hw.gpu.enabled: yes 117 | 118 | - name: Galaxy.S2.Gingerbread.2.3.3 119 | target: android-10 120 | abi: armeabi 121 | skin: 480x800 122 | config: 123 | hw.lcd.density: 219 124 | 125 | - name: Galaxy.S3.Jellybean.4.3 126 | target: android-18 127 | abi: armeabi-v7a 128 | skin: 720x1280 129 | config: 130 | hw.lcd.density: 306 131 | hw.gpu.enabled: yes 132 | 133 | - name: Galaxy.S3.ICS.4.0.3 134 | target: android-15 135 | abi: armeabi-v7a 136 | skin: 720x1280 137 | config: 138 | hw.lcd.density: 306 139 | hw.gpu.enabled: yes 140 | 141 | - name: Galaxy.S4.Jellybean.4.3 142 | target: android-18 143 | abi: armeabi-v7a 144 | skin: 1080x1920 145 | config: 146 | hw.lcd.density: 441 147 | hw.gpu.enabled: yes 148 | 149 | - name: Galaxy.Note.II.Jellybean.4.3 150 | target: android-18 151 | abi: armeabi-v7a 152 | skin: 1280x720 153 | config: 154 | hw.lcd.density: 267 155 | hw.gpu.enabled: yes 156 | 157 | - name: Galaxy.Note.Jellybean.4.3 158 | target: android-18 159 | abi: armeabi-v7a 160 | skin: 1280x800 161 | config: 162 | hw.lcd.density: 285 163 | hw.gpu.enabled: yes 164 | 165 | - name: Galaxy.Note.ICS.4.0.3 166 | target: android-15 167 | abi: armeabi-v7a 168 | skin: 1280x800 169 | config: 170 | hw.lcd.density: 285 171 | hw.gpu.enabled: yes 172 | 173 | - name: Galaxy.Note.Gingerbread.2.3.3 174 | target: android-10 175 | abi: armeabi 176 | skin: 1280x800 177 | config: 178 | hw.lcd.density: 285 179 | --------------------------------------------------------------------------------