Class: DeviceAPI::Android::Signing

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

Overview

Namespace for all methods encapsulating adb calls

Class Method Summary collapse

Class Method Details

.generate_keystore(options = {}) ⇒ Boolean, Exception

Creates a keystore used for signing apks

Parameters:

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

    options to pass through to keytool

Options Hash (options):

  • :keystore (String) — default: '~/.android/debug.keystore'

    full path to location to create keystore

  • :alias (String) — default: 'androiddebugkey'

    keystore alias name

  • :dname (String) — default: 'CN=hive'

    keystore dname

  • :password (String) — default: 'android'

    keystore password

Returns:

  • (Boolean, Exception)

    returns true if a keystore is created, otherwise an exception is raised

Raises:


15
16
17
18
19
20
21
22
23
24
# File 'lib/device_api/android/signing.rb', line 15

def self.generate_keystore(options = {})
  keystore    = options[:keystore]  || '~/.android/debug.keystore'
  alias_name  = options[:alias]     || 'androiddebugkey'
  dname       = options[:dname]     || 'CN=hive'
  password    = options[:password]  || 'android'

  result = execute("keytool -genkey -noprompt -alias #{alias_name} -dname '#{dname}' -keystore #{keystore} -storepass #{password} -keypass #{password} -keyalg RSA -keysize 2048 -validity 10000")
  raise SigningCommandError.new(result.stderr) if result.exit != 0
  true
end

.is_apk_signed?(apk_path) ⇒ Boolean

Checks to see if an apk has already been signed

Parameters:

  • apk_path (String)

    full path to apk to check

Returns:

  • (Boolean)

    returns false if the apk is unsigned, true if it is signed


56
57
58
59
60
# File 'lib/device_api/android/signing.rb', line 56

def self.is_apk_signed?(apk_path)
  result = execute("aapt list #{apk_path} | grep '^META-INF\/.*'")
  return false if result.stdout.empty?
  true
end

.sign_apk(options = {}) ⇒ Boolean, Exception

Signs an apk using the specified keystore

Parameters:

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

    options to pass through to jarsigner

Options Hash (options):

  • :apk (String)

    full path to the apk to sign

  • :alias (String) — default: 'androiddebugkey'

    alias of the keystore

  • :keystore (String) — default: '~/.android/debug.keystore'

    full path to the location of the keystore

  • :keystore_password (String) — default: 'android'

    password required to open the keystore

  • :resign (Boolean)

    if true then an already signed apk will be stripped of previous signing and resigned

Returns:

  • (Boolean, Exception)

    return true if the apk is signed, false if the apk is already signed and resigning is anything other than true otherwise an exception is raised

Raises:


35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/device_api/android/signing.rb', line 35

def self.sign_apk(options = {})
  apk               = options[:apk]
  alias_name        = options[:alias]             || 'androiddebugkey'
  keystore          = options[:keystore]          || '~/.android/debug.keystore'
  keystore_password = options[:keystore_password] || 'android'
  resign            = options[:resign]

  # Check to see if the APK has already been signed
  if is_apk_signed?(apk)
    return false unless resign
    unsign_apk(apk)
  end
  generate_keystore({ keystore: keystore, password: keystore_password, alias_name: alias_name }) unless File.exists?(File.expand_path(keystore))
  result = execute("jarsigner -verbose -sigalg MD5withRSA -digestalg SHA1 -keystore #{File.expand_path(keystore)} -storepass #{keystore_password} #{apk} #{alias_name}")
  raise SigningCommandError.new(result.stderr) if result.exit != 0
  true
end

.unsign_apk(apk_path) ⇒ Boolean, Exception

Removes any previous signatures from an apk

Parameters:

  • apk_path (String)

    full path to the apk

Returns:

  • (Boolean, Exception)

    returns true if the apk is successfully unsigned, otherwise an exception is raised

Raises:


65
66
67
68
69
70
# File 'lib/device_api/android/signing.rb', line 65

def self.unsign_apk(apk_path)
 file_list = execute("aapt list #{apk_path} | grep '^META-INF\/.*'")
 result = execute("aapt remove #{apk_path} #{file_list.stdout.split(/\s+/).join(' ')}")
 raise SigningCommandError.new(result.stderr) if result.exit != 0
 true
end