ruboto-core 0.3.3 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +3 -3
- data/Rakefile +75 -0
- data/assets/Rakefile +76 -85
- data/assets/res/layout/get_ruboto_core.xml +25 -0
- data/assets/samples/sample_broadcast_receiver.rb +1 -2
- data/assets/src/InheritingActivity.java +181 -5
- data/assets/src/InheritingBroadcastReceiver.java +22 -5
- data/assets/src/InheritingClass.java +4 -13
- data/assets/src/RubotoActivity.java +78 -118
- data/assets/src/RubotoBroadcastReceiver.java +31 -50
- data/assets/src/RubotoService.java +13 -28
- data/assets/src/org/ruboto/Script.java +286 -114
- data/assets/src/org/ruboto/test/ActivityTest.java +25 -26
- data/assets/src/org/ruboto/test/InstrumentationTestRunner.java +28 -29
- data/assets/{assets/scripts → src}/ruboto.rb +13 -8
- data/assets/test/assets/scripts/test_helper.rb +8 -4
- data/lib/ruboto/commands/base.rb +42 -6
- data/lib/ruboto/util/build.rb +25 -18
- data/lib/ruboto/util/update.rb +53 -30
- data/lib/ruboto/util/xml_element.rb +2 -2
- data/lib/ruboto/version.rb +3 -0
- data/test/activity/image_button_activity.rb +1 -1
- data/test/activity/image_button_and_button_activity.rb +1 -1
- data/test/activity/stack_activity.rb +21 -0
- data/test/activity/stack_activity_test.rb +24 -0
- data/test/app_test_methods.rb +25 -32
- data/test/rake_test.rb +15 -17
- data/test/ruboto_gen_test.rb +1 -16
- data/test/ruboto_gen_with_psych_test.rb +16 -0
- data/test/ruboto_update_test.rb +1 -47
- data/test/ruboto_update_with_psych_test.rb +18 -0
- data/test/service_test.rb +4 -2
- data/test/test_helper.rb +32 -22
- data/test/update_test_methods.rb +29 -0
- metadata +13 -22
data/README.md
CHANGED
@@ -172,9 +172,9 @@ The main thing Ruboto offers you is the ability to write Ruby scripts to define
|
|
172
172
|
|
173
173
|
Here's how it works:
|
174
174
|
|
175
|
-
First of all, your scripts are found in `
|
175
|
+
First of all, your scripts are found in `src/` and the script name is the same as the name of your class, only under_scored instead of CamelCased. Android classes have all of these methods that get called in certain situations. `Activity.onDestroy()` gets called when the activity gets killed, for example. Save weird cases (like the "launching" methods that need to setup JRuby), to script the method onFooBar, you call the Ruby method handle_foo_bar on the Android object. In your scripts, they are defined as `$class_name`. That was really abstract, so here's an example.
|
176
176
|
|
177
|
-
You generate an app with the option `--activity FooActivity`, which means that ruboto will generate a FooActivity for you. So you open `
|
177
|
+
You generate an app with the option `--activity FooActivity`, which means that ruboto will generate a FooActivity for you. So you open `src/foo_activity.rb` in your favorite text editor. If you want an activity that does nothing but Log when it gets launched and when it gets destroyed (in the onCreate and onPause methods). You want your script to look like this:
|
178
178
|
|
179
179
|
require 'ruboto.rb' #scripts will not work without doing this
|
180
180
|
$activity.handle_create do |bundle|
|
@@ -198,7 +198,7 @@ Each class has only one method that you can nest other calls inside of (ie. what
|
|
198
198
|
|
199
199
|
The arguments passed to the block you give `handle_` methods are the same as the arguments that the java methods take. Consult the Android documentation.
|
200
200
|
|
201
|
-
Activities also have some special methods defined to make things easier. The easiest way to get an idea of what they are is looking over the [demo scripts](http://github.com/ruboto/ruboto-irb/tree/master/assets/demo-scripts/). You can also read the [ruboto.rb file](http://github.com/ruboto/ruboto-core/blob/master/assets/
|
201
|
+
Activities also have some special methods defined to make things easier. The easiest way to get an idea of what they are is looking over the [demo scripts](http://github.com/ruboto/ruboto-irb/tree/master/assets/demo-scripts/). You can also read the [ruboto.rb file](http://github.com/ruboto/ruboto-core/blob/master/assets/src/ruboto.rb) where everything is defined.
|
202
202
|
|
203
203
|
Testing
|
204
204
|
-------
|
data/Rakefile
CHANGED
@@ -1,3 +1,22 @@
|
|
1
|
+
require 'rexml/document'
|
2
|
+
|
3
|
+
PLATFORM_PROJECT = File.expand_path('tmp/RubotoCore', File.dirname(__FILE__))
|
4
|
+
PLATFORM_DEBUG_APK = "#{PLATFORM_PROJECT}/bin/RubotoCore-debug.apk"
|
5
|
+
PLATFORM_RELEASE_APK = "#{PLATFORM_PROJECT}/bin/RubotoCore-release.apk"
|
6
|
+
MANIFEST_FILE = "AndroidManifest.xml"
|
7
|
+
|
8
|
+
# FIXME(uwe): Remove when we stop supporting JRuby 1.5.6
|
9
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.8.0')
|
10
|
+
gem_spec = Gem::Specification.find_by_path 'jruby-jars'
|
11
|
+
else
|
12
|
+
gem_spec = Gem.searcher.find('jruby-jars')
|
13
|
+
end
|
14
|
+
raise StandardError.new("Can't find Gem specification jruby-jars.") unless gem_spec
|
15
|
+
JRUBY_JARS_VERSION = gem_spec.version
|
16
|
+
ON_JRUBY_JARS_1_5_6 = JRUBY_JARS_VERSION == Gem::Version.new('1.5.6')
|
17
|
+
# FIXME end
|
18
|
+
|
19
|
+
|
1
20
|
task :default => :gem
|
2
21
|
|
3
22
|
desc "Generate a gem"
|
@@ -17,3 +36,59 @@ task :test do
|
|
17
36
|
require f.chomp('.rb')
|
18
37
|
end
|
19
38
|
end
|
39
|
+
|
40
|
+
namespace :platform do
|
41
|
+
desc 'Remove Ruboto Core platform project'
|
42
|
+
task :clean do
|
43
|
+
FileUtils.rm_rf PLATFORM_PROJECT
|
44
|
+
end
|
45
|
+
|
46
|
+
desc 'Generate the Ruboto Core platform project'
|
47
|
+
task :project => PLATFORM_PROJECT
|
48
|
+
|
49
|
+
file PLATFORM_PROJECT do
|
50
|
+
sh "ruby -rubygems -I#{File.expand_path('lib', File.dirname(__FILE__))} bin/ruboto gen app --package org.ruboto.core --name RubotoCore --with-jruby #{'--with-psych' unless ON_JRUBY_JARS_1_5_6} --path #{PLATFORM_PROJECT}"
|
51
|
+
Dir.chdir(PLATFORM_PROJECT) do
|
52
|
+
manifest = REXML::Document.new(File.read(MANIFEST_FILE))
|
53
|
+
manifest.root.attributes['android:versionCode'] = '2'
|
54
|
+
manifest.root.attributes['android:versionName'] = '0.4.1'
|
55
|
+
manifest.root.attributes['android:installLocation'] = 'auto' # or 'preferExternal' ?
|
56
|
+
manifest.root.elements['uses-sdk'].attributes['android:targetSdkVersion'] = '8'
|
57
|
+
File.open(MANIFEST_FILE, 'w') { |f| manifest.document.write(f, 4) }
|
58
|
+
File.open('default.properties', 'w'){|f| f << "target=android-8\n"}
|
59
|
+
keystore_file = File.expand_path('~/android_market.keystore')
|
60
|
+
if File.exists?(keystore_file)
|
61
|
+
File.open('local.properties', 'a'){|f| f << "key.store=#{keystore_file}\nkey.alias=android_market\n"}
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
file PLATFORM_DEBUG_APK => PLATFORM_PROJECT do
|
67
|
+
Dir.chdir(PLATFORM_PROJECT) do
|
68
|
+
sh 'rake debug'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
desc 'Generate a Ruboto Core platform release apk'
|
73
|
+
task :release => PLATFORM_RELEASE_APK
|
74
|
+
|
75
|
+
file PLATFORM_RELEASE_APK => PLATFORM_PROJECT do
|
76
|
+
Dir.chdir(PLATFORM_PROJECT) do
|
77
|
+
sh 'rake release'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
desc 'Install the Ruboto Core platform debug apk'
|
82
|
+
task :install => PLATFORM_DEBUG_APK do
|
83
|
+
Dir.chdir(PLATFORM_PROJECT) do
|
84
|
+
sh 'rake install'
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
desc 'Uninstall the Ruboto Core platform debug apk'
|
89
|
+
task :uninstall => PLATFORM_PROJECT do
|
90
|
+
Dir.chdir(PLATFORM_PROJECT) do
|
91
|
+
sh 'rake uninstall'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/assets/Rakefile
CHANGED
@@ -3,7 +3,7 @@ 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
|
-
def
|
6
|
+
def scripts_path() @sdcard_path ||= "/mnt/sdcard/Android/data/#{package}/files/scripts" end
|
7
7
|
def app_files_path() @app_files_path ||= "/data/data/#{package}/files" end
|
8
8
|
|
9
9
|
require 'rake/clean'
|
@@ -15,11 +15,13 @@ BUNDLE_PATH = File.expand_path 'tmp/bundle'
|
|
15
15
|
MANIFEST_FILE = File.expand_path 'AndroidManifest.xml'
|
16
16
|
RUBOTO_CONFIG_FILE = File.expand_path 'ruboto.yml'
|
17
17
|
GEM_FILE = File.expand_path('Gemfile.apk')
|
18
|
+
GEM_LOCK_FILE = File.expand_path('Gemfile.apk.lock')
|
18
19
|
APK_FILE = File.expand_path "bin/#{build_project_name}-debug.apk"
|
19
20
|
TEST_APK_FILE = File.expand_path "test/bin/#{build_project_name}Test-debug.apk"
|
20
21
|
JRUBY_JARS = Dir[File.expand_path 'libs/jruby-*.jar']
|
21
22
|
RESOURCE_FILES = Dir[File.expand_path 'res/**/*']
|
22
23
|
JAVA_SOURCE_FILES = Dir[File.expand_path 'src/**/*.java']
|
24
|
+
RUBY_SOURCE_FILES = Dir[File.expand_path 'src/**/*.rb']
|
23
25
|
|
24
26
|
CLEAN.include('tmp', 'bin')
|
25
27
|
|
@@ -45,11 +47,32 @@ end
|
|
45
47
|
desc 'build debug package'
|
46
48
|
task :debug => APK_FILE
|
47
49
|
|
50
|
+
namespace :debug do
|
51
|
+
desc 'build debug package if compiled files have changed'
|
52
|
+
task :quick => [MANIFEST_FILE, RUBOTO_CONFIG_FILE, BUNDLE_JAR] + JRUBY_JARS + JAVA_SOURCE_FILES + RESOURCE_FILES do |t|
|
53
|
+
build_apk(t)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
48
57
|
desc "build package and install it on the emulator or device"
|
49
58
|
task :install => APK_FILE do
|
50
59
|
install_apk
|
51
60
|
end
|
52
61
|
|
62
|
+
namespace :install do
|
63
|
+
desc 'uninstall, build, and install the application'
|
64
|
+
task :clean => [:uninstall, APK_FILE, :install]
|
65
|
+
|
66
|
+
desc 'Install the application, but only if compiled files are changed.'
|
67
|
+
task :quick => 'debug:quick' do
|
68
|
+
install_apk
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
task :release do
|
73
|
+
sh 'ant release'
|
74
|
+
end
|
75
|
+
|
53
76
|
task :tag => :release do
|
54
77
|
unless `git branch` =~ /^\* master$/
|
55
78
|
puts "You must be on the master branch to release!"
|
@@ -75,7 +98,7 @@ end
|
|
75
98
|
|
76
99
|
desc 'Start the emulator with larger disk'
|
77
100
|
task :emulator do
|
78
|
-
|
101
|
+
sh 'emulator -partition-size 1024 -avd Android_3.0'
|
79
102
|
end
|
80
103
|
|
81
104
|
task :start do
|
@@ -93,69 +116,26 @@ task :uninstall do
|
|
93
116
|
uninstall_apk
|
94
117
|
end
|
95
118
|
|
96
|
-
namespace :install do
|
97
|
-
desc 'Uninstall, build, and install the application'
|
98
|
-
task :clean => [:uninstall, APK_FILE, :install]
|
99
|
-
end
|
100
|
-
|
101
119
|
file MANIFEST_FILE
|
102
120
|
file RUBOTO_CONFIG_FILE
|
103
121
|
|
104
|
-
file APK_FILE => [MANIFEST_FILE, RUBOTO_CONFIG_FILE, BUNDLE_JAR] + JRUBY_JARS + JAVA_SOURCE_FILES + RESOURCE_FILES do |t|
|
105
|
-
|
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
|
109
|
-
|
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'
|
122
|
+
file APK_FILE => [MANIFEST_FILE, RUBOTO_CONFIG_FILE, BUNDLE_JAR] + JRUBY_JARS + JAVA_SOURCE_FILES + RESOURCE_FILES + RUBY_SOURCE_FILES do |t|
|
123
|
+
build_apk(t)
|
120
124
|
end
|
121
125
|
|
122
126
|
desc 'Copy scripts to emulator or device'
|
123
|
-
task :update_scripts do
|
124
|
-
if device_path_exists?(
|
125
|
-
|
126
|
-
data_dir = sdcard_path
|
127
|
-
elsif device_path_exists?(app_files_path)
|
128
|
-
data_dir_name = 'private'
|
129
|
-
data_dir = app_files_path
|
130
|
-
else
|
131
|
-
puts 'Cannot find the scripts directory on the device.'
|
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
|
137
|
-
puts "Reverting to uninstalling and re-installing the apk."
|
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
|
145
|
-
next
|
146
|
-
end
|
147
|
-
Rake::Task['install'].invoke
|
148
|
-
puts "Pushing files to apk #{data_dir_name} file area."
|
127
|
+
task :update_scripts => ['install:quick'] do
|
128
|
+
`adb shell mkdir -p #{scripts_path}` if !device_path_exists?(scripts_path)
|
129
|
+
puts "Pushing files to apk public file area."
|
149
130
|
last_update = File.exists?(UPDATE_MARKER_FILE) ? Time.parse(File.read(UPDATE_MARKER_FILE)) : Time.parse('1970-01-01T00:00:00')
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
end
|
131
|
+
# TODO(uwe): Use `adb sync src` instead?
|
132
|
+
Dir.chdir('src') do
|
133
|
+
Dir["**/*.rb"].each do |script_file|
|
134
|
+
next if File.directory? script_file
|
135
|
+
next if File.mtime(script_file) < last_update
|
136
|
+
next if script_file =~ /~$/
|
137
|
+
print "#{script_file}: "; $stdout.flush
|
138
|
+
`adb push #{script_file} #{scripts_path}/#{script_file}`
|
159
139
|
end
|
160
140
|
end
|
161
141
|
mark_update
|
@@ -166,43 +146,29 @@ namespace :update_scripts do
|
|
166
146
|
task :restart => [:stop, :update_scripts, :start]
|
167
147
|
end
|
168
148
|
|
169
|
-
task :update_test_scripts do
|
170
|
-
test_scripts_path = "/data/data/#{package}.tests/files/scripts"
|
171
|
-
# TODO(uwe): Investigate if we can just push the scripts instead of building and installing the instrumentation APK
|
172
|
-
if package_installed?(true) && device_path_exists?(test_scripts_path)
|
173
|
-
Dir['test/assets/scripts/*.rb'].each do |script|
|
174
|
-
print "#{script}: " ; $stdout.flush
|
175
|
-
`adb push #{script} #{test_scripts_path}`
|
176
|
-
end
|
177
|
-
`adb shell ps | grep #{package}.tests | awk '{print $2}' | xargs adb shell kill`
|
178
|
-
else
|
179
|
-
Dir.chdir 'test' do
|
180
|
-
sh 'ant install'
|
181
|
-
end
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
149
|
task :test => :uninstall do
|
186
150
|
Dir.chdir('test') do
|
187
151
|
puts 'Running tests'
|
188
|
-
|
189
|
-
|
152
|
+
sh "adb uninstall #{package}.tests"
|
153
|
+
sh "ant run-tests"
|
190
154
|
end
|
191
155
|
end
|
192
156
|
|
193
157
|
namespace :test do
|
194
|
-
task :quick =>
|
158
|
+
task :quick => :update_scripts do
|
195
159
|
Dir.chdir('test') do
|
196
160
|
puts 'Running quick tests'
|
161
|
+
sh 'ant install'
|
197
162
|
sh "ant run-tests-quick"
|
198
163
|
end
|
199
164
|
end
|
200
165
|
end
|
201
166
|
|
202
167
|
file GEM_FILE
|
168
|
+
file GEM_LOCK_FILE
|
203
169
|
|
204
170
|
desc 'Generate bundle jar from Gemfile'
|
205
|
-
file BUNDLE_JAR => GEM_FILE do
|
171
|
+
file BUNDLE_JAR => [GEM_FILE, GEM_LOCK_FILE] do
|
206
172
|
next unless File.exists? GEM_FILE
|
207
173
|
puts "Generating #{BUNDLE_JAR}"
|
208
174
|
|
@@ -248,15 +214,24 @@ end
|
|
248
214
|
# Expand JARs
|
249
215
|
Dir.chdir "#{BUNDLE_PATH}/ruby/1.8/gems" do
|
250
216
|
Dir['*'].each do |gem_lib|
|
251
|
-
next if gem_lib =~ /jdbc-sqlite/
|
252
217
|
Dir.chdir "#{gem_lib}/lib" do
|
253
218
|
Dir['**/*.jar'].each do |jar|
|
254
|
-
|
255
|
-
|
256
|
-
|
219
|
+
unless gem_lib =~ /jdbc-sqlite/
|
220
|
+
puts "Expanding #{gem_lib} #{jar} into #{BUNDLE_JAR}"
|
221
|
+
`jar xf #{jar}`
|
222
|
+
if jar == 'arjdbc/jdbc/adapter_java.jar'
|
223
|
+
service_load_code =
|
224
|
+
"require 'jruby'
|
225
|
+
Java::arjdbc.jdbc.AdapterJavaService.new.basicLoad(JRuby.runtime)
|
226
|
+
"
|
227
|
+
File.open(jar + '.rb', 'w'){|f| f << service_load_code}
|
228
|
+
File.open(jar.chomp('.jar') + '.rb', 'w'){|f| f << service_load_code} if jar.end_with?('.jar')
|
229
|
+
else
|
230
|
+
FileUtils.touch(jar + '.rb')
|
231
|
+
FileUtils.touch(jar.chomp('.jar') + '.rb') if jar.end_with?('.jar')
|
232
|
+
end
|
233
|
+
end
|
257
234
|
FileUtils.rm_f(jar)
|
258
|
-
# FileUtils.touch(jar + '.rb')
|
259
|
-
# FileUtils.touch(jar.chomp('jar') + 'rb')
|
260
235
|
end
|
261
236
|
end
|
262
237
|
end
|
@@ -280,7 +255,11 @@ def mark_update(time = Time.now)
|
|
280
255
|
end
|
281
256
|
|
282
257
|
def clear_update
|
283
|
-
|
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
|
284
263
|
end
|
285
264
|
|
286
265
|
def strings(name)
|
@@ -335,6 +314,18 @@ def replace_faulty_code(faulty_file, faulty_code)
|
|
335
314
|
end
|
336
315
|
end
|
337
316
|
|
317
|
+
def build_apk(t)
|
318
|
+
if File.exist?(APK_FILE)
|
319
|
+
changed_prereqs = t.prerequisites.select do |p|
|
320
|
+
File.file?(p) && !Dir[p].empty? && Dir[p].map{|f| File.mtime(f)}.max > File.mtime(APK_FILE)
|
321
|
+
end
|
322
|
+
return if changed_prereqs.empty?
|
323
|
+
changed_prereqs.each{|f| puts "#{f} changed."}
|
324
|
+
puts "Forcing rebuild of #{APK_FILE}."
|
325
|
+
end
|
326
|
+
sh 'ant debug'
|
327
|
+
end
|
328
|
+
|
338
329
|
def install_apk
|
339
330
|
case package_installed?
|
340
331
|
when true
|
@@ -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>
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'ruboto'
|
2
2
|
|
3
|
-
#
|
4
|
-
# the BroadcastReceiver receives an intent (whenever onReceive is called)
|
3
|
+
# will get called whenever the BroadcastReceiver receives an intent (whenever onReceive is called)
|
5
4
|
$broadcast_receiver.handle_receive do |context, intent|
|
6
5
|
Log.v "MYAPP", intent.getExtras.to_s
|
7
6
|
end
|
@@ -1,14 +1,190 @@
|
|
1
1
|
package THE_PACKAGE;
|
2
2
|
|
3
|
+
import java.io.IOException;
|
4
|
+
|
5
|
+
import org.ruboto.Script;
|
6
|
+
|
7
|
+
import android.app.ProgressDialog;
|
8
|
+
import android.content.BroadcastReceiver;
|
9
|
+
import android.content.Context;
|
10
|
+
import android.content.DialogInterface;
|
11
|
+
import android.content.DialogInterface.OnCancelListener;
|
12
|
+
import android.content.Intent;
|
13
|
+
import android.content.IntentFilter;
|
14
|
+
import android.net.Uri;
|
15
|
+
import android.os.Bundle;
|
16
|
+
import android.os.Handler;
|
17
|
+
import android.util.Log;
|
18
|
+
import android.view.View;
|
19
|
+
import android.widget.TextView;
|
20
|
+
import android.widget.Toast;
|
21
|
+
|
3
22
|
public class InheritingActivity extends org.ruboto.RubotoActivity {
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
23
|
+
private int splash = 0;
|
24
|
+
private ProgressDialog loadingDialog;
|
25
|
+
private boolean dialogCancelled = false;
|
26
|
+
private BroadcastReceiver receiver;
|
27
|
+
private boolean appStarted = false;
|
28
|
+
|
29
|
+
public void onCreate(Bundle bundle) {
|
30
|
+
Log.d("RUBOTO", "onCreate: ");
|
31
|
+
|
32
|
+
try {
|
33
|
+
splash = Class.forName(getPackageName() + ".R$layout").getField("splash").getInt(null);
|
8
34
|
} catch (Exception e) {
|
35
|
+
splash = -1;
|
9
36
|
}
|
10
37
|
|
11
38
|
setScriptName("start.rb");
|
12
|
-
|
39
|
+
if (Script.isInitialized()) {
|
40
|
+
appStarted = true;
|
41
|
+
}
|
42
|
+
super.onCreate(bundle);
|
13
43
|
}
|
44
|
+
|
45
|
+
public void onResume() {
|
46
|
+
Log.d("RUBOTO", "onResume: ");
|
47
|
+
|
48
|
+
if(appStarted) {
|
49
|
+
Log.d("RUBOTO", "onResume: App already started!");
|
50
|
+
super.onResume();
|
51
|
+
return;
|
52
|
+
}
|
53
|
+
|
54
|
+
Log.d("RUBOTO", "onResume: Checking JRuby");
|
55
|
+
if (Script.isInitialized()) {
|
56
|
+
Log.d("RUBOTO", "Already initialized");
|
57
|
+
fireRubotoActivity();
|
58
|
+
} else {
|
59
|
+
Log.d("RUBOTO", "Not initialized");
|
60
|
+
showProgress();
|
61
|
+
receiver = new BroadcastReceiver(){
|
62
|
+
public void onReceive(Context context, Intent intent) {
|
63
|
+
Log.i("RUBOTO", "received broadcast: " + intent);
|
64
|
+
Log.i("RUBOTO", "URI: " + intent.getData());
|
65
|
+
if (intent.getData().toString().equals("package:org.ruboto.core")) {
|
66
|
+
Toast.makeText(context,"Ruboto Core is now installed.",Toast.LENGTH_SHORT).show();
|
67
|
+
if (receiver != null) {
|
68
|
+
unregisterReceiver(receiver);
|
69
|
+
receiver = null;
|
70
|
+
}
|
71
|
+
showProgress();
|
72
|
+
initJRuby(false);
|
73
|
+
}
|
74
|
+
}
|
75
|
+
};
|
76
|
+
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
77
|
+
filter.addDataScheme("package");
|
78
|
+
registerReceiver(receiver, filter);
|
79
|
+
initJRuby(true);
|
80
|
+
super.onResume();
|
81
|
+
}
|
82
|
+
}
|
83
|
+
|
84
|
+
public void onPause() {
|
85
|
+
Log.d("RUBOTO", "onPause: ");
|
86
|
+
|
87
|
+
if (receiver != null) {
|
88
|
+
unregisterReceiver(receiver);
|
89
|
+
receiver = null;
|
90
|
+
}
|
91
|
+
super.onPause();
|
92
|
+
}
|
93
|
+
|
94
|
+
public void onDestroy() {
|
95
|
+
Log.d("RUBOTO", "onDestroy: ");
|
96
|
+
|
97
|
+
super.onDestroy();
|
98
|
+
if (dialogCancelled) {
|
99
|
+
System.runFinalizersOnExit(true);
|
100
|
+
System.exit(0);
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
private void initJRuby(final boolean firstTime) {
|
105
|
+
new Thread(new Runnable() {
|
106
|
+
public void run() {
|
107
|
+
final boolean jrubyOk = Script.setUpJRuby(InheritingActivity.this);
|
108
|
+
if (jrubyOk) {
|
109
|
+
Log.d("RUBOTO", "onResume: JRuby OK");
|
110
|
+
prepareJRuby();
|
111
|
+
runOnUiThread(new Runnable() {
|
112
|
+
public void run() {
|
113
|
+
fireRubotoActivity();
|
114
|
+
}
|
115
|
+
});
|
116
|
+
} else {
|
117
|
+
runOnUiThread(new Runnable() {
|
118
|
+
public void run() {
|
119
|
+
if (firstTime) {
|
120
|
+
Log.d("RUBOTO", "onResume: Checking JRuby - IN UI thread");
|
121
|
+
try {
|
122
|
+
setContentView(Class.forName(getPackageName() + ".R$layout").getField("get_ruboto_core").getInt(null));
|
123
|
+
} catch (Exception e) {
|
124
|
+
}
|
125
|
+
} else {
|
126
|
+
Toast.makeText(InheritingActivity.this,"Failed to initialize Ruboto Core.",Toast.LENGTH_SHORT).show();
|
127
|
+
try {
|
128
|
+
TextView textView = (TextView) findViewById(Class.forName(getPackageName() + ".R$id").getField("text").getInt(null));
|
129
|
+
textView.setText("Woops! Ruboto Core was installed, but it failed to initialize properly! I am not sure how to proceed from here. If you can, please file an error report at http://ruboto.org/");
|
130
|
+
} catch (Exception e) {
|
131
|
+
}
|
132
|
+
}
|
133
|
+
hideProgress();
|
134
|
+
}
|
135
|
+
});
|
136
|
+
}
|
137
|
+
}
|
138
|
+
}).start();
|
139
|
+
}
|
140
|
+
|
141
|
+
// Called when buton is pressed.
|
142
|
+
public void getRubotoCore(View view) {
|
143
|
+
try {
|
144
|
+
startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse("market://details?id=org.ruboto.core")));
|
145
|
+
} catch (android.content.ActivityNotFoundException anfe) {
|
146
|
+
try {
|
147
|
+
TextView textView = (TextView) findViewById(Class.forName(getPackageName() + ".R$id").getField("text").getInt(null));
|
148
|
+
textView.setText("Could not find the Android Market App. You will have to install Ruboto Core manually. Bummer!");
|
149
|
+
} catch (Exception e) {}
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
private void fireRubotoActivity() {
|
154
|
+
if(appStarted) return;
|
155
|
+
appStarted = true;
|
156
|
+
Log.i("RUBOTO", "Starting activity");
|
157
|
+
loadScript();
|
158
|
+
onStart();
|
159
|
+
super.onResume();
|
160
|
+
hideProgress();
|
161
|
+
}
|
162
|
+
|
163
|
+
private void showProgress() {
|
164
|
+
if (loadingDialog == null) {
|
165
|
+
Log.i("RUBOTO", "Showing progress");
|
166
|
+
if (splash > 0) {
|
167
|
+
requestWindowFeature(android.view.Window.FEATURE_NO_TITLE);
|
168
|
+
setContentView(splash);
|
169
|
+
} else {
|
170
|
+
loadingDialog = ProgressDialog.show(this, null, "Starting...", true, true);
|
171
|
+
loadingDialog.setCanceledOnTouchOutside(false);
|
172
|
+
loadingDialog.setOnCancelListener(new OnCancelListener() {
|
173
|
+
public void onCancel(DialogInterface dialog) {
|
174
|
+
dialogCancelled = true;
|
175
|
+
finish();
|
176
|
+
}
|
177
|
+
});
|
178
|
+
}
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
private void hideProgress() {
|
183
|
+
if (loadingDialog != null) {
|
184
|
+
Log.d("RUBOTO", "Hide progress");
|
185
|
+
loadingDialog.dismiss();
|
186
|
+
loadingDialog = null;
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
14
190
|
}
|
@@ -1,10 +1,27 @@
|
|
1
1
|
package THE_PACKAGE;
|
2
2
|
|
3
|
+
import org.ruboto.Script;
|
4
|
+
|
3
5
|
public class InheritingBroadcastReceiver extends org.ruboto.RubotoBroadcastReceiver {
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
private boolean scriptLoaded = false;
|
7
|
+
|
8
|
+
public InheritingBroadcastReceiver() {
|
9
|
+
super("start.rb");
|
10
|
+
if (Script.isInitialized()) {
|
11
|
+
scriptLoaded = true;
|
12
|
+
}
|
13
|
+
}
|
14
|
+
|
15
|
+
public void onReceive(android.content.Context context, android.content.Intent intent) {
|
16
|
+
if (!scriptLoaded) {
|
17
|
+
if (Script.setUpJRuby(context)) {
|
18
|
+
loadScript();
|
19
|
+
scriptLoaded = true;
|
20
|
+
} else {
|
21
|
+
// FIXME(uwe): What to do if the Ruboto Core platform is missing?
|
22
|
+
}
|
23
|
+
}
|
24
|
+
super.onReceive(context, intent);
|
25
|
+
}
|
9
26
|
|
10
27
|
}
|
@@ -1,28 +1,19 @@
|
|
1
1
|
package THE_PACKAGE;
|
2
2
|
|
3
|
-
import org.jruby.embed.ScriptingContainer;
|
4
|
-
import org.jruby.javasupport.util.RuntimeHelpers;
|
5
|
-
import org.jruby.runtime.builtin.IRubyObject;
|
6
|
-
import org.jruby.javasupport.JavaUtil;
|
7
|
-
import org.jruby.exceptions.RaiseException;
|
8
3
|
import org.ruboto.Script;
|
9
4
|
|
10
5
|
public class THE_RUBOTO_CLASS THE_ACTION THE_ANDROID_CLASS {
|
11
|
-
private ScriptingContainer __ruby__;
|
12
6
|
|
13
7
|
THE_CONSTANTS
|
14
|
-
private IRubyObject[] callbackProcs = new IRubyObject[CONSTANTS_COUNT];
|
15
8
|
|
16
|
-
|
9
|
+
private Object[] callbackProcs = new Object[CONSTANTS_COUNT];
|
17
10
|
|
18
|
-
|
19
|
-
if (__ruby__ == null) __ruby__ = Script.getRuby();
|
20
|
-
return __ruby__;
|
21
|
-
}
|
11
|
+
THE_CONSTRUCTORS
|
22
12
|
|
23
|
-
public void setCallbackProc(int id,
|
13
|
+
public void setCallbackProc(int id, Object obj) {
|
24
14
|
callbackProcs[id] = obj;
|
25
15
|
}
|
26
16
|
|
27
17
|
THE_METHODS
|
18
|
+
|
28
19
|
}
|