diff --git a/ruby-gem/lib/calabash-android/dependencies.rb b/ruby-gem/lib/calabash-android/dependencies.rb index eaa8c43d..5c1cdb12 100644 --- a/ruby-gem/lib/calabash-android/dependencies.rb +++ b/ruby-gem/lib/calabash-android/dependencies.rb @@ -68,6 +68,10 @@ def self.zipalign_path android_dependencies(:zipalign_path) end + def self.apksigner_path + android_dependencies(:apksigner_path) + end + def self.android_jar_path android_dependencies(:android_jar_path) end @@ -229,6 +233,12 @@ def self.locate_android_dependencies(android_sdk_location) aapt_path = scan_for_path(android_sdk_location, aapt_executable, tools_directories(android_sdk_location)) zipalign_path = scan_for_path(android_sdk_location, zipalign_executable, tools_directories(android_sdk_location)) + if ENV['APKSIGNER_PATH'] + apksigner_path = ENV['APKSIGNER_PATH'] + else + apksigner_path = scan_for_path(android_sdk_location, apksigner_executable, tools_directories(android_sdk_location)) + end + if adb_path.nil? raise Environment::InvalidEnvironmentError, "Could not find '#{adb_executable}' in '#{android_sdk_location}'" @@ -244,8 +254,14 @@ def self.locate_android_dependencies(android_sdk_location) "Could not find '#{zipalign_executable}' in '#{android_sdk_location}'" end + if apksigner_path.nil? + raise Environment::InvalidEnvironmentError, + "Could not find '#{apksigner_executable}' in '#{android_sdk_location}'" + end + Logging.log_debug("Set aapt path to '#{aapt_path}'") Logging.log_debug("Set zipalign path to '#{zipalign_path}'") + Logging.log_debug("Set apksigner path to '#{apksigner_path}'") Logging.log_debug("Set adb path to '#{adb_path}'") android_jar_path = scan_for_path(File.join(android_sdk_location, 'platforms'), 'android.jar', [File.basename(platform_directory(android_sdk_location))]) @@ -260,6 +276,7 @@ def self.locate_android_dependencies(android_sdk_location) { aapt_path: aapt_path, zipalign_path: zipalign_path, + apksigner_path: apksigner_path, adb_path: adb_path, android_jar_path: android_jar_path } @@ -486,6 +503,10 @@ def self.zipalign_executable is_windows? ? 'zipalign.exe' : 'zipalign' end + def self.apksigner_executable + is_windows? ? 'apksigner.exe' : 'apksigner' + end + def self.jarsigner_executable is_windows? ? 'jarsigner.exe' : 'jarsigner' end diff --git a/ruby-gem/lib/calabash-android/helpers.rb b/ruby-gem/lib/calabash-android/helpers.rb index 7a3bad28..7ac6f91c 100755 --- a/ruby-gem/lib/calabash-android/helpers.rb +++ b/ruby-gem/lib/calabash-android/helpers.rb @@ -92,7 +92,11 @@ def checksum(file_path) end def test_server_path(apk_file_path) - "test_servers/#{checksum(apk_file_path)}_#{Calabash::Android::VERSION}.apk" + if ENV['TEST_APP_PATH'] + ENV['TEST_APP_PATH'] + else + "test_servers/#{checksum(apk_file_path)}_#{Calabash::Android::VERSION}.apk" + end end def build_test_server_if_needed(app_path) @@ -166,46 +170,25 @@ def sign_apk(app_path, dest_path) 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") - - Calabash::Utils.with_silent_zip do - Zip::File.foreach("app.apk") do |z| - z.extract if /^META-INF\/\w+\.(rsa|dsa)$/i =~ z.name - end - end - - signature_files = Dir["#{tmp_dir}/META-INF/*"] - - log 'Signature files:' - - signature_files.each do |signature_file| - log signature_file - end - - raise "No signature files found in META-INF. Cannot proceed." if signature_files.empty? - raise "More than one signature file (DSA or RSA) found in META-INF. Cannot proceed." if signature_files.length > 1 - - cmd = "\"#{Calabash::Android::Dependencies.keytool_path}\" -v -printcert -J\"-Dfile.encoding=utf-8\" -file \"#{signature_files.first}\"" - log cmd - fingerprints = `#{cmd}` - md5_fingerprint = extract_sha1_fingerprint(fingerprints) - log "SHA1 fingerprint for signing cert (#{app_path}): #{md5_fingerprint}" - md5_fingerprint - end - end -end - -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 + cmd = "\"#{Calabash::Android::Dependencies.apksigner_path}\" verify --print-certs --verbose \"#{app_path}\"" + log cmd + fingerprints = `#{cmd}` + sha1_fingerprint = extract_sha1_fingerprint(fingerprints) + log "SHA1 fingerprint for signing cert (#{app_path}): #{sha1_fingerprint}" + sha1_fingerprint end def extract_sha1_fingerprint(fingerprints) - m = fingerprints.scan(/SHA1.*((?:[a-fA-F\d]{2}:){15}[a-fA-F\d]{2})/).flatten + # Try to parse keytool data + m = fingerprints.scan(/SHA1.*((?:[a-fA-F\d]{2}:){19}[a-fA-F\d]{2})/).flatten + if m.empty? + # Try to parse apksigner data + m = fingerprints.scan(/SHA-1.*\b([a-f0-9]{40})\b/).flatten + # Transform it to keytool compatible format + unless m.empty? + return m.first.scan(/../).map(&:upcase).join(':') + end + end raise "No SHA1 fingerprint found:\n #{fingerprints}" if m.empty? m.first end diff --git a/ruby-gem/lib/calabash-android/java_keystore.rb b/ruby-gem/lib/calabash-android/java_keystore.rb index 3d351f2c..dca78e7b 100755 --- a/ruby-gem/lib/calabash-android/java_keystore.rb +++ b/ruby-gem/lib/calabash-android/java_keystore.rb @@ -62,23 +62,21 @@ def sign_apk(apk_path, dest_path) log "Signing using the digest algorithm: '#{digest_algorithm}'" cmd_args = { - '-sigfile' => 'CERT', - '-sigalg' => signing_algorithm, - '-digestalg' => digest_algorithm, - '-signedjar' => dest_path, - '-storepass' => password, - '-keystore' => location, + '--out' => dest_path, + '--ks-key-alias' => keystore_alias, + '--ks-pass' => "pass:#{password}", + '--ks' => location, } unless @key_password.nil? - cmd_args['-keypass'] = @key_password + cmd_args['--key-pass'] = "pass:#{@key_password}" end cmd_args = cmd_args.flatten + cmd_args.unshift('sign') cmd_args << apk_path - cmd_args << keystore_alias - result = system_with_stdout_on_success(Calabash::Android::Dependencies.jarsigner_path, *cmd_args) + result = system_with_stdout_on_success(Calabash::Android::Dependencies.apksigner_path, *cmd_args) unless result raise "Could not sign app: #{apk_path}" diff --git a/ruby-gem/lib/calabash-android/version.rb b/ruby-gem/lib/calabash-android/version.rb index 3425ef72..3ea26b85 100644 --- a/ruby-gem/lib/calabash-android/version.rb +++ b/ruby-gem/lib/calabash-android/version.rb @@ -1,7 +1,7 @@ module Calabash module Android - VERSION = "0.9.12.uia10" + VERSION = "0.9.12.uia11" # Server Commit 6b8a1ad9b645df91a297d4c85ff202e6f0cdda27 patch AccessibilityNodeInfoDumper to include all the non-visible elements and dump everything