ruboto-core 0.2.1 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +1 -1
- data/Gemfile.lock +8 -4
- data/README.md +1 -1
- data/Rakefile +4 -0
- data/assets/Rakefile +140 -64
- data/assets/assets/scripts/ruboto.rb +17 -26
- data/assets/res/drawable-hdpi/icon.png +0 -0
- data/assets/res/drawable-ldpi/icon.png +0 -0
- data/assets/res/drawable-mdpi/icon.png +0 -0
- data/assets/src/RubotoActivity.java +2 -0
- data/assets/src/org/ruboto/Script.java +38 -4
- data/assets/src/org/ruboto/test/InstrumentationTestRunner.java +12 -0
- data/lib/java_class_gen/android_api.xml +1 -1
- data/lib/ruboto/commands/base.rb +19 -9
- data/lib/ruboto/util/asset_copier.rb +10 -3
- data/lib/ruboto/util/build.rb +1 -1
- data/lib/ruboto/util/update.rb +110 -23
- data/lib/ruboto/util/verify.rb +24 -0
- data/lib/ruboto/util/xml_element.rb +2 -9
- data/test/activity/{image_button.rb → image_button_activity.rb} +0 -0
- data/test/activity/{image_button_test.rb → image_button_activity_test.rb} +1 -1
- data/test/activity/{image_button_and_button.rb → image_button_and_button_activity.rb} +0 -7
- data/test/activity/{image_button_and_button_test.rb → image_button_and_button_activity_test.rb} +1 -1
- data/test/activity/option_menu_activity.rb +21 -0
- data/test/activity/option_menu_activity_test.rb +20 -0
- data/test/app_test_methods.rb +24 -31
- data/test/minimal_app_test.rb +22 -0
- data/test/rake_test.rb +2 -17
- data/test/ruboto_gen_test.rb +19 -8
- data/test/ruboto_update_test.rb +8 -18
- data/test/service_test.rb +2 -4
- data/test/test_helper.rb +59 -7
- metadata +31 -13
data/COPYING
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Copyright (c)
|
1
|
+
Copyright (c) 2011 Daniel Jackoway, Charles Nutter, Scott Moyer, Uwe Kubosch
|
2
2
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
4
|
of this software and associated documentation files (the "Software"), to deal
|
data/Gemfile.lock
CHANGED
@@ -2,11 +2,15 @@ GEM
|
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
4
|
arrayfields (4.7.4)
|
5
|
-
|
5
|
+
chronic (0.6.2)
|
6
|
+
fattr (2.2.0)
|
6
7
|
jruby-jars (1.6.3)
|
7
|
-
main (4.
|
8
|
-
arrayfields (
|
9
|
-
|
8
|
+
main (4.7.3)
|
9
|
+
arrayfields (~> 4.7.4)
|
10
|
+
chronic (~> 0.6.2)
|
11
|
+
fattr (~> 2.2.0)
|
12
|
+
map (~> 4.3.0)
|
13
|
+
map (4.3.0)
|
10
14
|
|
11
15
|
PLATFORMS
|
12
16
|
java
|
data/README.md
CHANGED
@@ -40,7 +40,7 @@ Command-line Tools
|
|
40
40
|
<a name="application_generator"></a>
|
41
41
|
### Application generator
|
42
42
|
|
43
|
-
$ ruboto gen app --package com.yourdomain.whatever --path path/to/where/you/want/the/app --name NameOfApp --target android-version --
|
43
|
+
$ ruboto gen app --package com.yourdomain.whatever --path path/to/where/you/want/the/app --name NameOfApp --target android-version --min-sdk another-android-version --activity MainActivityName
|
44
44
|
Version values must be specified using'android-' and the sdk level number (e.g., android-8 is froyo).
|
45
45
|
|
46
46
|
<a name="class_generator"></a>
|
data/Rakefile
CHANGED
@@ -1,14 +1,18 @@
|
|
1
1
|
task :default => :gem
|
2
2
|
|
3
|
+
desc "Generate a gem"
|
3
4
|
task :gem do
|
4
5
|
`gem build ruboto-core.gemspec`
|
5
6
|
end
|
6
7
|
|
8
|
+
desc "Push the gem to RubyGems"
|
7
9
|
task :release do
|
8
10
|
sh "gem push #{Dir['ruboto-core-*.gem'][-1]}"
|
9
11
|
end
|
10
12
|
|
13
|
+
desc "Run the tests"
|
11
14
|
task :test do
|
15
|
+
FileUtils.rm_rf Dir['tmp/RubotoTestApp_template*']
|
12
16
|
Dir['test/*_test.rb'].each do |f|
|
13
17
|
require f.chomp('.rb')
|
14
18
|
end
|
data/assets/Rakefile
CHANGED
@@ -3,32 +3,51 @@ require 'time'
|
|
3
3
|
def manifest() @manifest ||= REXML::Document.new(File.read(MANIFEST_FILE)) end
|
4
4
|
def package() manifest.root.attribute('package') end
|
5
5
|
def build_project_name() @build_project_name ||= REXML::Document.new(File.read('build.xml')).elements['project'].attribute(:name).value end
|
6
|
-
|
7
|
-
|
8
|
-
BUNDLE_JAR = 'libs/bundle.jar'
|
9
|
-
BUNDLE_PATH = 'tmp/bundle'
|
6
|
+
def sdcard_path() @sdcard_path ||= "/mnt/sdcard/Android/data/#{package}/files" end
|
7
|
+
def app_files_path() @app_files_path ||= "/data/data/#{package}/files" end
|
10
8
|
|
11
9
|
require 'rake/clean'
|
12
10
|
require 'rexml/document'
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
MANIFEST_FILE = 'AndroidManifest.xml'
|
18
|
-
|
12
|
+
UPDATE_MARKER_FILE = File.expand_path(File.join('tmp', 'LAST_UPDATE'), File.dirname(__FILE__))
|
13
|
+
BUNDLE_JAR = File.expand_path 'libs/bundle.jar'
|
14
|
+
BUNDLE_PATH = File.expand_path 'tmp/bundle'
|
15
|
+
MANIFEST_FILE = File.expand_path 'AndroidManifest.xml'
|
16
|
+
RUBOTO_CONFIG_FILE = File.expand_path 'ruboto.yml'
|
17
|
+
GEM_FILE = File.expand_path('Gemfile.apk')
|
18
|
+
APK_FILE = File.expand_path "bin/#{build_project_name}-debug.apk"
|
19
|
+
TEST_APK_FILE = File.expand_path "test/bin/#{build_project_name}Test-debug.apk"
|
20
|
+
JRUBY_JARS = Dir[File.expand_path 'libs/jruby-*.jar']
|
21
|
+
RESOURCE_FILES = Dir[File.expand_path 'res/**/*']
|
22
|
+
JAVA_SOURCE_FILES = Dir[File.expand_path 'src/**/*.java']
|
19
23
|
|
20
24
|
CLEAN.include('tmp', 'bin')
|
21
25
|
|
22
26
|
task :default => :debug
|
23
27
|
|
24
|
-
|
25
|
-
|
26
|
-
|
28
|
+
file JRUBY_JARS => RUBOTO_CONFIG_FILE do
|
29
|
+
next unless File.exists? RUBOTO_CONFIG_FILE
|
30
|
+
jruby_jars_mtime = JRUBY_JARS.map{|f| File.mtime(f)}.min
|
31
|
+
ruboto_yml_mtime = File.mtime(RUBOTO_CONFIG_FILE)
|
32
|
+
next if jruby_jars_mtime > ruboto_yml_mtime
|
33
|
+
puts '*' * 80
|
34
|
+
if JRUBY_JARS.empty?
|
35
|
+
puts ' The JRuby jars are missing.'
|
36
|
+
else
|
37
|
+
puts " The JRuby jars need reconfiguring after changes to #{RUBOTO_CONFIG_FILE}"
|
38
|
+
puts " #{RUBOTO_CONFIG_FILE}: #{ruboto_yml_mtime}"
|
39
|
+
puts " #{JRUBY_JARS.join(', ')}: #{jruby_jars_mtime}"
|
40
|
+
end
|
41
|
+
puts ' Run "ruboto update jruby" to regenerate the JRuby jars'
|
42
|
+
puts '*' * 80
|
27
43
|
end
|
28
44
|
|
45
|
+
desc 'build debug package'
|
46
|
+
task :debug => APK_FILE
|
47
|
+
|
29
48
|
desc "build package and install it on the emulator or device"
|
30
|
-
task :install =>
|
31
|
-
|
49
|
+
task :install => APK_FILE do
|
50
|
+
install_apk
|
32
51
|
end
|
33
52
|
|
34
53
|
task :tag => :release do
|
@@ -59,67 +78,81 @@ task :emulator do
|
|
59
78
|
system 'emulator -partition-size 1024 -avd Android_3.0'
|
60
79
|
end
|
61
80
|
|
62
|
-
task :
|
81
|
+
task :start do
|
63
82
|
`adb shell am start -a android.intent.action.MAIN -n #{package}/.#{main_activity}`
|
64
83
|
end
|
65
84
|
|
66
|
-
task :
|
85
|
+
task :stop do
|
67
86
|
`adb shell ps | grep #{package} | awk '{print $2}' | xargs adb shell kill`
|
68
87
|
end
|
69
88
|
|
70
89
|
desc 'Restart the application'
|
71
|
-
task :restart => [:
|
90
|
+
task :restart => [:stop, :start]
|
72
91
|
|
73
92
|
task :uninstall do
|
74
|
-
|
75
|
-
system "adb uninstall #{package}"
|
93
|
+
uninstall_apk
|
76
94
|
end
|
77
95
|
|
78
96
|
namespace :install do
|
79
97
|
desc 'Uninstall, build, and install the application'
|
80
|
-
task :clean => [:uninstall, :install]
|
81
|
-
|
82
|
-
desc 'Build, install, and restart the application'
|
83
|
-
task :restart => [:install, :start_app]
|
84
|
-
|
85
|
-
namespace :restart do
|
86
|
-
desc 'Uninstall, build, install, and restart the application'
|
87
|
-
task :clean => [:uninstall, :install, :start_app]
|
88
|
-
end
|
98
|
+
task :clean => [:uninstall, APK_FILE, :install]
|
89
99
|
end
|
90
100
|
|
91
101
|
file MANIFEST_FILE
|
102
|
+
file RUBOTO_CONFIG_FILE
|
103
|
+
|
104
|
+
file APK_FILE => [MANIFEST_FILE, RUBOTO_CONFIG_FILE, BUNDLE_JAR] + JRUBY_JARS + JAVA_SOURCE_FILES + RESOURCE_FILES do |t|
|
105
|
+
if File.exist?(APK_FILE)
|
106
|
+
changed_prereqs = t.prerequisites.select do |p|
|
107
|
+
File.exist?(p) && !Dir[p].empty? && Dir[p].map{|f| File.mtime(f)}.max > File.mtime(APK_FILE)
|
108
|
+
end
|
92
109
|
|
93
|
-
|
94
|
-
|
95
|
-
|
110
|
+
if changed_prereqs.empty?
|
111
|
+
puts
|
112
|
+
puts 'skipping'
|
113
|
+
puts
|
114
|
+
next
|
115
|
+
end
|
116
|
+
changed_prereqs.each{|f| puts "#{f} changed."}
|
117
|
+
puts "Forcing rebuild of #{APK_FILE}."
|
118
|
+
end
|
119
|
+
sh 'ant debug'
|
96
120
|
end
|
97
121
|
|
98
122
|
desc 'Copy scripts to emulator or device'
|
99
|
-
task :update_scripts
|
100
|
-
sdcard_path
|
101
|
-
|
102
|
-
if package_installed? && device_path_exists?(sdcard_path)
|
103
|
-
puts 'Pushing files to apk public file area.'
|
123
|
+
task :update_scripts do
|
124
|
+
if device_path_exists?(sdcard_path)
|
125
|
+
data_dir_name = 'public'
|
104
126
|
data_dir = sdcard_path
|
105
|
-
elsif
|
106
|
-
|
127
|
+
elsif device_path_exists?(app_files_path)
|
128
|
+
data_dir_name = 'private'
|
107
129
|
data_dir = app_files_path
|
108
130
|
else
|
109
131
|
puts 'Cannot find the scripts directory on the device.'
|
110
|
-
|
111
|
-
|
112
|
-
|
132
|
+
unless manifest.root.elements["uses-permission[@android:name='android.permission.WRITE_EXTERNAL_STORAGE']"]
|
133
|
+
puts 'If you have a non-rooted device, you need to add'
|
134
|
+
puts %q{ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />}
|
135
|
+
puts 'to the AndroidManifest.xml file to enable the update_scripts rake task.'
|
136
|
+
end
|
113
137
|
puts "Reverting to uninstalling and re-installing the apk."
|
114
|
-
Rake::Task[
|
138
|
+
Rake::Task[:uninstall].reenable
|
139
|
+
Rake::Task[:uninstall].invoke
|
140
|
+
FileUtils.rm_f APK_FILE
|
141
|
+
Rake::Task[APK_FILE].reenable
|
142
|
+
Rake::Task[APK_FILE].invoke
|
143
|
+
Rake::Task[:install].reenable
|
144
|
+
Rake::Task[:install].invoke
|
115
145
|
next
|
116
146
|
end
|
147
|
+
Rake::Task['install'].invoke
|
148
|
+
puts "Pushing files to apk #{data_dir_name} file area."
|
117
149
|
last_update = File.exists?(UPDATE_MARKER_FILE) ? Time.parse(File.read(UPDATE_MARKER_FILE)) : Time.parse('1970-01-01T00:00:00')
|
118
150
|
Dir.chdir('assets') do
|
119
151
|
['scripts'].each do |asset_dir|
|
120
152
|
Dir["#{asset_dir}/*"].each do |asset_file|
|
121
153
|
next if File.directory? asset_file
|
122
|
-
next if File.
|
154
|
+
next if File.mtime(asset_file) < last_update
|
155
|
+
next if asset_file =~ /~$/
|
123
156
|
print "#{asset_file}: " ; $stdout.flush
|
124
157
|
`adb push #{asset_file} #{data_dir}/#{asset_file}`
|
125
158
|
end
|
@@ -130,13 +163,13 @@ end
|
|
130
163
|
|
131
164
|
namespace :update_scripts do
|
132
165
|
desc 'Copy scripts to emulator and restart the app'
|
133
|
-
task :restart => [:
|
166
|
+
task :restart => [:stop, :update_scripts, :start]
|
134
167
|
end
|
135
168
|
|
136
169
|
task :update_test_scripts do
|
137
170
|
test_scripts_path = "/data/data/#{package}.tests/files/scripts"
|
138
171
|
# TODO(uwe): Investigate if we can just push the scripts instead of building and installing the instrumentation APK
|
139
|
-
if
|
172
|
+
if package_installed?(true) && device_path_exists?(test_scripts_path)
|
140
173
|
Dir['test/assets/scripts/*.rb'].each do |script|
|
141
174
|
print "#{script}: " ; $stdout.flush
|
142
175
|
`adb push #{script} #{test_scripts_path}`
|
@@ -166,15 +199,15 @@ namespace :test do
|
|
166
199
|
end
|
167
200
|
end
|
168
201
|
|
169
|
-
file
|
202
|
+
file GEM_FILE
|
170
203
|
|
171
204
|
desc 'Generate bundle jar from Gemfile'
|
172
|
-
file BUNDLE_JAR =>
|
173
|
-
next unless File.exists?
|
205
|
+
file BUNDLE_JAR => GEM_FILE do
|
206
|
+
next unless File.exists? GEM_FILE
|
174
207
|
puts "Generating #{BUNDLE_JAR}"
|
175
208
|
|
176
209
|
FileUtils.mkdir_p BUNDLE_PATH
|
177
|
-
sh "bundle install --path=#{BUNDLE_PATH}"
|
210
|
+
sh "bundle install --gemfile #{GEM_FILE} --path=#{BUNDLE_PATH}"
|
178
211
|
|
179
212
|
# FIXME(uwe): Should not be necessary. ARJDBC should not offer the same files as AR.
|
180
213
|
|
@@ -210,6 +243,25 @@ end
|
|
210
243
|
EOF
|
211
244
|
replace_faulty_code(faulty_file, faulty_code)
|
212
245
|
end
|
246
|
+
# FIXME end
|
247
|
+
|
248
|
+
# Expand JARs
|
249
|
+
Dir.chdir "#{BUNDLE_PATH}/ruby/1.8/gems" do
|
250
|
+
Dir['*'].each do |gem_lib|
|
251
|
+
next if gem_lib =~ /jdbc-sqlite/
|
252
|
+
Dir.chdir "#{gem_lib}/lib" do
|
253
|
+
Dir['**/*.jar'].each do |jar|
|
254
|
+
puts "Expanding #{gem_lib} #{jar} into #{BUNDLE_JAR}"
|
255
|
+
|
256
|
+
`jar xf #{jar}`
|
257
|
+
FileUtils.rm_f(jar)
|
258
|
+
# FileUtils.touch(jar + '.rb')
|
259
|
+
# FileUtils.touch(jar.chomp('jar') + 'rb')
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
213
265
|
|
214
266
|
FileUtils.rm_f BUNDLE_JAR
|
215
267
|
Dir["#{BUNDLE_PATH}/ruby/1.8/gems/*"].each_with_index do |gem_dir, i|
|
@@ -220,15 +272,15 @@ end
|
|
220
272
|
Rake::Task['install'].invoke
|
221
273
|
end
|
222
274
|
|
223
|
-
task :mark_update do
|
224
|
-
mark_update
|
225
|
-
end
|
226
|
-
|
227
275
|
# Methods
|
228
276
|
|
229
|
-
def mark_update
|
277
|
+
def mark_update(time = Time.now)
|
230
278
|
FileUtils.mkdir_p File.dirname(UPDATE_MARKER_FILE)
|
231
|
-
File.open(UPDATE_MARKER_FILE, 'w'){|f| f <<
|
279
|
+
File.open(UPDATE_MARKER_FILE, 'w'){|f| f << time.iso8601}
|
280
|
+
end
|
281
|
+
|
282
|
+
def clear_update
|
283
|
+
FileUtils.rm_f UPDATE_MARKER_FILE
|
232
284
|
end
|
233
285
|
|
234
286
|
def strings(name)
|
@@ -246,22 +298,24 @@ def main_activity() manifest.root.elements['application'].elements["activity[@an
|
|
246
298
|
def device_path_exists?(path)
|
247
299
|
path_output =`adb shell ls #{path}`
|
248
300
|
result = path_output.chomp !~ /No such file or directory|opendir failed, Permission denied/
|
249
|
-
puts "Checking path on device: #{path}: #{result || path_output}"
|
250
301
|
result
|
251
302
|
end
|
252
303
|
|
253
304
|
def package_installed? test = false
|
254
305
|
package_name = "#{package}#{'.tests' if test}"
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
if o
|
259
|
-
|
260
|
-
|
306
|
+
['', '-0', '-1', '-2'].each do |i|
|
307
|
+
p = "/data/app/#{package_name}#{i}.apk"
|
308
|
+
o = `adb shell ls -l #{p}`.chomp
|
309
|
+
if o =~ /^-rw-r--r-- system\s+system\s+(\d+) \d{4}-\d{2}-\d{2} \d{2}:\d{2} #{File.basename(p)}$/
|
310
|
+
apk_file = test ? TEST_APK_FILE : APK_FILE
|
311
|
+
if !File.exists?(apk_file) || $1.to_i == File.size(apk_file)
|
312
|
+
return true
|
313
|
+
else
|
314
|
+
return false
|
315
|
+
end
|
261
316
|
end
|
262
317
|
end
|
263
|
-
|
264
|
-
return false
|
318
|
+
return nil
|
265
319
|
end
|
266
320
|
|
267
321
|
private
|
@@ -280,3 +334,25 @@ def replace_faulty_code(faulty_file, faulty_code)
|
|
280
334
|
puts "Could not find expected faulty code\n\n#{faulty_code}\n\nin file #{faulty_file}\n\n#{old_code}\n\n"
|
281
335
|
end
|
282
336
|
end
|
337
|
+
|
338
|
+
def install_apk
|
339
|
+
case package_installed?
|
340
|
+
when true
|
341
|
+
puts "Package already installed."
|
342
|
+
return
|
343
|
+
when false
|
344
|
+
puts "Package installed, but of wrong size."
|
345
|
+
end
|
346
|
+
sh 'ant ruboto-install-debug'
|
347
|
+
clear_update
|
348
|
+
end
|
349
|
+
|
350
|
+
def uninstall_apk
|
351
|
+
return if package_installed?.nil?
|
352
|
+
puts "Uninstalling package #{package}"
|
353
|
+
system "adb uninstall #{package}"
|
354
|
+
if $? != 0 && package_installed?
|
355
|
+
puts "Uninstall failed exit code #{$?}"
|
356
|
+
exit $?
|
357
|
+
end
|
358
|
+
end
|
@@ -197,8 +197,9 @@ def ruboto_configure_activity(klass)
|
|
197
197
|
|
198
198
|
p = Proc.new do |num, menu_item|
|
199
199
|
# handles a problem where this is called for context items
|
200
|
-
# JRUBY-5866 JRuby can't access nested Java class if the class is called 'id'
|
201
|
-
|
200
|
+
# TODO(uwe): JRUBY-5866 JRuby can't access nested Java class if the class is called 'id'
|
201
|
+
# TODO(uwe): Remove check for SDK version when we stop supporting api level < 11
|
202
|
+
unless @just_processed_context_item == menu_item || (android.os.Build::VERSION::SDK_INT >= 11 && menu_item.item_id == AndroidIds.home)
|
202
203
|
instance_eval &(menu_item.on_click)
|
203
204
|
@just_processed_context_item = nil
|
204
205
|
true
|
@@ -599,27 +600,17 @@ def setup_preferences
|
|
599
600
|
@preferences_setup_complete = true
|
600
601
|
end
|
601
602
|
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
#
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
# if $service
|
618
|
-
java_import "org.ruboto.RubotoService"
|
619
|
-
ruboto_setup(RubotoService)
|
620
|
-
# end
|
621
|
-
|
622
|
-
# if $broadcast_receiver
|
623
|
-
java_import "org.ruboto.RubotoBroadcastReceiver"
|
624
|
-
ruboto_setup(RubotoBroadcastReceiver, "receive")
|
625
|
-
# end
|
603
|
+
# Setup activity support
|
604
|
+
java_import "org.ruboto.RubotoActivity"
|
605
|
+
setup_activity
|
606
|
+
ruboto_configure_activity(RubotoActivity)
|
607
|
+
ruboto_setup(RubotoActivity)
|
608
|
+
setup_view
|
609
|
+
|
610
|
+
# setup service support
|
611
|
+
java_import "org.ruboto.RubotoService"
|
612
|
+
ruboto_setup(RubotoService)
|
613
|
+
|
614
|
+
# setup broadcast receiver support
|
615
|
+
java_import "org.ruboto.RubotoBroadcastReceiver"
|
616
|
+
ruboto_setup(RubotoBroadcastReceiver, "receive")
|
Binary file
|
Binary file
|
Binary file
|
@@ -127,11 +127,13 @@ THE_CONSTANTS
|
|
127
127
|
} else {
|
128
128
|
try {
|
129
129
|
new Script(scriptName).execute();
|
130
|
+
/* TODO(uwe): Add a way to add callbacks from a class or just forward all calls to the instance
|
130
131
|
rubyClassName = this.getClass().getSimpleName();
|
131
132
|
if (getRuby().get(rubyClassName) != null) {
|
132
133
|
rubyInstance = Script.exec(rubyClassName + ".new");
|
133
134
|
getRuby().callMethod(rubyInstance, "on_create", configBundle);
|
134
135
|
}
|
136
|
+
*/
|
135
137
|
} catch(IOException e){
|
136
138
|
e.printStackTrace();
|
137
139
|
ProgressDialog.show(this, "Script failed", "Something bad happened", true, true);
|