Top Level Namespace
- Includes:
- REXML
Defined Under Namespace
Modules: Calabash
Constant Summary collapse
- WAIT_TIMEOUT =
(ENV['WAIT_TIMEOUT'] || 30).to_f
- STEP_PAUSE =
(ENV['STEP_PAUSE'] || 0.5).to_f
Instance Method Summary collapse
- #android_home_path ⇒ Object
- #build_test_server_if_needed(app_path) ⇒ Object
- #checksum(file_path) ⇒ Object
- #default_keystore ⇒ Object
- #extract_md5_fingerprint(fingerprints) ⇒ Object
- #fail_if_key_missing(map, key) ⇒ Object
- #fingerprint_from_apk(app_path) ⇒ Object
- #fingerprint_from_keystore ⇒ Object
- #framework_path(apk_file_path) ⇒ Object
- #is_windows? ⇒ Boolean
- #keytool_path ⇒ Object
- #log(message, error = false) ⇒ Object
- #main_activity(app) ⇒ Object
- #manifest(app) ⇒ Object
- #manifest_path(apk_file_path) ⇒ Object
- #package_name(app) ⇒ Object
- #put_in_quotes(s) ⇒ Object
- #read_keystore_info ⇒ Object
- #remove_quotes(s) ⇒ Object
- #resign_apk(app_path) ⇒ Object
- #sign_apk(app_path, dest_path) ⇒ Object
- #test_server_path(apk_file_path) ⇒ Object
- #tools_dir ⇒ Object
Instance Method Details
#android_home_path ⇒ Object
106 107 108 |
# File 'lib/calabash-android/helpers.rb', line 106 def android_home_path ENV["ANDROID_HOME"].gsub("\\", "/") end |
#build_test_server_if_needed(app_path) ⇒ Object
59 60 61 62 63 64 65 66 67 68 69 |
# File 'lib/calabash-android/helpers.rb', line 59 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
41 42 43 44 |
# File 'lib/calabash-android/helpers.rb', line 41 def checksum(file_path) require 'digest/md5' Digest::MD5.file(file_path).hexdigest end |
#default_keystore ⇒ Object
124 125 126 127 128 129 130 |
# File 'lib/calabash-android/helpers.rb', line 124 def default_keystore { "keystore_location" => File.(File.join(ENV["HOME"], "/.android/debug.keystore")), "keystore_password" => "android", "keystore_alias" => "androiddebugkey", } end |
#extract_md5_fingerprint(fingerprints) ⇒ Object
185 186 187 188 189 190 191 |
# File 'lib/calabash-android/helpers.rb', line 185 def extract_md5_fingerprint(fingerprints) log 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 |
#fail_if_key_missing(map, key) ⇒ Object
132 133 134 |
# File 'lib/calabash-android/helpers.rb', line 132 def fail_if_key_missing(map, key) raise "Found .calabash_settings but no #{key} defined." unless map[key] end |
#fingerprint_from_apk(app_path) ⇒ Object
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/calabash-android/helpers.rb', line 163 def fingerprint_from_apk(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 = "#{keytool_path} -v -printcert -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 |
#fingerprint_from_keystore ⇒ Object
152 153 154 155 156 157 158 159 160 161 |
# File 'lib/calabash-android/helpers.rb', line 152 def fingerprint_from_keystore keystore_info = read_keystore_info cmd = "#{keytool_path} -v -list -alias #{keystore_info["keystore_alias"]} -keystore #{keystore_info["keystore_location"]} -storepass #{keystore_info["keystore_password"]}" log cmd fingerprints = `#{cmd}` md5_fingerprint = extract_md5_fingerprint(fingerprints) log "MD5 fingerprint for keystore (#{keystore_info["keystore_location"]}): #{md5_fingerprint}" md5_fingerprint end |
#framework_path(apk_file_path) ⇒ Object
54 55 56 |
# File 'lib/calabash-android/helpers.rb', line 54 def framework_path(apk_file_path) "test_servers/apktool-#{checksum(apk_file_path)}_#{Calabash::Android::VERSION}" end |
#is_windows? ⇒ Boolean
193 194 195 196 |
# File 'lib/calabash-android/helpers.rb', line 193 def is_windows? require 'rbconfig' (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/) end |
#keytool_path ⇒ Object
144 145 146 147 148 149 150 |
# File 'lib/calabash-android/helpers.rb', line 144 def keytool_path if is_windows? "\"#{ENV["JAVA_HOME"]}/bin/keytool.exe\"" else "keytool" end end |
#log(message, error = false) ⇒ Object
198 199 200 |
# File 'lib/calabash-android/helpers.rb', line 198 def log(, error = false) $stdout.puts "#{Time.now.strftime("%Y-%m-%d %H:%M:%S")} - #{}" if (error or ARGV.include? "-v" or ARGV.include? "--verbose") end |
#main_activity(app) ⇒ Object
16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/calabash-android/helpers.rb', line 16 def main_activity(app) manifest = Document.new(manifest(app)) main_activity = manifest.elements["//action[@name='android.intent.action.MAIN']/../.."].attributes['name'] #Handle situation where main activity is on the form '.class_name' if main_activity.start_with? "." main_activity = package_name(app) + main_activity elsif not main_activity.include? "." #This is undocumentet behaviour but Android seems to accept shorthand naming that does not start with '.' main_activity = "#{package_name(app)}.#{main_activity}" end main_activity end |
#manifest(app) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/calabash-android/helpers.rb', line 28 def manifest(app) out_path = manifest_path(app) manifest_file = File.join(out_path, 'AndroidManifest.xml') unless File.size?(manifest_file) manifest_extractor = File.join(File.(File.dirname(__FILE__)),'lib', 'apktool-cli-1.5.3-SNAPSHOT.jar') output = `java -jar "#{manifest_extractor}" d -s --frame-path "#{framework_path(app)}" -f "#{app}" #{out_path} 2>&1` raise "Unable to extract manifest: #{output}" unless File.size?(manifest_file) # Tidy up a bit. It would be nice if apktool could just dump the manifest alone. FileUtils.rm_rf(%w{res assets classes.dex}.map {|f| File.join(out_path, f) }) end File.read(manifest_file) end |
#manifest_path(apk_file_path) ⇒ Object
50 51 52 |
# File 'lib/calabash-android/helpers.rb', line 50 def manifest_path(apk_file_path) "test_servers/#{checksum(apk_file_path)}_#{Calabash::Android::VERSION}.res" end |
#package_name(app) ⇒ Object
8 9 10 11 12 13 14 |
# File 'lib/calabash-android/helpers.rb', line 8 def package_name(app) require 'rexml/document' require 'rexml/xpath' manifest = Document.new(manifest(app)) manifest.root.attributes['package'] end |
#put_in_quotes(s) ⇒ Object
140 141 142 |
# File 'lib/calabash-android/helpers.rb', line 140 def put_in_quotes(s) %Q{"#{s}"} end |
#read_keystore_info ⇒ Object
110 111 112 113 114 115 116 117 118 119 120 121 122 |
# File 'lib/calabash-android/helpers.rb', line 110 def read_keystore_info keystore = default_keystore if File.exist? ".calabash_settings" keystore = JSON.parse(IO.read(".calabash_settings")) fail_if_key_missing(keystore, "keystore_location") fail_if_key_missing(keystore, "keystore_password") fail_if_key_missing(keystore, "keystore_alias") keystore["keystore_location"] = File.(keystore["keystore_location"]) end keystore["keystore_location"] = put_in_quotes(remove_quotes(keystore["keystore_location"])) keystore end |
#remove_quotes(s) ⇒ Object
136 137 138 |
# File 'lib/calabash-android/helpers.rb', line 136 def remove_quotes(s) s.gsub(/"/, "") end |
#resign_apk(app_path) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/calabash-android/helpers.rb', line 71 def resign_apk(app_path) Dir.mktmpdir do |tmp_dir| log "Resign apk" unsigned_path = File.join(tmp_dir, 'unsigned.apk') FileUtils.cp(app_path, unsigned_path) `java -jar "#{File.dirname(__FILE__)}/lib/unsign.jar" "#{unsigned_path}"` sign_apk(unsigned_path, app_path) end end |
#sign_apk(app_path, dest_path) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/calabash-android/helpers.rb', line 83 def sign_apk(app_path, dest_path) keystore = read_keystore_info() if is_windows? jarsigner_path = "\"#{ENV["JAVA_HOME"]}/bin/jarsigner.exe\"" else jarsigner_path = "jarsigner" end cmd = "#{jarsigner_path} -sigalg MD5withRSA -digestalg SHA1 -signedjar #{dest_path} -storepass #{keystore["keystore_password"]} -keystore #{keystore["keystore_location"]} \"#{app_path}\" #{keystore["keystore_alias"]}" log cmd unless system(cmd) puts "jarsigner command: #{cmd}" raise "Could not sign app (#{app_path}" end end |
#test_server_path(apk_file_path) ⇒ Object
46 47 48 |
# File 'lib/calabash-android/helpers.rb', line 46 def test_server_path(apk_file_path) "test_servers/#{checksum(apk_file_path)}_#{Calabash::Android::VERSION}.apk" end |
#tools_dir ⇒ Object
100 101 102 103 104 |
# File 'lib/calabash-android/helpers.rb', line 100 def tools_dir dirs = Dir["#{android_home_path}/build-tools/*/"] + Dir["#{android_home_path}/platform-tools/"] raise "Could not find tools directory in ANDROID_HOME" if dirs.empty? dirs.first end |