calabash-android 0.6.1.pre2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/calabash-android +91 -78
- data/bin/calabash-android-build.rb +2 -2
- data/lib/calabash-android/dependencies.rb +525 -0
- data/lib/calabash-android/environment.rb +4 -1
- data/lib/calabash-android/helpers.rb +12 -6
- data/lib/calabash-android/java_keystore.rb +3 -3
- data/lib/calabash-android/lib/TestServer.apk +0 -0
- data/lib/calabash-android/operations.rb +4 -2
- data/lib/calabash-android/version.rb +1 -1
- metadata +19 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b3ade59bc8400b324a6dec237662e305d450e29
|
4
|
+
data.tar.gz: e5619b9fa36eae19c2202ba726b7ef3d7f04268e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 37c23641f575d0ff281d61aaea3a60a8fe2e0d3d40f19cdc8ccea6e82256a3b9619ebae0d0f192a357c07f104e45ee31773344f24add9743f064dbc076d77392
|
7
|
+
data.tar.gz: 146b66bb1ad78917230a26cabf627556bb80aae44074bb218d1b39556aefe9d1b7592bdc7d19b4db77a340ea2786daada7ddd934ebf4b66a7e9c5e7190c81d4f
|
data/bin/calabash-android
CHANGED
@@ -2,15 +2,12 @@
|
|
2
2
|
|
3
3
|
require 'fileutils'
|
4
4
|
require 'rbconfig'
|
5
|
-
require 'calabash-android/helpers'
|
6
|
-
require 'calabash-android/java_keystore'
|
7
|
-
require 'calabash-android/env'
|
8
5
|
|
9
6
|
# for ruby 1.9.1 and earlier
|
10
7
|
unless defined? RbConfig.ruby
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
def RbConfig.ruby
|
9
|
+
File.join(RbConfig::CONFIG["bindir"], RbConfig::CONFIG["ruby_install_name"] + RbConfig::CONFIG["EXEEXT"])
|
10
|
+
end
|
14
11
|
end
|
15
12
|
|
16
13
|
|
@@ -32,11 +29,6 @@ end
|
|
32
29
|
|
33
30
|
|
34
31
|
require File.join(File.dirname(__FILE__), "calabash-android-helpers")
|
35
|
-
require File.join(File.dirname(__FILE__), "calabash-android-generate")
|
36
|
-
require File.join(File.dirname(__FILE__), "calabash-android-build")
|
37
|
-
require File.join(File.dirname(__FILE__), "calabash-android-run")
|
38
|
-
require File.join(File.dirname(__FILE__), "calabash-android-setup")
|
39
|
-
require File.join(File.dirname(__FILE__), "calabash-android-console")
|
40
32
|
|
41
33
|
@features_dir = File.join(FileUtils.pwd, "features")
|
42
34
|
@support_dir = File.join(@features_dir, "support")
|
@@ -44,79 +36,100 @@ require File.join(File.dirname(__FILE__), "calabash-android-console")
|
|
44
36
|
@script_dir = File.join(File.dirname(__FILE__), '..', 'scripts')
|
45
37
|
|
46
38
|
def is_apk_file?(file_path)
|
47
|
-
|
39
|
+
file_path.end_with? ".apk" and File.exist? file_path
|
48
40
|
end
|
49
41
|
|
50
42
|
def relative_to_full_path(file_path)
|
51
|
-
|
43
|
+
File.expand_path(file_path)
|
52
44
|
end
|
53
45
|
|
54
46
|
if ARGV.length == 0
|
55
|
-
|
47
|
+
print_usage
|
56
48
|
else
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
49
|
+
cmd = ARGV.shift
|
50
|
+
|
51
|
+
case cmd
|
52
|
+
when 'help'
|
53
|
+
print_help
|
54
|
+
when 'build'
|
55
|
+
require 'calabash-android/helpers'
|
56
|
+
require 'calabash-android/java_keystore'
|
57
|
+
require 'calabash-android/env'
|
58
|
+
require File.join(File.dirname(__FILE__), "calabash-android-build")
|
59
|
+
|
60
|
+
if ARGV.empty?
|
61
|
+
puts "Please specify the app you want to build a test server for"
|
62
|
+
exit 1
|
63
|
+
elsif !File.exist?(ARGV.first)
|
64
|
+
puts "Could not find file '#{ARGV.first}'"
|
65
|
+
exit 1
|
66
|
+
elsif !is_apk_file?(ARGV.first)
|
67
|
+
puts "'#{ARGV.first}' is not a valid android application"
|
68
|
+
exit 1
|
69
|
+
else
|
70
|
+
while not ARGV.empty? and is_apk_file?(ARGV.first)
|
71
|
+
calabash_build(relative_to_full_path(ARGV.shift))
|
72
|
+
end
|
73
|
+
end
|
74
|
+
when 'run'
|
75
|
+
require 'calabash-android/helpers'
|
76
|
+
require 'calabash-android/java_keystore'
|
77
|
+
require 'calabash-android/env'
|
78
|
+
require File.join(File.dirname(__FILE__), "calabash-android-run")
|
79
|
+
|
80
|
+
if ARGV.empty? or not is_apk_file?(ARGV.first)
|
81
|
+
puts "The first parameter must be the path to the apk file."
|
82
|
+
exit 1
|
83
|
+
else
|
84
|
+
exit calabash_run(relative_to_full_path(ARGV.shift))
|
85
|
+
end
|
86
|
+
when 'gen'
|
87
|
+
require 'calabash-android/helpers'
|
88
|
+
require 'calabash-android/java_keystore'
|
89
|
+
require 'calabash-android/env'
|
90
|
+
require File.join(File.dirname(__FILE__), "calabash-android-generate")
|
91
|
+
|
92
|
+
calabash_scaffold
|
93
|
+
when 'console'
|
94
|
+
require 'calabash-android/helpers'
|
95
|
+
require 'calabash-android/java_keystore'
|
96
|
+
require 'calabash-android/env'
|
97
|
+
require File.join(File.dirname(__FILE__), "calabash-android-console")
|
98
|
+
|
99
|
+
if ARGV.empty? or not is_apk_file?(ARGV.first)
|
100
|
+
puts "The first parameter must be the path to the apk file."
|
101
|
+
exit 1
|
102
|
+
else
|
103
|
+
calabash_console(relative_to_full_path(ARGV.shift))
|
104
|
+
end
|
105
|
+
when 'setup'
|
106
|
+
require 'calabash-android/helpers'
|
107
|
+
require 'calabash-android/java_keystore'
|
108
|
+
require 'calabash-android/env'
|
109
|
+
require File.join(File.dirname(__FILE__), "calabash-android-setup")
|
110
|
+
|
111
|
+
calabash_setup
|
112
|
+
when 'resign'
|
113
|
+
require 'calabash-android/helpers'
|
114
|
+
require 'calabash-android/java_keystore'
|
115
|
+
require 'calabash-android/env'
|
116
|
+
|
117
|
+
if ARGV.empty?
|
118
|
+
puts "Please specify the app you want to resign"
|
119
|
+
exit 1
|
120
|
+
elsif !File.exist?(ARGV.first)
|
121
|
+
puts "Could not find file '#{ARGV.first}'"
|
122
|
+
exit 1
|
123
|
+
elsif !is_apk_file?(ARGV.first)
|
124
|
+
puts "'#{ARGV.first}' is not a valid android application"
|
125
|
+
exit 1
|
126
|
+
else
|
127
|
+
resign_apk(File.expand_path(ARGV.first))
|
128
|
+
end
|
129
|
+
when 'version'
|
130
|
+
puts Calabash::Android::VERSION
|
131
|
+
else
|
132
|
+
puts "Invalid command '#{cmd}'"
|
133
|
+
print_usage
|
86
134
|
end
|
87
|
-
when 'gen'
|
88
|
-
calabash_scaffold
|
89
|
-
when 'console'
|
90
|
-
Env.exit_if_env_not_set_up
|
91
|
-
|
92
|
-
if ARGV.empty? or not is_apk_file?(ARGV.first)
|
93
|
-
puts "The first parameter must be the path to the apk file."
|
94
|
-
exit 1
|
95
|
-
else
|
96
|
-
calabash_console(relative_to_full_path(ARGV.shift))
|
97
|
-
end
|
98
|
-
when 'setup'
|
99
|
-
Env.exit_if_env_not_set_up
|
100
|
-
calabash_setup
|
101
|
-
when 'resign'
|
102
|
-
Env.exit_if_env_not_set_up
|
103
|
-
|
104
|
-
if ARGV.empty?
|
105
|
-
puts "Please specify the app you want to resign"
|
106
|
-
exit 1
|
107
|
-
elsif !File.exist?(ARGV.first)
|
108
|
-
puts "Could not find file '#{ARGV.first}'"
|
109
|
-
exit 1
|
110
|
-
elsif !is_apk_file?(ARGV.first)
|
111
|
-
puts "'#{ARGV.first}' is not a valid android application"
|
112
|
-
exit 1
|
113
|
-
else
|
114
|
-
resign_apk(File.expand_path(ARGV.first))
|
115
|
-
end
|
116
|
-
when 'version'
|
117
|
-
puts Calabash::Android::VERSION
|
118
|
-
else
|
119
|
-
puts "Invalid command '#{cmd}'"
|
120
|
-
print_usage
|
121
|
-
end
|
122
135
|
end
|
@@ -22,7 +22,7 @@ def calabash_build(app)
|
|
22
22
|
|
23
23
|
puts ""
|
24
24
|
puts "Notice that resigning an app might break some functionality."
|
25
|
-
puts "Getting a copy of the certificate used when the app was
|
25
|
+
puts "Getting a copy of the certificate used when the app was built will in general be more reliable."
|
26
26
|
|
27
27
|
exit 1
|
28
28
|
end
|
@@ -47,7 +47,7 @@ def calabash_build(app)
|
|
47
47
|
raise "Could not replace test package name in manifest"
|
48
48
|
end
|
49
49
|
|
50
|
-
unless system %Q{"#{
|
50
|
+
unless system %Q{"#{Calabash::Android::Dependencies.aapt_path}" package -M AndroidManifest.xml -I "#{android_platform}/android.jar" -F dummy.apk}
|
51
51
|
raise "Could not create dummy.apk"
|
52
52
|
end
|
53
53
|
|
@@ -0,0 +1,525 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
require 'luffa'
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
|
6
|
+
require 'win32/registry'
|
7
|
+
end
|
8
|
+
|
9
|
+
module Calabash
|
10
|
+
module Android
|
11
|
+
module Dependencies
|
12
|
+
private
|
13
|
+
|
14
|
+
class ScanningTimedOutError < RuntimeError; end
|
15
|
+
|
16
|
+
def self.set_android_dependencies(android_dependencies)
|
17
|
+
@@android_dependencies = android_dependencies
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.set_java_dependencies(java_dependencies)
|
21
|
+
@@java_dependencies = java_dependencies
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.android_dependencies(key)
|
25
|
+
setup unless defined?(@@android_dependencies)
|
26
|
+
|
27
|
+
if @@android_dependencies.has_key?(key)
|
28
|
+
file = @@android_dependencies[key]
|
29
|
+
|
30
|
+
unless File.exists?(file)
|
31
|
+
raise "No such file '#{file}'"
|
32
|
+
end
|
33
|
+
|
34
|
+
file
|
35
|
+
else
|
36
|
+
raise "No such dependency '#{key}'"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.java_dependencies(key)
|
41
|
+
setup unless defined?(@@java_dependencies)
|
42
|
+
|
43
|
+
if key == :ant_path
|
44
|
+
ant_executable
|
45
|
+
elsif @@java_dependencies.has_key?(key)
|
46
|
+
file = @@java_dependencies[key]
|
47
|
+
|
48
|
+
unless File.exists?(file)
|
49
|
+
raise "No such file '#{file}'"
|
50
|
+
end
|
51
|
+
|
52
|
+
file
|
53
|
+
else
|
54
|
+
raise "No such dependency '#{key}'"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
public
|
59
|
+
|
60
|
+
def self.adb_path
|
61
|
+
android_dependencies(:adb_path)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.aapt_path
|
65
|
+
android_dependencies(:aapt_path)
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.zipalign_path
|
69
|
+
android_dependencies(:zipalign_path)
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.android_jar_path
|
73
|
+
android_dependencies(:android_jar_path)
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.java_path
|
77
|
+
java_dependencies(:java_path)
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.keytool_path
|
81
|
+
java_dependencies(:keytool_path)
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.jarsigner_path
|
85
|
+
java_dependencies(:jarsigner_path)
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.ant_path
|
89
|
+
java_dependencies(:ant_path)
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.setup
|
93
|
+
if ENV['CI_NO_ANDROID_RUNTIME'] == '1'
|
94
|
+
@@android_dependencies = {}
|
95
|
+
@@java_dependencies = {}
|
96
|
+
return
|
97
|
+
end
|
98
|
+
|
99
|
+
@@halt_scanning = false
|
100
|
+
@@halt_scanning_thread = nil
|
101
|
+
|
102
|
+
if ENV['ANDROID_HOME']
|
103
|
+
android_sdk_location = ENV['ANDROID_HOME']
|
104
|
+
Logging.log_debug("Setting Android SDK location to $ANDROID_HOME")
|
105
|
+
else
|
106
|
+
android_sdk_location = detect_android_sdk_location
|
107
|
+
end
|
108
|
+
|
109
|
+
if android_sdk_location.nil?
|
110
|
+
Logging.log_error 'Could not find an Android SDK please make sure it is installed.'
|
111
|
+
Logging.log_error 'You can read about how Calabash is searching for an Android SDK and how you can help here:'
|
112
|
+
Logging.log_error 'https://github.com/calabash/calabash-android/blob/master/documentation/installation.md#prerequisites'
|
113
|
+
|
114
|
+
raise 'Could not find an Android SDK'
|
115
|
+
end
|
116
|
+
|
117
|
+
Logging.log_debug("Android SDK location set to '#{android_sdk_location}'")
|
118
|
+
|
119
|
+
@@halt_scanning_thread = Thread.new do
|
120
|
+
sleep 60
|
121
|
+
@@halt_scanning = true
|
122
|
+
end
|
123
|
+
|
124
|
+
begin
|
125
|
+
set_android_dependencies(locate_android_dependencies(android_sdk_location))
|
126
|
+
rescue ScanningTimedOutError => e
|
127
|
+
Logging.log_error 'Timed out locating Android dependency'
|
128
|
+
Logging.log_error 'You can read about how Calabash is searching for an Android SDK and how you can help here:'
|
129
|
+
Logging.log_error 'https://github.com/calabash/calabash-android/blob/master/documentation/installation.md#prerequisites'
|
130
|
+
|
131
|
+
raise e.message
|
132
|
+
rescue Environment::InvalidEnvironmentError => e
|
133
|
+
Logging.log_error 'Could not locate Android dependency'
|
134
|
+
Logging.log_error 'You can read about how Calabash is searching for an Android SDK and how you can help here:'
|
135
|
+
Logging.log_error 'https://github.com/calabash/calabash-android/blob/master/documentation/installation.md#prerequisites'
|
136
|
+
|
137
|
+
raise e
|
138
|
+
end
|
139
|
+
|
140
|
+
if ENV['JAVA_HOME']
|
141
|
+
java_sdk_home = ENV['JAVA_HOME']
|
142
|
+
Logging.log_debug("Setting Java SDK location to $JAVA_HOME")
|
143
|
+
else
|
144
|
+
java_sdk_home = detect_java_sdk_location
|
145
|
+
end
|
146
|
+
|
147
|
+
Logging.log_debug("Java SDK location set to '#{java_sdk_home}'")
|
148
|
+
|
149
|
+
Thread.kill(@@halt_scanning_thread) if @@halt_scanning_thread
|
150
|
+
@@halt_scanning = false
|
151
|
+
|
152
|
+
@@halt_scanning_thread = Thread.new do
|
153
|
+
sleep 60
|
154
|
+
@@halt_scanning = true
|
155
|
+
end
|
156
|
+
|
157
|
+
begin
|
158
|
+
set_java_dependencies(locate_java_dependencies(java_sdk_home))
|
159
|
+
rescue ScanningTimedOutError => e
|
160
|
+
Logging.log_error 'Timed out locating Java dependency'
|
161
|
+
Logging.log_error "You can read about how Calabash is searching for a JDK and how you can help here:"
|
162
|
+
Logging.log_error "https://github.com/calabash/calabash-android/blob/master/documentation/installation.md#prerequisites"
|
163
|
+
|
164
|
+
raise e.message
|
165
|
+
rescue Environment::InvalidJavaSDKHome => e
|
166
|
+
Logging.log_error "Could not find Java Development Kit please make sure it is installed."
|
167
|
+
Logging.log_error "You can read about how Calabash is searching for a JDK and how you can help here:"
|
168
|
+
Logging.log_error "https://github.com/calabash/calabash-android/blob/master/documentation/installation.md#prerequisites"
|
169
|
+
|
170
|
+
raise e
|
171
|
+
rescue Environment::InvalidEnvironmentError => e
|
172
|
+
Logging.log_error "Could not find Java dependency"
|
173
|
+
Logging.log_error "You can read about how Calabash is searching for a JDK and how you can help here:"
|
174
|
+
Logging.log_error "https://github.com/calabash/calabash-android/blob/master/documentation/installation.md#prerequisites"
|
175
|
+
|
176
|
+
raise e
|
177
|
+
end
|
178
|
+
|
179
|
+
Thread.kill(@@halt_scanning_thread) if @@halt_scanning_thread
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
def self.tools_directory
|
185
|
+
tools_directories = tools_directories(ENV['ANDROID_HOME'])
|
186
|
+
|
187
|
+
File.join(ENV['ANDROID_HOME'], tools_directories.first)
|
188
|
+
end
|
189
|
+
|
190
|
+
def self.tools_directories(android_sdk_location)
|
191
|
+
build_tools_files = list_files(File.join(android_sdk_location, 'build-tools')).select {|file| File.directory?(file)}
|
192
|
+
|
193
|
+
build_tools_directories =
|
194
|
+
build_tools_files.select do |dir|
|
195
|
+
begin
|
196
|
+
Luffa::Version.new(File.basename(dir))
|
197
|
+
true
|
198
|
+
rescue ArgumentError
|
199
|
+
false
|
200
|
+
end
|
201
|
+
end.sort do |a, b|
|
202
|
+
Luffa::Version.compare(Luffa::Version.new(File.basename(a)), Luffa::Version.new(File.basename(b)))
|
203
|
+
end.reverse.map{|dir| File.join('build-tools', File.basename(dir))}
|
204
|
+
|
205
|
+
if build_tools_directories.empty?
|
206
|
+
unless build_tools_files.reverse.first.nil?
|
207
|
+
build_tools_directories = [File.join('build-tools', File.basename(build_tools_files.reverse.first))]
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
build_tools_directories + ['platform-tools', 'tools']
|
212
|
+
end
|
213
|
+
|
214
|
+
def self.platform_directory(android_sdk_location)
|
215
|
+
files = list_files(File.join(android_sdk_location, 'platforms'))
|
216
|
+
.select {|file| File.directory?(file)}
|
217
|
+
|
218
|
+
sorted_files = files.sort_by {|item| '%08s' % item.split('-').last}.reverse
|
219
|
+
|
220
|
+
File.join('platforms', File.basename(sorted_files.first))
|
221
|
+
end
|
222
|
+
|
223
|
+
def self.locate_android_dependencies(android_sdk_location)
|
224
|
+
adb_path = scan_for_path(android_sdk_location, adb_executable, ['platform-tools'])
|
225
|
+
aapt_path = scan_for_path(android_sdk_location, aapt_executable, tools_directories(android_sdk_location))
|
226
|
+
zipalign_path = scan_for_path(android_sdk_location, zipalign_executable, tools_directories(android_sdk_location))
|
227
|
+
|
228
|
+
if adb_path.nil?
|
229
|
+
raise Environment::InvalidEnvironmentError,
|
230
|
+
"Could not find '#{adb_executable}' in '#{android_sdk_location}'"
|
231
|
+
end
|
232
|
+
|
233
|
+
if aapt_path.nil?
|
234
|
+
raise Environment::InvalidEnvironmentError,
|
235
|
+
"Could not find '#{aapt_executable}' in '#{android_sdk_location}'"
|
236
|
+
end
|
237
|
+
|
238
|
+
if zipalign_path.nil?
|
239
|
+
raise Environment::InvalidEnvironmentError,
|
240
|
+
"Could not find '#{zipalign_executable}' in '#{android_sdk_location}'"
|
241
|
+
end
|
242
|
+
|
243
|
+
Logging.log_debug("Set aapt path to '#{aapt_path}'")
|
244
|
+
Logging.log_debug("Set zipalign path to '#{zipalign_path}'")
|
245
|
+
Logging.log_debug("Set adb path to '#{adb_path}'")
|
246
|
+
|
247
|
+
android_jar_path = scan_for_path(File.join(android_sdk_location, 'platforms'), 'android.jar', [File.basename(platform_directory(android_sdk_location))])
|
248
|
+
|
249
|
+
if android_jar_path.nil?
|
250
|
+
raise Environment::InvalidEnvironmentError,
|
251
|
+
"Could not find 'android.jar' in '#{File.join(android_sdk_location, 'platforms')}'"
|
252
|
+
end
|
253
|
+
|
254
|
+
Logging.log_debug("Set android jar path to '#{android_jar_path}'")
|
255
|
+
|
256
|
+
{
|
257
|
+
aapt_path: aapt_path,
|
258
|
+
zipalign_path: zipalign_path,
|
259
|
+
adb_path: adb_path,
|
260
|
+
android_jar_path: android_jar_path
|
261
|
+
}
|
262
|
+
end
|
263
|
+
|
264
|
+
def self.locate_java_dependencies(java_sdk_location)
|
265
|
+
# For the Java dependencies, we will use the PATH elements of they exist
|
266
|
+
on_path = find_executable_on_path(java_executable)
|
267
|
+
|
268
|
+
if on_path
|
269
|
+
Logging.log_debug('Found java on PATH')
|
270
|
+
java_path = on_path
|
271
|
+
else
|
272
|
+
if java_sdk_location.nil? || java_sdk_location.empty?
|
273
|
+
raise Environment::InvalidJavaSDKHome,
|
274
|
+
"Could not locate '#{java_executable}' on path, and Java SDK Home is invalid."
|
275
|
+
end
|
276
|
+
|
277
|
+
java_path = scan_for_path(java_sdk_location, java_executable, ['bin'])
|
278
|
+
end
|
279
|
+
|
280
|
+
Logging.log_debug("Set java path to '#{java_path}'")
|
281
|
+
|
282
|
+
on_path = find_executable_on_path(keytool_executable)
|
283
|
+
|
284
|
+
if on_path
|
285
|
+
Logging.log_debug('Found keytool on PATH')
|
286
|
+
keytool_path = on_path
|
287
|
+
else
|
288
|
+
if java_sdk_location.nil? || java_sdk_location.empty?
|
289
|
+
raise Environment::InvalidJavaSDKHome,
|
290
|
+
"Could not locate '#{keytool_executable}' on path, and Java SDK Home is invalid."
|
291
|
+
end
|
292
|
+
|
293
|
+
keytool_path = scan_for_path(java_sdk_location, keytool_executable, ['bin'])
|
294
|
+
end
|
295
|
+
|
296
|
+
Logging.log_debug("Set keytool path to '#{keytool_path}'")
|
297
|
+
|
298
|
+
on_path = find_executable_on_path(jarsigner_executable)
|
299
|
+
|
300
|
+
if on_path
|
301
|
+
Logging.log_debug('Found jarsigner on PATH')
|
302
|
+
jarsigner_path = on_path
|
303
|
+
else
|
304
|
+
if java_sdk_location.nil? || java_sdk_location.empty?
|
305
|
+
raise Environment::InvalidJavaSDKHome,
|
306
|
+
"Could not locate '#{jarsigner_executable}' on path, and Java SDK Home is invalid."
|
307
|
+
end
|
308
|
+
|
309
|
+
jarsigner_path = scan_for_path(java_sdk_location, jarsigner_executable, ['bin'])
|
310
|
+
end
|
311
|
+
|
312
|
+
Logging.log_debug("Set jarsigner path to '#{jarsigner_path}'")
|
313
|
+
|
314
|
+
if java_path.nil?
|
315
|
+
raise Environment::InvalidEnvironmentError,
|
316
|
+
"Could not find '#{java_executable}' on PATH or in '#{java_sdk_location}'"
|
317
|
+
end
|
318
|
+
|
319
|
+
if keytool_path.nil?
|
320
|
+
raise Environment::InvalidEnvironmentError,
|
321
|
+
"Could not find '#{keytool_executable}' on PATH or in '#{java_sdk_location}'"
|
322
|
+
end
|
323
|
+
|
324
|
+
if jarsigner_path.nil?
|
325
|
+
raise Environment::InvalidEnvironmentError,
|
326
|
+
"Could not find '#{jarsigner_executable}' on PATH or in '#{java_sdk_location}'"
|
327
|
+
end
|
328
|
+
|
329
|
+
{
|
330
|
+
java_path: java_path,
|
331
|
+
keytool_path: keytool_path,
|
332
|
+
jarsigner_path: jarsigner_path
|
333
|
+
}
|
334
|
+
end
|
335
|
+
|
336
|
+
def self.halt_scanning?
|
337
|
+
@@halt_scanning
|
338
|
+
end
|
339
|
+
|
340
|
+
def self.scan_for_path(path, file_name, expected_sub_folders = nil)
|
341
|
+
if self.halt_scanning?
|
342
|
+
Logging.log_error("Timed out looking for '#{file_name}', currently looking in '#{path}'")
|
343
|
+
raise ScanningTimedOutError, "Timed out looking for '#{file_name}'"
|
344
|
+
end
|
345
|
+
|
346
|
+
# Optimization for expected folders
|
347
|
+
if expected_sub_folders && !expected_sub_folders.empty?
|
348
|
+
expected_sub_folders.each do |expected_sub_folder|
|
349
|
+
result = scan_for_path(File.join(path, expected_sub_folder), file_name)
|
350
|
+
|
351
|
+
return result if result
|
352
|
+
end
|
353
|
+
|
354
|
+
Logging.log_warn("Did not find '#{file_name}' in any standard directory of '#{path}'. Calabash will therefore take longer to load")
|
355
|
+
Logging.log_debug(" - Expected to find '#{file_name}' in any of:")
|
356
|
+
|
357
|
+
expected_sub_folders.each do |expected_sub_folder|
|
358
|
+
Logging.log_debug(" - #{File.join(path, expected_sub_folder)}")
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
files = list_files(path).sort.reverse
|
363
|
+
|
364
|
+
if files.reject{|file| File.directory?(file)}.
|
365
|
+
map{|file| File.basename(file)}.include?(file_name)
|
366
|
+
return File.join(path, file_name)
|
367
|
+
else
|
368
|
+
files.select{|file| File.directory?(file)}.each do |dir|
|
369
|
+
result = scan_for_path(dir, file_name)
|
370
|
+
|
371
|
+
return result if result
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
nil
|
376
|
+
end
|
377
|
+
|
378
|
+
def self.detect_android_sdk_location
|
379
|
+
if File.exist?(monodroid_config_file)
|
380
|
+
sdk_location = read_attribute_from_monodroid_config('android-sdk', 'path')
|
381
|
+
|
382
|
+
if sdk_location
|
383
|
+
Logging.log_debug("Setting Android SDK location from '#{monodroid_config_file}'")
|
384
|
+
|
385
|
+
return sdk_location
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
if File.exist?('~/Library/Developer/Xamarin/android-sdk-mac_x86/')
|
390
|
+
return '~/Library/Developer/Xamarin/android-sdk-mac_x86/'
|
391
|
+
end
|
392
|
+
|
393
|
+
if File.exist?('C:\\Android\\android-sdk')
|
394
|
+
return 'C:\\Android\\android-sdk'
|
395
|
+
end
|
396
|
+
|
397
|
+
if is_windows?
|
398
|
+
from_registry = read_registry(::Win32::Registry::HKEY_CURRENT_USER, "Software\\Novell\\Mono for Android", 'AndroidSdkDirectory')
|
399
|
+
|
400
|
+
if from_registry && File.exist?(from_registry)
|
401
|
+
Logging.log_debug("Setting Android SDK location from HKEY_CURRENT_USER Software\\Novell\\Mono for Android")
|
402
|
+
return from_registry
|
403
|
+
end
|
404
|
+
|
405
|
+
from_registry = read_registry(::Win32::Registry::HKEY_LOCAL_MACHINE, 'Software\\Android SDK Tools', 'Path')
|
406
|
+
|
407
|
+
if from_registry && File.exist?(from_registry)
|
408
|
+
Logging.log_debug("Setting Android SDK location from HKEY_LOCAL_MACHINE Software\\Android SDK Tools")
|
409
|
+
return from_registry
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
nil
|
414
|
+
end
|
415
|
+
|
416
|
+
def self.detect_java_sdk_location
|
417
|
+
if File.exist?(monodroid_config_file)
|
418
|
+
sdk_location = read_attribute_from_monodroid_config('java-sdk', 'path')
|
419
|
+
|
420
|
+
if sdk_location
|
421
|
+
Logging.log_debug("Setting Java SDK location from '#{monodroid_config_file}'")
|
422
|
+
|
423
|
+
return sdk_location
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
java_versions = ['1.9', '1.8', '1.7', '1.6']
|
428
|
+
|
429
|
+
if is_windows?
|
430
|
+
java_versions.each do |java_version|
|
431
|
+
key = "SOFTWARE\\JavaSoft\\Java Development Kit\\#{java_version}"
|
432
|
+
from_registry = read_registry(::Win32::Registry::HKEY_LOCAL_MACHINE, key, 'JavaHome')
|
433
|
+
|
434
|
+
if from_registry && File.exist?(from_registry)
|
435
|
+
Logging.log_debug("Setting Java SDK location from HKEY_LOCAL_MACHINE #{key}")
|
436
|
+
return from_registry
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
nil
|
442
|
+
end
|
443
|
+
|
444
|
+
def self.monodroid_config_file
|
445
|
+
File.expand_path('~/.config/xbuild/monodroid-config.xml')
|
446
|
+
end
|
447
|
+
|
448
|
+
def self.read_attribute_from_monodroid_config(element, attribute)
|
449
|
+
element = REXML::Document.new(IO.read(monodroid_config_file)).elements["//#{element}"]
|
450
|
+
|
451
|
+
if element
|
452
|
+
element.attributes[attribute]
|
453
|
+
else
|
454
|
+
nil
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
def self.find_executable_on_path(executable)
|
459
|
+
path_elements.each do |x|
|
460
|
+
f = File.join(x, executable)
|
461
|
+
return f if File.exists?(f)
|
462
|
+
end
|
463
|
+
|
464
|
+
nil
|
465
|
+
end
|
466
|
+
|
467
|
+
def self.path_elements
|
468
|
+
return [] unless ENV['PATH']
|
469
|
+
ENV['PATH'].split (/[:;]/)
|
470
|
+
end
|
471
|
+
|
472
|
+
def self.zipalign_executable
|
473
|
+
is_windows? ? 'zipalign.exe' : 'zipalign'
|
474
|
+
end
|
475
|
+
|
476
|
+
def self.jarsigner_executable
|
477
|
+
is_windows? ? 'jarsigner.exe' : 'jarsigner'
|
478
|
+
end
|
479
|
+
|
480
|
+
def self.java_executable
|
481
|
+
is_windows? ? 'java.exe' : 'java'
|
482
|
+
end
|
483
|
+
|
484
|
+
def self.keytool_executable
|
485
|
+
is_windows? ? 'keytool.exe' : 'keytool'
|
486
|
+
end
|
487
|
+
|
488
|
+
def self.adb_executable
|
489
|
+
is_windows? ? 'adb.exe' : 'adb'
|
490
|
+
end
|
491
|
+
|
492
|
+
def self.aapt_executable
|
493
|
+
is_windows? ? 'aapt.exe' : 'aapt'
|
494
|
+
end
|
495
|
+
|
496
|
+
def self.ant_executable
|
497
|
+
is_windows? ? 'ant.exe' : 'ant'
|
498
|
+
end
|
499
|
+
|
500
|
+
def self.is_windows?
|
501
|
+
(RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
|
502
|
+
end
|
503
|
+
|
504
|
+
def self.read_registry(root_key, key, value)
|
505
|
+
begin
|
506
|
+
root_key.open(key)[value]
|
507
|
+
rescue
|
508
|
+
nil
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
512
|
+
def self.list_files(path)
|
513
|
+
# Dir.glob does not accept backslashes, even on windows. We have to
|
514
|
+
# substitute all backwards slashes to forward.
|
515
|
+
# C:\foo becomes C:/foo
|
516
|
+
|
517
|
+
if is_windows?
|
518
|
+
Dir.glob(File.join(path, '*').gsub('\\', '/'))
|
519
|
+
else
|
520
|
+
Dir.glob(File.join(path, '*'))
|
521
|
+
end
|
522
|
+
end
|
523
|
+
end
|
524
|
+
end
|
525
|
+
end
|
@@ -1,8 +1,11 @@
|
|
1
1
|
module Calabash
|
2
2
|
module Android
|
3
|
-
|
4
3
|
# @!visibility private
|
5
4
|
class Environment
|
5
|
+
# @!visibility private
|
6
|
+
class InvalidEnvironmentError < RuntimeError; end
|
7
|
+
# @!visibility private
|
8
|
+
class InvalidJavaSDKHome < RuntimeError; end
|
6
9
|
|
7
10
|
# @!visibility private
|
8
11
|
# Returns true if running on Windows
|
@@ -4,6 +4,10 @@ require 'tempfile'
|
|
4
4
|
require 'escape'
|
5
5
|
require 'rbconfig'
|
6
6
|
require 'calabash-android/java_keystore'
|
7
|
+
require 'calabash-android/environment'
|
8
|
+
require 'calabash-android/logging'
|
9
|
+
require 'calabash-android/dependencies'
|
10
|
+
require 'calabash-android/version'
|
7
11
|
|
8
12
|
def package_name(app)
|
9
13
|
unless File.exist?(app)
|
@@ -33,7 +37,7 @@ def main_activity(app)
|
|
33
37
|
rescue => e
|
34
38
|
log("Could not find launchable activity, trying to parse raw AndroidManifest. #{e.message}")
|
35
39
|
|
36
|
-
manifest_data = `"#{
|
40
|
+
manifest_data = `"#{Calabash::Android::Dependencies.aapt_path}" dump xmltree "#{app}" AndroidManifest.xml`
|
37
41
|
regex = /^\s*A:[\s*]android:name\(\w+\)\=\"android.intent.category.LAUNCHER\"/
|
38
42
|
lines = manifest_data.lines.collect(&:strip)
|
39
43
|
indicator_line = nil
|
@@ -77,7 +81,7 @@ def main_activity(app)
|
|
77
81
|
end
|
78
82
|
|
79
83
|
def aapt_dump(app, key)
|
80
|
-
lines = `"#{
|
84
|
+
lines = `"#{Calabash::Android::Dependencies.aapt_path}" dump badging "#{app}"`.lines.collect(&:strip)
|
81
85
|
lines.select { |l| l.start_with?("#{key}:") }
|
82
86
|
end
|
83
87
|
|
@@ -97,6 +101,8 @@ def build_test_server_if_needed(app_path)
|
|
97
101
|
exit 1
|
98
102
|
else
|
99
103
|
puts "No test server found for this combination of app and calabash version. Recreating test server."
|
104
|
+
require 'calabash-android/operations'
|
105
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'bin', 'calabash-android-build')
|
100
106
|
calabash_build(app_path)
|
101
107
|
end
|
102
108
|
end
|
@@ -115,7 +121,7 @@ def resign_apk(app_path)
|
|
115
121
|
end
|
116
122
|
|
117
123
|
def unsign_apk(path)
|
118
|
-
meta_files = `"#{
|
124
|
+
meta_files = `"#{Calabash::Android::Dependencies.aapt_path}" list "#{path}"`.lines.collect(&:strip).grep(/^META-INF\//)
|
119
125
|
|
120
126
|
signing_file_names = ['.mf', '.rsa', '.dsa', '.ec', '.sf']
|
121
127
|
|
@@ -137,12 +143,12 @@ def unsign_apk(path)
|
|
137
143
|
if files_to_remove.empty?
|
138
144
|
log "App wasn't signed. Will not try to unsign it."
|
139
145
|
else
|
140
|
-
system("\"#{
|
146
|
+
system("\"#{Calabash::Android::Dependencies.aapt_path}\" remove \"#{path}\" #{files_to_remove.join(" ")}")
|
141
147
|
end
|
142
148
|
end
|
143
149
|
|
144
150
|
def zipalign_apk(inpath, outpath)
|
145
|
-
cmd = %Q("#{
|
151
|
+
cmd = %Q("#{Calabash::Android::Dependencies.zipalign_path}" -f 4 "#{inpath}" "#{outpath}")
|
146
152
|
log "Zipaligning using: #{cmd}"
|
147
153
|
system(cmd)
|
148
154
|
end
|
@@ -177,7 +183,7 @@ def fingerprint_from_apk(app_path)
|
|
177
183
|
raise "No signature files found in META-INF. Cannot proceed." if signature_files.empty?
|
178
184
|
raise "More than one signature file (DSA or RSA) found in META-INF. Cannot proceed." if signature_files.length > 1
|
179
185
|
|
180
|
-
cmd = "#{
|
186
|
+
cmd = "#{Calabash::Android::Dependencies.keytool_path} -v -printcert -J\"-Dfile.encoding=utf-8\" -file \"#{signature_files.first}\""
|
181
187
|
log cmd
|
182
188
|
fingerprints = `#{cmd}`
|
183
189
|
md5_fingerprint = extract_md5_fingerprint(fingerprints)
|
@@ -6,13 +6,13 @@ class JavaKeystore
|
|
6
6
|
raise "No such keystore file '#{location}'" unless File.exists?(File.expand_path(location))
|
7
7
|
log "Reading keystore data from keystore file '#{File.expand_path(location)}'"
|
8
8
|
|
9
|
-
keystore_data = system_with_stdout_on_success(
|
9
|
+
keystore_data = system_with_stdout_on_success(Calabash::Android::Dependencies.keytool_path, '-list', '-v', '-alias', keystore_alias, '-keystore', location, '-storepass', password, '-J"-Dfile.encoding=utf-8"', '-J"-Duser.language=en-US"')
|
10
10
|
|
11
11
|
if keystore_data.nil?
|
12
12
|
if keystore_alias.empty?
|
13
13
|
log "Could not obtain keystore data. Will try to extract alias automatically"
|
14
14
|
|
15
|
-
keystore_data = system_with_stdout_on_success(
|
15
|
+
keystore_data = system_with_stdout_on_success(Calabash::Android::Dependencies.keytool_path, '-list', '-v', '-keystore', location, '-storepass', password, '-J"-Dfile.encoding=utf-8"', '-J"-Duser.language=en-US"')
|
16
16
|
aliases = keystore_data.scan(/Alias name\:\s*(.*)/).flatten
|
17
17
|
|
18
18
|
if aliases.length == 0
|
@@ -56,7 +56,7 @@ class JavaKeystore
|
|
56
56
|
log "Signing using the signature algorithm: '#{signing_algorithm}'"
|
57
57
|
log "Signing using the digest algorithm: '#{digest_algorithm}'"
|
58
58
|
|
59
|
-
unless system_with_stdout_on_success(
|
59
|
+
unless system_with_stdout_on_success(Calabash::Android::Dependencies.jarsigner_path, '-sigfile', 'CERT', '-sigalg', signing_algorithm, '-digestalg', digest_algorithm, '-signedjar', dest_path, '-storepass', password, '-keystore', location, apk_path, keystore_alias)
|
60
60
|
raise "Could not sign app: #{apk_path}"
|
61
61
|
end
|
62
62
|
end
|
Binary file
|
@@ -20,12 +20,14 @@ require 'calabash-android/dot_dir'
|
|
20
20
|
require 'calabash-android/logging'
|
21
21
|
require 'calabash-android/store/preferences'
|
22
22
|
require 'calabash-android/usage_tracker'
|
23
|
+
require 'calabash-android/dependencies'
|
23
24
|
require 'retriable'
|
24
25
|
require 'cucumber'
|
25
26
|
require 'date'
|
26
27
|
require 'time'
|
27
28
|
require 'shellwords'
|
28
29
|
|
30
|
+
Calabash::Android::Dependencies.setup
|
29
31
|
|
30
32
|
module Calabash module Android
|
31
33
|
|
@@ -558,7 +560,7 @@ module Calabash module Android
|
|
558
560
|
end
|
559
561
|
|
560
562
|
def adb_command
|
561
|
-
"#{
|
563
|
+
"\"#{Calabash::Android::Dependencies.adb_path}\" -s #{serial}"
|
562
564
|
end
|
563
565
|
|
564
566
|
def default_serial
|
@@ -595,7 +597,7 @@ module Calabash module Android
|
|
595
597
|
end
|
596
598
|
|
597
599
|
def connected_devices
|
598
|
-
lines =
|
600
|
+
lines = `"#{Calabash::Android::Dependencies.adb_path}" devices`.split("\n")
|
599
601
|
start_index = lines.index{ |x| x =~ /List of devices attached/ } + 1
|
600
602
|
lines[start_index..-1].collect { |l| l.split("\t").first }
|
601
603
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: calabash-android
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jonas Maturana Larsen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: cucumber
|
@@ -134,6 +134,20 @@ dependencies:
|
|
134
134
|
- - "~>"
|
135
135
|
- !ruby/object:Gem::Version
|
136
136
|
version: 0.0.4
|
137
|
+
- !ruby/object:Gem::Dependency
|
138
|
+
name: luffa
|
139
|
+
requirement: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '0'
|
144
|
+
type: :runtime
|
145
|
+
prerelease: false
|
146
|
+
version_requirements: !ruby/object:Gem::Requirement
|
147
|
+
requirements:
|
148
|
+
- - ">="
|
149
|
+
- !ruby/object:Gem::Version
|
150
|
+
version: '0'
|
137
151
|
- !ruby/object:Gem::Dependency
|
138
152
|
name: rake
|
139
153
|
requirement: !ruby/object:Gem::Requirement
|
@@ -318,6 +332,7 @@ files:
|
|
318
332
|
- lib/calabash-android/color_helper.rb
|
319
333
|
- lib/calabash-android/cucumber.rb
|
320
334
|
- lib/calabash-android/defaults.rb
|
335
|
+
- lib/calabash-android/dependencies.rb
|
321
336
|
- lib/calabash-android/deprecated_actions.map
|
322
337
|
- lib/calabash-android/dot_dir.rb
|
323
338
|
- lib/calabash-android/drag_helpers.rb
|
@@ -374,9 +389,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
374
389
|
version: '0'
|
375
390
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
376
391
|
requirements:
|
377
|
-
- - "
|
392
|
+
- - ">="
|
378
393
|
- !ruby/object:Gem::Version
|
379
|
-
version:
|
394
|
+
version: '0'
|
380
395
|
requirements: []
|
381
396
|
rubyforge_project:
|
382
397
|
rubygems_version: 2.4.5.1
|