Class: DeviceAPI::Android::ADB

Inherits:
Execution
  • Object
show all
Defined in:
lib/device_api/android/adb.rb

Overview

Namespace for all methods encapsulating adb calls

Class Method Summary collapse

Class Method Details

.am(serial, command) ⇒ Object

Starts intent using adb Returns stdout DeviceAPI::ADB.am(serial, “start -a android.intent.action.MAIN -n com.android.settings/.wifi.WifiSettings”)

Parameters:

  • serial

    serial number of device

  • command

    -option activity



283
284
285
# File 'lib/device_api/android/adb.rb', line 283

def self.am(serial, command)
  shell(serial, "am #{command}").stdout
end

.block_package(serial, package) ⇒ Object

Blocks a package, used on Android versions less than KitKat Returns boolean

Parameters:

  • serial

    serial of device

  • package

    to block



299
300
301
302
# File 'lib/device_api/android/adb.rb', line 299

def self.block_package(serial, package)
  result = pm(serial, "block #{package}")
  result.include?('true')
end

.change_apk(options = {}) ⇒ Object

Raises:



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/device_api/android/adb.rb', line 144

def self.change_apk(options = {})
  package_name = options[:package_name]
  apk = options[:apk]
  serial = options[:serial]
  action = options[:action]

  case action
    when :install
      command = "adb -s #{serial} install #{apk}"
    when :uninstall
      command = "adb -s #{serial} uninstall #{package_name}"
    else
      raise ADBCommandError.new('No action specified')
  end

  result = execute(command)

  raise ADBCommandError.new(result.stderr) if result.exit != 0

  lines = result.stdout.split("\n").map { |line| line.strip }

  lines.last
end

.devicesArray

Returns an array representing connected devices DeviceAPI::ADB.devices #=> { ‘1232132’ => ‘device’ }

Returns:

  • (Array)

    list of attached devices

Raises:



17
18
19
20
21
22
# File 'lib/device_api/android/adb.rb', line 17

def self.devices
  result = execute_with_timeout_and_retry('adb devices')

  raise ADBCommandError.new(result.stderr) if result.exit != 0
  result.stdout.scan(/(.*)\t(.*)/).map { |a,b| {a => b}}
end

.dumpsys(serial, command) ⇒ Array

Returns the ‘dumpsys’ information from the specified device

Parameters:

  • serial

    serial number of device

Returns:

  • (Array)

    array of results from adb shell dumpsys



119
120
121
122
# File 'lib/device_api/android/adb.rb', line 119

def self.dumpsys(serial, command)
  result = shell(serial, "dumpsys #{command}")
  result.stdout.split("\n").map { |line| line.strip }
end

.get_battery_info(serial) ⇒ Hash

Get the ‘battery’ information from dumpsys

Parameters:

  • serial (String)

    serial number of device

Returns:

  • (Hash)

    hash containing battery information from dumpsys



67
68
69
70
# File 'lib/device_api/android/adb.rb', line 67

def self.get_battery_info(serial)
  lines = dumpsys(serial, 'battery')
  process_dumpsys('(.*):\s+(.*)', lines)
end

.get_device_dpi(serial) ⇒ Object



105
106
107
108
109
110
111
112
113
114
# File 'lib/device_api/android/adb.rb', line 105

def self.get_device_dpi(serial)
  lines = dumpsys(serial, 'window')
  dpi = nil
  lines.each do |line|
    if /sw(\d*)dp/.match(line)
      dpi = Regexp.last_match[1]
    end
  end
  dpi
end

.get_network_info(serial) ⇒ Object

Get the network information



73
74
75
76
77
78
79
# File 'lib/device_api/android/adb.rb', line 73

def self.get_network_info(serial)
  lines = shell(serial, 'netcfg')
  lines.stdout.split("\n").map do |a|
    b = a.split(" ")
    { name: b[0], ip: b[2].split('/')[0], mac: b[4] }
  end
end

.get_state(serial) ⇒ String

Retrieve device state for a single device

Parameters:

  • serial

    serial number of device

Returns:

  • (String)

    device state

Raises:



27
28
29
30
31
32
33
34
35
# File 'lib/device_api/android/adb.rb', line 27

def self.get_state(serial)
  result = execute('adb get-state -s #{serial}')

  raise ADBCommandError.new(result.stderr) if result.exit != 0

  lines = result.stdout.split("\n")
  /(.*)/.match(lines.last)
  Regexp.last_match[0].strip
end

.get_uptime(serial) ⇒ Float

Returns the uptime of the specified device

Parameters:

  • serial

    serial number of device

Returns:

  • (Float)

    uptime in seconds



171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/device_api/android/adb.rb', line 171

