ruboto 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +19 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +21 -0
- data/README.md +293 -0
- data/Rakefile +114 -0
- data/assets/Rakefile +386 -0
- 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/res/layout/get_ruboto_core.xml +25 -0
- data/assets/samples/sample_activity.rb +21 -0
- data/assets/samples/sample_activity_test.rb +21 -0
- data/assets/samples/sample_broadcast_receiver.rb +6 -0
- data/assets/samples/sample_broadcast_receiver_test.rb +1 -0
- data/assets/samples/sample_service.rb +14 -0
- data/assets/samples/sample_service_test.rb +1 -0
- data/assets/src/InheritingActivity.java +195 -0
- data/assets/src/InheritingBroadcastReceiver.java +27 -0
- data/assets/src/InheritingClass.java +19 -0
- data/assets/src/InheritingService.java +9 -0
- data/assets/src/RubotoActivity.java +111 -0
- data/assets/src/RubotoBroadcastReceiver.java +51 -0
- data/assets/src/RubotoService.java +61 -0
- data/assets/src/org/ruboto/RubotoDialog.java +11 -0
- data/assets/src/org/ruboto/Script.java +545 -0
- data/assets/src/org/ruboto/test/ActivityTest.java +63 -0
- data/assets/src/org/ruboto/test/InstrumentationTestRunner.java +124 -0
- data/assets/src/ruboto.rb +621 -0
- data/assets/test/assets/scripts/test_helper.rb +13 -0
- data/bin/ruboto +5 -0
- data/lib/java_class_gen/InheritingClass.java.erb +10 -0
- data/lib/java_class_gen/android_api.xml +1 -0
- data/lib/ruboto.rb +16 -0
- data/lib/ruboto/api.rb +21 -0
- data/lib/ruboto/commands/base.rb +392 -0
- data/lib/ruboto/core_ext/array.rb +6 -0
- data/lib/ruboto/core_ext/object.rb +10 -0
- data/lib/ruboto/util/asset_copier.rb +27 -0
- data/lib/ruboto/util/build.rb +201 -0
- data/lib/ruboto/util/code_formatting.rb +22 -0
- data/lib/ruboto/util/log_action.rb +20 -0
- data/lib/ruboto/util/main_fix.rb +13 -0
- data/lib/ruboto/util/objectspace.rb +8 -0
- data/lib/ruboto/util/scan_in_api.rb +40 -0
- data/lib/ruboto/util/update.rb +420 -0
- data/lib/ruboto/util/verify.rb +87 -0
- data/lib/ruboto/util/xml_element.rb +200 -0
- data/lib/ruboto/version.rb +3 -0
- data/test/activity/image_button_activity.rb +21 -0
- data/test/activity/image_button_activity_test.rb +21 -0
- data/test/activity/image_button_and_button_activity.rb +24 -0
- data/test/activity/image_button_and_button_activity_test.rb +27 -0
- data/test/activity/option_menu_activity.rb +21 -0
- data/test/activity/option_menu_activity_test.rb +20 -0
- data/test/activity/stack_activity.rb +21 -0
- data/test/activity/stack_activity_test.rb +23 -0
- data/test/app_test_methods.rb +41 -0
- data/test/minimal_app_test.rb +23 -0
- data/test/rake_test.rb +40 -0
- data/test/ruboto_gen_test.rb +32 -0
- data/test/ruboto_gen_with_psych_test.rb +16 -0
- data/test/ruboto_update_test.rb +5 -0
- data/test/ruboto_update_with_psych_test.rb +18 -0
- data/test/service_test.rb +49 -0
- data/test/test_helper.rb +177 -0
- data/test/update_test_methods.rb +33 -0
- metadata +157 -0
data/assets/Rakefile
ADDED
@@ -0,0 +1,386 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
def manifest() @manifest ||= REXML::Document.new(File.read(MANIFEST_FILE)) end
|
4
|
+
def package() manifest.root.attribute('package') end
|
5
|
+
def build_project_name() @build_project_name ||= REXML::Document.new(File.read('build.xml')).elements['project'].attribute(:name).value end
|
6
|
+
def scripts_path() @sdcard_path ||= "/mnt/sdcard/Android/data/#{package}/files/scripts" end
|
7
|
+
def app_files_path() @app_files_path ||= "/data/data/#{package}/files" end
|
8
|
+
|
9
|
+
require 'rake/clean'
|
10
|
+
require 'rexml/document'
|
11
|
+
|
12
|
+
PROJECT_DIR = Dir.getwd
|
13
|
+
UPDATE_MARKER_FILE = File.expand_path(File.join('tmp', 'LAST_UPDATE'), File.dirname(__FILE__))
|
14
|
+
BUNDLE_JAR = File.expand_path 'libs/bundle.jar'
|
15
|
+
BUNDLE_PATH = File.expand_path 'tmp/bundle'
|
16
|
+
MANIFEST_FILE = File.expand_path 'AndroidManifest.xml'
|
17
|
+
RUBOTO_CONFIG_FILE = File.expand_path 'ruboto.yml'
|
18
|
+
GEM_FILE = File.expand_path('Gemfile.apk')
|
19
|
+
GEM_LOCK_FILE = File.expand_path('Gemfile.apk.lock')
|
20
|
+
RELEASE_APK_FILE = File.expand_path "bin/#{build_project_name}-release.apk"
|
21
|
+
APK_FILE = File.expand_path "bin/#{build_project_name}-debug.apk"
|
22
|
+
TEST_APK_FILE = File.expand_path "test/bin/#{build_project_name}Test-debug.apk"
|
23
|
+
JRUBY_JARS = Dir[File.expand_path 'libs/jruby-*.jar']
|
24
|
+
RESOURCE_FILES = Dir[File.expand_path 'res/**/*']
|
25
|
+
JAVA_SOURCE_FILES = Dir[File.expand_path 'src/**/*.java']
|
26
|
+
RUBY_SOURCE_FILES = Dir[File.expand_path 'src/**/*.rb']
|
27
|
+
APK_DEPENDENCIES = [MANIFEST_FILE, RUBOTO_CONFIG_FILE, BUNDLE_JAR] + JRUBY_JARS + JAVA_SOURCE_FILES + RESOURCE_FILES + RUBY_SOURCE_FILES
|
28
|
+
|
29
|
+
CLEAN.include('tmp', 'bin')
|
30
|
+
|
31
|
+
task :default => :debug
|
32
|
+
|
33
|
+
file JRUBY_JARS => RUBOTO_CONFIG_FILE do
|
34
|
+
next unless File.exists? RUBOTO_CONFIG_FILE
|
35
|
+
jruby_jars_mtime = JRUBY_JARS.map { |f| File.mtime(f) }.min
|
36
|
+
ruboto_yml_mtime = File.mtime(RUBOTO_CONFIG_FILE)
|
37
|
+
next if jruby_jars_mtime > ruboto_yml_mtime
|
38
|
+
puts '*' * 80
|
39
|
+
if JRUBY_JARS.empty?
|
40
|
+
puts ' The JRuby jars are missing.'
|
41
|
+
else
|
42
|
+
puts " The JRuby jars need reconfiguring after changes to #{RUBOTO_CONFIG_FILE}"
|
43
|
+
puts " #{RUBOTO_CONFIG_FILE}: #{ruboto_yml_mtime}"
|
44
|
+
puts " #{JRUBY_JARS.join(', ')}: #{jruby_jars_mtime}"
|
45
|
+
end
|
46
|
+
puts ' Run "ruboto update jruby" to regenerate the JRuby jars'
|
47
|
+
puts '*' * 80
|
48
|
+
end
|
49
|
+
|
50
|
+
desc 'build debug package'
|
51
|
+
task :debug => APK_FILE
|
52
|
+
|
53
|
+
namespace :debug do
|
54
|
+
desc 'build debug package if compiled files have changed'
|
55
|
+
task :quick => [MANIFEST_FILE, RUBOTO_CONFIG_FILE, BUNDLE_JAR] + JRUBY_JARS + JAVA_SOURCE_FILES + RESOURCE_FILES do |t|
|
56
|
+
build_apk(t, false)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "build package and install it on the emulator or device"
|
61
|
+
task :install => APK_FILE do
|
62
|
+
install_apk
|
63
|
+
end
|
64
|
+
|
65
|
+
namespace :install do
|
66
|
+
desc 'uninstall, build, and install the application'
|
67
|
+
task :clean => [:uninstall, APK_FILE, :install]
|
68
|
+
|
69
|
+
desc 'Install the application, but only if compiled files are changed.'
|
70
|
+
task :quick => 'debug:quick' do
|
71
|
+
install_apk
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
task :release => RELEASE_APK_FILE
|
76
|
+
|
77
|
+
file RELEASE_APK_FILE => APK_DEPENDENCIES do |t|
|
78
|
+
build_apk(t, true)
|
79
|
+
end
|
80
|
+
|
81
|
+
task :tag => :release do
|
82
|
+
unless `git branch` =~ /^\* master$/
|
83
|
+
puts "You must be on the master branch to release!"
|
84
|
+
exit!
|
85
|
+
end
|
86
|
+
sh "git commit --allow-empty -a -m 'Release #{version}'"
|
87
|
+
sh "git tag #{version}"
|
88
|
+
sh "git push origin master --tags"
|
89
|
+
#sh "gem push pkg/#{name}-#{version}.gem"
|
90
|
+
end
|
91
|
+
|
92
|
+
task :sign => :release do
|
93
|
+
sh "jarsigner -keystore #{ENV['RUBOTO_KEYSTORE']} -signedjar bin/#{build_project_name}.apk bin/#{build_project_name}-unsigned.apk #{ENV['RUBOTO_KEY_ALIAS']}"
|
94
|
+
end
|
95
|
+
|
96
|
+
task :align => :sign do
|
97
|
+
sh "zipalign 4 bin/#{build_project_name}.apk #{build_project_name}.apk"
|
98
|
+
end
|
99
|
+
|
100
|
+
task :publish => :align do
|
101
|
+
puts "#{build_project_name}.apk is ready for the market!"
|
102
|
+
end
|
103
|
+
|
104
|
+
desc 'Start the emulator with larger disk'
|
105
|
+
task :emulator do
|
106
|
+
sh 'emulator -partition-size 1024 -avd Android_3.0'
|
107
|
+
end
|
108
|
+
|
109
|
+
task :start do
|
110
|
+
start_app
|
111
|
+
end
|
112
|
+
|
113
|
+
task :stop do
|
114
|
+
raise "Unable to stop app. Only available on emulator." unless stop_app
|
115
|
+
end
|
116
|
+
|
117
|
+
desc 'Restart the application'
|
118
|
+
task :restart => [:stop, :start]
|
119
|
+
|
120
|
+
task :uninstall do
|
121
|
+
uninstall_apk
|
122
|
+
end
|
123
|
+
|
124
|
+
file MANIFEST_FILE
|
125
|
+
file RUBOTO_CONFIG_FILE
|
126
|
+
|
127
|
+
file APK_FILE => APK_DEPENDENCIES do |t|
|
128
|
+
build_apk(t, false)
|
129
|
+
end
|
130
|
+
|
131
|
+
desc 'Copy scripts to emulator or device'
|
132
|
+
task :update_scripts => ['install:quick'] do
|
133
|
+
update_scripts
|
134
|
+
end
|
135
|
+
|
136
|
+
namespace :update_scripts do
|
137
|
+
desc 'Copy scripts to emulator and restart the app'
|
138
|
+
task :restart => APK_DEPENDENCIES do |t|
|
139
|
+
if stop_app
|
140
|
+
update_scripts
|
141
|
+
else
|
142
|
+
build_apk(t, false)
|
143
|
+
install_apk
|
144
|
+
end
|
145
|
+
start_app
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
task :test => :uninstall do
|
150
|
+
Dir.chdir('test') do
|
151
|
+
puts 'Running tests'
|
152
|
+
sh "adb uninstall #{package}.tests"
|
153
|
+
sh "ant instrument install test"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
namespace :test do
|
158
|
+
task :quick => :update_scripts do
|
159
|
+
Dir.chdir('test') do
|
160
|
+
puts 'Running quick tests'
|
161
|
+
sh 'ant instrument'
|
162
|
+
sh 'ant installi'
|
163
|
+
sh "ant run-tests-quick"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
file GEM_FILE
|
169
|
+
file GEM_LOCK_FILE
|
170
|
+
|
171
|
+
desc 'Generate bundle jar from Gemfile'
|
172
|
+
task :bundle => BUNDLE_JAR
|
173
|
+
|
174
|
+
file BUNDLE_JAR => [GEM_FILE, GEM_LOCK_FILE] do
|
175
|
+
next unless File.exists? GEM_FILE
|
176
|
+
puts "Generating #{BUNDLE_JAR}"
|
177
|
+
|
178
|
+
FileUtils.mkdir_p BUNDLE_PATH
|
179
|
+
sh "bundle install --gemfile #{GEM_FILE} --path=#{BUNDLE_PATH}"
|
180
|
+
gem_path = Dir["#{BUNDLE_PATH}/*ruby/1.8/gems"][0]
|
181
|
+
|
182
|
+
if package != 'org.ruboto.core' && JRUBY_JARS.none? { |f| File.exists? f }
|
183
|
+
Dir.chdir gem_path do
|
184
|
+
Dir['activerecord-jdbc-adapter-*'].each do |g|
|
185
|
+
puts "Removing #{g} gem since it is included in the RubotoCore platform apk."
|
186
|
+
FileUtils.rm_rf g
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# Remove duplicate files
|
192
|
+
Dir.chdir gem_path do
|
193
|
+
scanned_files = []
|
194
|
+
source_files = RUBY_SOURCE_FILES.map { |f| f.gsub("#{PROJECT_DIR}/src/", '') }
|
195
|
+
Dir["*/lib/**/*"].each do |f|
|
196
|
+
next if File.directory? f
|
197
|
+
raise "Malformed file name" unless f =~ %r{^(.*?)/lib/(.*)$}
|
198
|
+
gem_name, lib_file = $1, $2
|
199
|
+
if existing_file = scanned_files.find { |sf| sf =~ %r{(.*?)/lib/#{lib_file}} }
|
200
|
+
puts "Overwriting duplicate file #{lib_file} in gem #{$1} with file in #{gem_name}"
|
201
|
+
FileUtils.rm existing_file
|
202
|
+
scanned_files.delete existing_file
|
203
|
+
elsif source_files.include? lib_file
|
204
|
+
puts "Removing duplicate file #{lib_file} in gem #{gem_name}"
|
205
|
+
puts "Already present in project source src/#{lib_file}"
|
206
|
+
FileUtils.rm f
|
207
|
+
next
|
208
|
+
end
|
209
|
+
scanned_files << f
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# Expand JARs
|
214
|
+
Dir.chdir gem_path do
|
215
|
+
Dir['*'].each do |gem_lib|
|
216
|
+
Dir.chdir "#{gem_lib}/lib" do
|
217
|
+
Dir['**/*.jar'].each do |jar|
|
218
|
+
unless jar =~ /sqlite-jdbc/
|
219
|
+
puts "Expanding #{gem_lib} #{jar} into #{BUNDLE_JAR}"
|
220
|
+
`jar xf #{jar}`
|
221
|
+
end
|
222
|
+
if jar == 'arjdbc/jdbc/adapter_java.jar'
|
223
|
+
jar_load_code = <<-END_CODE
|
224
|
+
require 'jruby'
|
225
|
+
Java::arjdbc.jdbc.AdapterJavaService.new.basicLoad(JRuby.runtime)
|
226
|
+
END_CODE
|
227
|
+
else
|
228
|
+
jar_load_code = ''
|
229
|
+
end
|
230
|
+
puts "Writing dummy JAR file #{jar + '.rb'}"
|
231
|
+
File.open(jar + '.rb', 'w') { |f| f << jar_load_code }
|
232
|
+
if jar.end_with?('.jar')
|
233
|
+
puts "Writing dummy JAR file #{jar.sub(/.jar$/, '.rb')}"
|
234
|
+
File.open(jar.sub(/.jar$/, '.rb'), 'w') { |f| f << jar_load_code }
|
235
|
+
end
|
236
|
+
FileUtils.rm_f(jar)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
|
243
|
+
FileUtils.rm_f BUNDLE_JAR
|
244
|
+
Dir["#{gem_path}/*"].each_with_index do |gem_dir, i|
|
245
|
+
`jar #{i == 0 ? 'c' : 'u'}f #{BUNDLE_JAR} -C #{gem_dir}/lib .`
|
246
|
+
end
|
247
|
+
FileUtils.rm_rf BUNDLE_PATH
|
248
|
+
end
|
249
|
+
|
250
|
+
# Methods
|
251
|
+
|
252
|
+
def mark_update(time = Time.now)
|
253
|
+
FileUtils.mkdir_p File.dirname(UPDATE_MARKER_FILE)
|
254
|
+
File.open(UPDATE_MARKER_FILE, 'w') { |f| f << time.iso8601 }
|
255
|
+
end
|
256
|
+
|
257
|
+
def clear_update
|
258
|
+
mark_update File.ctime APK_FILE
|
259
|
+
if device_path_exists?(scripts_path)
|
260
|
+
sh "adb shell rm -r #{scripts_path}"
|
261
|
+
puts "Deleted scripts directory #{scripts_path}"
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
def strings(name)
|
266
|
+
@strings ||= REXML::Document.new(File.read('res/values/strings.xml'))
|
267
|
+
value = @strings.elements["//string[@name='#{name.to_s}']"] or raise "string '#{name}' not found in strings.xml"
|
268
|
+
value.text
|
269
|
+
end
|
270
|
+
|
271
|
+
def version()
|
272
|
+
strings :version_name
|
273
|
+
end
|
274
|
+
|
275
|
+
def app_name()
|
276
|
+
strings :app_name
|
277
|
+
end
|
278
|
+
|
279
|
+
def main_activity()
|
280
|
+
manifest.root.elements['application'].elements["activity[@android:label='@string/app_name']"].attribute('android:name')
|
281
|
+
end
|
282
|
+
|
283
|
+
def device_path_exists?(path)
|
284
|
+
path_output =`adb shell ls #{path}`
|
285
|
+
result = path_output.chomp !~ /No such file or directory|opendir failed, Permission denied/
|
286
|
+
result
|
287
|
+
end
|
288
|
+
|
289
|
+
def package_installed? test = false
|
290
|
+
package_name = "#{package}#{'.tests' if test}"
|
291
|
+
['', '-0', '-1', '-2'].each do |i|
|
292
|
+
p = "/data/app/#{package_name}#{i}.apk"
|
293
|
+
o = `adb shell ls -l #{p}`.chomp
|
294
|
+
if o =~ /^-rw-r--r-- system\s+system\s+(\d+) \d{4}-\d{2}-\d{2} \d{2}:\d{2} #{File.basename(p)}$/
|
295
|
+
apk_file = test ? TEST_APK_FILE : APK_FILE
|
296
|
+
if !File.exists?(apk_file) || $1.to_i == File.size(apk_file)
|
297
|
+
return true
|
298
|
+
else
|
299
|
+
return false
|
300
|
+
end
|
301
|
+
end
|
302
|
+
end
|
303
|
+
return nil
|
304
|
+
end
|
305
|
+
|
306
|
+
private
|
307
|
+
|
308
|
+
def replace_faulty_code(faulty_file, faulty_code)
|
309
|
+
explicit_requires = Dir["#{faulty_file.chomp('.rb')}/*.rb"].sort.map { |f| File.basename(f) }.map do |filename|
|
310
|
+
"require 'active_model/validations/#{filename}'"
|
311
|
+
end.join("\n")
|
312
|
+
|
313
|
+
old_code = File.read(faulty_file)
|
314
|
+
new_code = old_code.gsub faulty_code, explicit_requires
|
315
|
+
if new_code != old_code
|
316
|
+
puts "Replaced directory listing code in file #{faulty_file} with explicit requires."
|
317
|
+
File.open(faulty_file, 'w') { |f| f << new_code }
|
318
|
+
else
|
319
|
+
puts "Could not find expected faulty code\n\n#{faulty_code}\n\nin file #{faulty_file}\n\n#{old_code}\n\n"
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
def build_apk(t, release)
|
324
|
+
apk_file = release ? RELEASE_APK_FILE : APK_FILE
|
325
|
+
if File.exist?(apk_file)
|
326
|
+
changed_prereqs = t.prerequisites.select do |p|
|
327
|
+
File.file?(p) && !Dir[p].empty? && Dir[p].map { |f| File.mtime(f) }.max > File.mtime(APK_FILE)
|
328
|
+
end
|
329
|
+
return if changed_prereqs.empty?
|
330
|
+
changed_prereqs.each { |f| puts "#{f} changed." }
|
331
|
+
puts "Forcing rebuild of #{apk_file}."
|
332
|
+
end
|
333
|
+
if release
|
334
|
+
sh 'ant release'
|
335
|
+
else
|
336
|
+
sh 'ant debug'
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
def install_apk
|
341
|
+
case package_installed?
|
342
|
+
when true
|
343
|
+
puts "Package already installed."
|
344
|
+
return
|
345
|
+
when false
|
346
|
+
puts "Package installed, but of wrong size."
|
347
|
+
end
|
348
|
+
sh 'ant installd'
|
349
|
+
clear_update
|
350
|
+
end
|
351
|
+
|
352
|
+
def uninstall_apk
|
353
|
+
return if package_installed?.nil?
|
354
|
+
puts "Uninstalling package #{package}"
|
355
|
+
system "adb uninstall #{package}"
|
356
|
+
if $? != 0 && package_installed?
|
357
|
+
puts "Uninstall failed exit code #{$?}"
|
358
|
+
exit $?
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
def update_scripts
|
363
|
+
`adb shell mkdir -p #{scripts_path}` if !device_path_exists?(scripts_path)
|
364
|
+
puts "Pushing files to apk public file area."
|
365
|
+
last_update = File.exists?(UPDATE_MARKER_FILE) ? Time.parse(File.read(UPDATE_MARKER_FILE)) : Time.parse('1970-01-01T00:00:00')
|
366
|
+
# TODO(uwe): Use `adb sync src` instead?
|
367
|
+
Dir.chdir('src') do
|
368
|
+
Dir["**/*.rb"].each do |script_file|
|
369
|
+
next if File.directory? script_file
|
370
|
+
next if File.mtime(script_file) < last_update
|
371
|
+
next if script_file =~ /~$/
|
372
|
+
print "#{script_file}: "; $stdout.flush
|
373
|
+
`adb push #{script_file} #{scripts_path}/#{script_file}`
|
374
|
+
end
|
375
|
+
end
|
376
|
+
mark_update
|
377
|
+
end
|
378
|
+
|
379
|
+
def start_app
|
380
|
+
`adb shell am start -a android.intent.action.MAIN -n #{package}/.#{main_activity}`
|
381
|
+
end
|
382
|
+
|
383
|
+
def stop_app
|
384
|
+
output = `adb shell ps | grep #{package} | awk '{print $2}' | xargs adb shell kill`
|
385
|
+
return output !~ /Operation not permitted/
|
386
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,25 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<LinearLayout
|
3
|
+
xmlns:android="http://schemas.android.com/apk/res/android"
|
4
|
+
android:layout_width="fill_parent"
|
5
|
+
android:layout_height="fill_parent"
|
6
|
+
android:orientation="vertical"
|
7
|
+
android:gravity="center_horizontal|center_vertical"
|
8
|
+
>
|
9
|
+
<!--
|
10
|
+
-->
|
11
|
+
<ImageButton
|
12
|
+
android:id="@+id/image"
|
13
|
+
android:layout_width="fill_parent"
|
14
|
+
android:layout_height="fill_parent"
|
15
|
+
android:src="@drawable/icon"
|
16
|
+
android:layout_weight="1"
|
17
|
+
android:scaleType="fitCenter"
|
18
|
+
android:onClick="getRubotoCore"
|
19
|
+
/>
|
20
|
+
<TextView android:id="@+id/text"
|
21
|
+
android:layout_width="wrap_content"
|
22
|
+
android:layout_height="wrap_content"
|
23
|
+
android:text="Welcome to Ruboto! This is the first Ruboto application installed on this device. To continue, you need to install the Ruboto Core platform package. Click on the image above to go to the market and d\
|
24
|
+
ownload and install the Ruboto Core platform package. Then return back here to start the app." />
|
25
|
+
</LinearLayout>
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'ruboto'
|
2
|
+
|
3
|
+
ruboto_import_widgets :Button, :LinearLayout, :TextView
|
4
|
+
|
5
|
+
$activity.handle_create do |bundle|
|
6
|
+
setTitle 'This is the Title'
|
7
|
+
|
8
|
+
setup_content do
|
9
|
+
linear_layout :orientation => LinearLayout::VERTICAL do
|
10
|
+
@text_view = text_view :text => 'What hath Matz wrought?', :id => 42
|
11
|
+
button :text => 'M-x butterfly', :width => :wrap_content, :id => 43
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
handle_click do |view|
|
16
|
+
if view.getText == 'M-x butterfly'
|
17
|
+
@text_view.setText 'What hath Matz wrought!'
|
18
|
+
toast 'Flipped a bit via butterfly'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
activity Java::THE_PACKAGE.SampleActivity
|
2
|
+
|
3
|
+
setup do |activity|
|
4
|
+
start = Time.now
|
5
|
+
loop do
|
6
|
+
@text_view = activity.findViewById(42)
|
7
|
+
break if @text_view || (Time.now - start > 60)
|
8
|
+
sleep 1
|
9
|
+
end
|
10
|
+
assert @text_view
|
11
|
+
end
|
12
|
+
|
13
|
+
test('initial setup') do |activity|
|
14
|
+
assert_equal "What hath Matz wrought?", @text_view.text
|
15
|
+
end
|
16
|
+
|
17
|
+
test('button changes text') do |activity|
|
18
|
+
button = activity.findViewById(43)
|
19
|
+
button.performClick
|
20
|
+
assert_equal "What hath Matz wrought!", @text_view.text
|
21
|
+
end
|