Top Level Namespace

Defined Under Namespace

Modules: Calabash Classes: Env, JavaKeystore

Constant Summary collapse

WAIT_TIMEOUT =
(ENV['WAIT_TIMEOUT'] || 30).to_f
STEP_PAUSE =
(ENV['STEP_PAUSE'] || 0.5).to_f

Instance Method Summary collapse

Instance Method Details

#aapt_dump(app, key) ⇒ Object



24
25
26
27
# File 'lib/calabash-android/helpers.rb', line 24

def aapt_dump(app, key)
  lines = `"#{Env.tools_dir}/aapt" dump badging "#{app}"`.lines.collect(&:strip)
  lines.select { |l| l.start_with?("#{key}:") }
end

#build_test_server_if_needed(app_path) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
# File 'lib/calabash-android/helpers.rb', line 38

def build_test_server_if_needed(app_path)
  unless File.exist?(test_server_path(app_path))
    if ARGV.include? "--no-build"
      puts "No test server found for this combination of app and calabash version. Exiting!"
      exit 1
    else
      puts "No test server found for this combination of app and calabash version. Recreating test server."
      calabash_build(app_path)
    end
  end
end

#checksum(file_path) ⇒ Object



29
30
31
32
# File 'lib/calabash-android/helpers.rb', line 29

def checksum(file_path)
  require 'digest/md5'
  Digest::MD5.file(file_path).hexdigest
end

#extract_md5_fingerprint(fingerprints) ⇒ Object



104
105
106
107
108
# File 'lib/calabash-android/helpers.rb', line 104

def extract_md5_fingerprint(fingerprints)
  m = fingerprints.scan(/MD5.*((?:[a-fA-F\d]{2}:){15}[a-fA-F\d]{2})/).flatten
  raise "No MD5 fingerprint found:\n #{fingerprints}" if m.empty?
  m.first
end

#fingerprint_from_apk(app_path) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/calabash-android/helpers.rb', line 80

def fingerprint_from_apk(app_path)
  app_path = File.expand_path(app_path)
  Dir.mktmpdir do |tmp_dir|
    Dir.chdir(tmp_dir) do
      FileUtils.cp(app_path, "app.apk")
      FileUtils.mkdir("META-INF")
      Zip::ZipFile.foreach("app.apk") do |z|
        z.extract if /^META-INF\/\w+.(RSA|rsa)/ =~ z.name
      end
      rsa_files = Dir["#{tmp_dir}/META-INF/*"]

      raise "No RSA file found in META-INF. Cannot proceed." if rsa_files.empty?
      raise "More than one RSA file found in META-INF. Cannot proceed." if rsa_files.length > 1

      cmd = "#{Env.keytool_path} -v -printcert -J\"-Dfile.encoding=utf-8\" -file \"#{rsa_files.first}\""
      log cmd
      fingerprints = `#{cmd}`
      md5_fingerprint = extract_md5_fingerprint(fingerprints)
      log "MD5 fingerprint for signing cert (#{app_path}): #{md5_fingerprint}"
      md5_fingerprint
    end
  end
end

#log(message, error = false) ⇒ Object



110
111
112
# File 'lib/calabash-android/helpers.rb', line 110

def log(message, error = false)
  $stdout.puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S")} - #{message}" if (error or ARGV.include? "-v" or ARGV.include? "--verbose")
end

#main_activity(app) ⇒ Object



16
17
18
19
20
21
22
# File 'lib/calabash-android/helpers.rb', line 16

def main_activity(app)
  launchable_activity_line = aapt_dump(app, "launchable-activity").first
  raise "'launchable-activity' not found in aapt output" unless launchable_activity_line
  m = launchable_activity_line.match(/name='([^']+)'/)
  raise "Unexpected output from aapt: #{launchable_activity_line}" unless m
  m[1]
end

#package_name(app) ⇒ Object



8
9
10
11
12
13
14
# File 'lib/calabash-android/helpers.rb', line 8

def package_name(app)
  package_line = aapt_dump(app, "package").first
  raise "'package' not found in aapt output" unless package_line
  m = package_line.match(/name='([^']+)'/)
  raise "Unexpected output from aapt: #{package_line}" unless m
  m[1]
end

#resign_apk(app_path) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
# File 'lib/calabash-android/helpers.rb', line 50

def resign_apk(app_path)
  Dir.mktmpdir do |tmp_dir|
    log "Resign apk"
    unsigned_path = File.join(tmp_dir, 'unsigned.apk')
    unaligned_path = File.join(tmp_dir, 'unaligned.apk')
    FileUtils.cp(app_path, unsigned_path)
    unsign_apk(unsigned_path)
    sign_apk(unsigned_path, unaligned_path)
    zipalign_apk(unaligned_path, app_path)
  end
end

#sign_apk(app_path, dest_path) ⇒ Object



75
76
77
78
# File 'lib/calabash-android/helpers.rb', line 75

def sign_apk(app_path, dest_path)
  java_keystore = JavaKeystore.get_keystores.first
  java_keystore.sign_apk(app_path, dest_path)
end

#test_server_path(apk_file_path) ⇒ Object



34
35
36
# File 'lib/calabash-android/helpers.rb', line 34

def test_server_path(apk_file_path)
  "test_servers/#{checksum(apk_file_path)}_#{Calabash::Android::VERSION}.apk"
end

#unsign_apk(path) ⇒ Object



62
63
64
65
66
67
68
69
# File 'lib/calabash-android/helpers.rb', line 62

def unsign_apk(path)
  files_to_remove = `"#{Env.tools_dir}/aapt" list "#{path}"`.lines.collect(&:strip).grep(/^META-INF\//)
  if files_to_remove.empty?
    log "App wasn't signed. Will not try to unsign it."
  else
    system("\"#{Env.tools_dir}/aapt\" remove \"#{path}\" #{files_to_remove.join(" ")}")
  end
end

#zipalign_apk(inpath, outpath) ⇒ Object



71
72
73
# File 'lib/calabash-android/helpers.rb', line 71

def zipalign_apk(inpath, outpath)
  system(%Q(#{Env.zipalign_path} -f 4 "#{inpath}" "#{outpath}"))
end