def self.get_uptime(serial)
  result = shell(serial, 'cat /proc/uptime')

  lines = result.stdout.split("\n")
  uptime = 0
  lines.each do |l|
    if /([\d.]*)\s+[\d.]*/.match(l)
      uptime = Regexp.last_match[0].to_f.round
    end
  end
  uptime
end

.getdumpsys(serial) ⇒ Hash

Get the ‘input’ information from dumpsys

Parameters:

  • serial

    serial number of device

Returns:

  • (Hash)

    hash containing input information from dumpsys



51
52
53
54
# File 'lib/device_api/android/adb.rb', line 51

def self.getdumpsys(serial)
  lines = dumpsys(serial, 'input')
  process_dumpsys('(.*):\s+(.*)', lines)
end

.getphoneinfo(serial) ⇒ Hash

Get the ‘iphonesubinfo’ from dumpsys

Parameters:

  • serial

    serial number of device

Returns:

  • (Hash)

    hash containing iphonesubinfo information from dumpsys



59
60
61
62
# File 'lib/device_api/android/adb.rb', line 59

def self.getphoneinfo(serial)
  lines = dumpsys(serial, 'iphonesubinfo')
  process_dumpsys('(.*) =\s+(.*)', lines)
end

.getpowerinfo(serial) ⇒ Hash

Get the ‘power’ information from dumpsys

Parameters:

  • serial (String)

    serial number of device

Returns:

  • (Hash)

    hash containing power information from dumpsys



100
101
102
103
# File 'lib/device_api/android/adb.rb', line 100

def self.getpowerinfo(serial)
  lines = dumpsys(serial, 'power')
  process_dumpsys('(.*)=(.*)', lines)
end

.getprop(serial) ⇒ Hash

Get the properties of a specified device

Parameters:

  • serial

    serial number of device

Returns:

  • (Hash)

    hash containing device properties



40
41
42
43
44
45
46
# File 'lib/device_api/android/adb.rb', line 40

def self.getprop(serial)
  result = shell(serial, 'getprop')

  lines = result.stdout.encode('UTF-16', 'UTF-8', invalid: :replace, replace: '').encode('UTF-8', 'UTF-16').split("\n")

  process_dumpsys('\[(.*)\]:\s+\[(.*)\]', lines)
end

.hide_package(serial, package) ⇒ Object

Blocks a package on KitKat and above Returns boolean

Parameters:

  • serial

    serial of device

  • package

    to hide



308
309
310
311
# File 'lib/device_api/android/adb.rb', line 308

def self.hide_package(serial, package)
  result = pm(serial, "hide #{package}")
  result.include?('true')
end

.install_apk(options = {}) ⇒ String

Installs a specified apk to a specific device

Parameters:

  • options (Hash) (defaults to: {})

    the options used for installing an apk

Options Hash (options):

  • :apk (String)

    path to apk to install

  • :serial (String)

    serial number of device

Returns:

  • (String)

    return result from adb install command



129
130
131
132
# File 'lib/device_api/android/adb.rb', line 129

def self.install_apk(options = {})
  options[:action] = :install
  change_apk(options)
end

.keyevent(serial, keyevent) ⇒ Object

Sends a key event to the specified device

Parameters:

  • serial (String)

    serial number of device

  • keyevent (String)

    keyevent to send to the device



244
245
246
# File 'lib/device_api/android/adb.rb', line 244

def self.keyevent(serial, keyevent)
  shell(serial, "input keyevent #{keyevent}").stdout
end

.monkey(serial, args) ⇒ Object

Runs monkey testing

Examples:

DeviceAPI::ADB.monkey( serial, :package => 'my.lovely.app' )

Parameters:

  • serial

    serial number of device

  • args (Hash)

    hash of arguments used for starting testing

Options Hash (args):

  • :events (String) — default: 10000

    number of events to run

  • :package (String)

    name of package to run the tests against

  • :seed (String)

    pass the seed number (optional)

  • :throttle (String)

    throttle value (optional)



201
202
203
204
205
206
207
208
209
210
211
212
213
# File 'lib/device_api/android/adb.rb', line 201

def self.monkey(serial, args)

  events = args[:events] || 10000
  package = args[:package] or raise "package name not provided (:package => 'bbc.iplayer')"
  seed = args[:seed]
  throttle = args[:throttle]

  cmd = "monkey -p #{package} -v #{events}"
  cmd = cmd + " -s #{seed}" if seed
  cmd = cmd + " -t #{throttle}" if throttle

  shell(serial, cmd)
end

.pm(serial, command) ⇒ Object

Package manager commands

Examples:

DeviceAPI::ADB.pm(serial, ‘list packages’)

Parameters:

  • serial

    serial of device

  • command

    command to issue to the package manager



291
292
293
# File 'lib/device_api/android/adb.rb', line 291

