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.
Files changed (35) hide show
  1. data/README.md +3 -3
  2. data/Rakefile +75 -0
  3. data/assets/Rakefile +76 -85
  4. data/assets/res/layout/get_ruboto_core.xml +25 -0
  5. data/assets/samples/sample_broadcast_receiver.rb +1 -2
  6. data/assets/src/InheritingActivity.java +181 -5
  7. data/assets/src/InheritingBroadcastReceiver.java +22 -5
  8. data/assets/src/InheritingClass.java +4 -13
  9. data/assets/src/RubotoActivity.java +78 -118
  10. data/assets/src/RubotoBroadcastReceiver.java +31 -50
  11. data/assets/src/RubotoService.java +13 -28
  12. data/assets/src/org/ruboto/Script.java +286 -114
  13. data/assets/src/org/ruboto/test/ActivityTest.java +25 -26
  14. data/assets/src/org/ruboto/test/InstrumentationTestRunner.java +28 -29
  15. data/assets/{assets/scripts → src}/ruboto.rb +13 -8
  16. data/assets/test/assets/scripts/test_helper.rb +8 -4
  17. data/lib/ruboto/commands/base.rb +42 -6
  18. data/lib/ruboto/util/build.rb +25 -18
  19. data/lib/ruboto/util/update.rb +53 -30
  20. data/lib/ruboto/util/xml_element.rb +2 -2
  21. data/lib/ruboto/version.rb +3 -0
  22. data/test/activity/image_button_activity.rb +1 -1
  23. data/test/activity/image_button_and_button_activity.rb +1 -1
  24. data/test/activity/stack_activity.rb +21 -0
  25. data/test/activity/stack_activity_test.rb +24 -0
  26. data/test/app_test_methods.rb +25 -32
  27. data/test/rake_test.rb +15 -17
  28. data/test/ruboto_gen_test.rb +1 -16
  29. data/test/ruboto_gen_with_psych_test.rb +16 -0
  30. data/test/ruboto_update_test.rb +1 -47
  31. data/test/ruboto_update_with_psych_test.rb +18 -0
  32. data/test/service_test.rb +4 -2
  33. data/test/test_helper.rb +32 -22
  34. data/test/update_test_methods.rb +29 -0
  35. 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 `assets/scripts/` 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.
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 `assets/scripts/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:
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/assets/scripts/ruboto.rb) where everything is defined.
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 sdcard_path() @sdcard_path ||= "/mnt/sdcard/Android/data/#{package}/files" end
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
- system 'emulator -partition-size 1024 -avd Android_3.0'
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
- 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
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?(sdcard_path)
125
- data_dir_name = 'public'
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
- Dir.chdir('assets') do
151
- ['scripts'].each do |asset_dir|
152
- Dir["#{asset_dir}/*"].each do |asset_file|
153
- next if File.directory? asset_file
154
- next if File.mtime(asset_file) < last_update
155
- next if asset_file =~ /~$/
156
- print "#{asset_file}: " ; $stdout.flush
157
- `adb push #{asset_file} #{data_dir}/#{asset_file}`
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
- system "adb uninstall #{package}.tests"
189
- system "ant run-tests"
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 => [:update_scripts, :update_test_scripts] do
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
- puts "Expanding #{gem_lib} #{jar} into #{BUNDLE_JAR}"
255
-
256
- `jar xf #{jar}`
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
- FileUtils.rm_f UPDATE_MARKER_FILE
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
- # despite the name, the when_launched block will get called whenever
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
- public void onCreate(android.os.Bundle arg0) {
5
- try {
6
- setSplash(Class.forName("THE_PACKAGE.R$layout").getField("splash")
7
- .getInt(null));
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
- super.onCreate(arg0);
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
- public void onReceive(android.content.Context arg0,
5
- android.content.Intent arg1) {
6
- setScriptName("start.rb");
7
- super.onReceive(arg0, arg1);
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
- THE_CONSTRUCTORS
9
+ private Object[] callbackProcs = new Object[CONSTANTS_COUNT];
17
10
 
18
- private ScriptingContainer getRuby() {
19
- if (__ruby__ == null) __ruby__ = Script.getRuby();
20
- return __ruby__;
21
- }
11
+ THE_CONSTRUCTORS
22
12
 
23
- public void setCallbackProc(int id, IRubyObject obj) {
13
+ public void setCallbackProc(int id, Object obj) {
24
14
  callbackProcs[id] = obj;
25
15
  }
26
16
 
27
17
  THE_METHODS
18
+
28
19
  }