def self.pm(serial, command)
  shell(serial, "pm #{command}").stdout
end

.process_dumpsys(regex_string, data) ⇒ Hash

Processes the results from dumpsys to format them into a hash

Parameters:

  • regex_string (String)

    regex string used to separate the results from the keys

  • data (Array)

    data returned from dumpsys

Returns:

  • (Hash)

    hash containing the keys and values as distinguished by the supplied regex



85
86
87
88
89
90
91
92
93
94
95
# File 'lib/device_api/android/adb.rb', line 85

def self.process_dumpsys(regex_string, data)
  props = {}
  regex = Regexp.new(regex_string)
  data.each do |line|
    if regex.match(line)
      props[Regexp.last_match[1]] = Regexp.last_match[2]
    end
  end

  props
end

.reboot(serial) ⇒ nil

Reboots the specified device

Parameters:

  • serial

    serial number of device

Returns:

  • (nil)

    Nil if successful, otherwise an error is raised

Raises:



187
188
189
190
# File 'lib/device_api/android/adb.rb', line 187

def self.reboot(serial)
  result = execute("adb -s #{serial} reboot")
  raise ADBCommandError.new(result.stderr) if result.exit != 0
end

.screencap(serial, args) ⇒ Object

Take a screenshot from the device

Examples:

DeviceAPI::ADB.screenshot( serial, :filename => '/tmp/filename.png' )

Parameters:

  • serial

    serial number of device

  • args (Hash)

    hash of arguments

Options Hash (args):

  • :filename (String)

    name (with full path) required to save the image



221
222
223
224
225
226
227
228
229
# File 'lib/device_api/android/adb.rb', line 221

def self.screencap( serial, args )
  
  filename = args[:filename] or raise "filename not provided (:filename => '/tmp/myfile.png')"
  
  convert_carriage_returns = %q{perl -pe 's/\x0D\x0A/\x0A/g'}
  cmd = "screencap -p | #{convert_carriage_returns} > #{filename}"
  
  shell(serial, cmd)
end

.shell(serial, command) ⇒ Object

ADB Shell command

Parameters:

  • serial (String)

    serial number of device

  • command (String)

    command to execute



251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/device_api/android/adb.rb', line 251

def self.shell(serial, command)
  result = execute("adb -s #{serial} shell #{command}")

  case result.stderr
  when /^error: device unauthorized./
    raise DeviceAPI::UnauthorizedDevice, result.stderr
  when /^error: device not found/
    raise DeviceAPI::DeviceNotFound, result.stderr
  else
    raise ADBCommandError.new(result.stderr)
  end if result.exit != 0

  result
end

.swipe(serial, coords = {x_from: 0, x_to: 0, y_from: 0, y_to: 0 }) ⇒ Object

Sends a swipe command to the specified device

Parameters:

  • serial (String)

    serial number of the device

  • coords (Hash) (defaults to: {x_from: 0, x_to: 0, y_from: 0, y_to: 0 })

    hash of coordinates to swipe from / to

Options Hash (coords):

  • :x_from (String) — default: 0

    Coordinate to start from on the X axis

  • :x_to (String) — default: 0

    Coordinate to end on on the X axis

  • :y_from (String) — default: 0

    Coordinate to start from on the Y axis

  • :y_to (String) — default: 0

    Coordinate to end on on the Y axis



273
274
275
# File 'lib/device_api/android/adb.rb', line 273

def self.swipe(serial, coords = {x_from: 0, x_to: 0, y_from: 0, y_to: 0 })
  shell(serial, "input swipe #{coords[:x_from]} #{coords[:x_to]} #{coords[:y_from]} #{coords[:y_to]}").stdout
end

.uninstall_apk(options = {}) ⇒ String

Uninstalls a specified package from a specified device

Parameters:

  • options (Hash) (defaults to: {})

    the options used for uninstalling a package

Options Hash (options):

  • :package_name (String)

    package to uninstall

  • :serial (String)

    serial number of device

Returns:

  • (String)

    return result from adb uninstall command



139
140
141
142
# File 'lib/device_api/android/adb.rb', line 139

def self.uninstall_apk(options = {})
  options[:action] = :uninstall
  change_apk(options)
end

.wifi(serial) ⇒ Object

Returns wifi status and access point name

Examples:

DeviceAPI::ADB.wifi(serial)

Parameters:

  • serial

    serial number of device



235
236
237
238
239
# File 'lib/device_api/android/adb.rb', line 235

def self.wifi(serial)
  result = shell(serial, 'dumpsys wifi | grep mNetworkInfo')

  {:status => result.stdout.match("state:(.*?),")[1].strip, :access_point => result.stdout.match("extra:(.*?),")[1].strip.gsub(/"/,'')}
end