ruboto 0.15.0 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +4 -1
  3. data/README.md +44 -43
  4. data/RELEASE_CANDICATE_DOC +10 -12
  5. data/RELEASE_DOC +69 -37
  6. data/Rakefile +47 -27
  7. data/assets/rakelib/ruboto.rake +69 -26
  8. data/assets/src/RubotoActivity.java +17 -4
  9. data/assets/src/RubotoService.java +18 -0
  10. data/assets/src/org/ruboto/EntryPointActivity.java +1 -1
  11. data/assets/src/org/ruboto/JRubyAdapter.java +3 -1
  12. data/assets/src/org/ruboto/ScriptLoader.java +27 -4
  13. data/assets/src/ruboto/activity.rb +4 -3
  14. data/assets/src/ruboto/activity/reload.rb +17 -12
  15. data/assets/src/ruboto/widget.rb +18 -18
  16. data/bin/elevate.exe +0 -0
  17. data/bin/elevate_32.exe +0 -0
  18. data/lib/java_class_gen/android_api.xml +1 -1
  19. data/lib/ruboto/commands/base.rb +3 -5
  20. data/lib/ruboto/util/build.rb +1 -1
  21. data/lib/ruboto/util/emulator.rb +31 -5
  22. data/lib/ruboto/util/setup.rb +183 -68
  23. data/lib/ruboto/util/update.rb +35 -42
  24. data/lib/ruboto/util/xml_element.rb +45 -33
  25. data/lib/ruboto/version.rb +1 -1
  26. data/test/activity/call_super_activity.rb +1 -1
  27. data/test/activity/dialog_fragment_activity.rb +37 -0
  28. data/test/activity/dialog_fragment_activity_test.rb +19 -0
  29. data/test/activity/image_button_activity.rb +2 -1
  30. data/test/activity/navigation_activity_test.rb +2 -1
  31. data/test/activity/no_on_create_activity.rb +17 -0
  32. data/test/activity/no_on_create_activity_test.rb +15 -0
  33. data/test/activity/spinner_activity.rb +51 -0
  34. data/test/activity/spinner_activity_test.rb +65 -0
  35. data/test/activity/stack_activity_test.rb +14 -7
  36. data/test/activity/startup_exception_activity.rb +7 -5
  37. data/test/activity/startup_exception_activity_test.rb +2 -2
  38. data/test/app_test_methods.rb +4 -0
  39. data/test/git_based_gem_test.rb +64 -0
  40. data/test/minimal_app_test.rb +12 -13
  41. data/test/rake_test.rb +1 -0
  42. data/test/ruboto_gen_test.rb +21 -15
  43. data/test/ruboto_update_test.rb +23 -6
  44. data/test/sqldroid_test.rb +0 -1
  45. data/test/test_helper.rb +37 -19
  46. metadata +25 -2
@@ -34,7 +34,7 @@ adb_version_str = `adb version`
34
34
  (puts "Unrecognized adb version: #$1"; exit 1) unless adb_version_str =~ /Android Debug Bridge version (\d+\.\d+\.\d+)/
35
35
  (puts "adb version 1.0.31 or later required. Version found: #$1"; exit 1) unless Gem::Version.new($1) >= Gem::Version.new('1.0.31')
36
36
  android_home = ENV['ANDROID_HOME']
37
- android_home = android_home.gsub("\\", "/") unless android_home.nil?
37
+ android_home = android_home.gsub("\\", '/') unless android_home.nil?
38
38
  if android_home.nil?
39
39
  if (adb_path = which('adb'))
40
40
  android_home = File.dirname(File.dirname(adb_path))
@@ -235,27 +235,25 @@ end
235
235
 
236
236
  file RUBOTO_CONFIG_FILE
237
237
 
238
+ task :jruby_adapter => JRUBY_ADAPTER_FILE
238
239
  file JRUBY_ADAPTER_FILE => RUBOTO_CONFIG_FILE do
239
240
  require 'yaml'
240
- if (heap_alloc = YAML.load(File.read(RUBOTO_CONFIG_FILE))['heap_alloc'])
241
- config = <<EOF
242
- // BEGIN Ruboto HeapAlloc
243
- @SuppressWarnings("unused")
244
- byte[] arrayForHeapAllocation = new byte[#{heap_alloc} * 1024 * 1024];
245
- arrayForHeapAllocation = null;
246
- // END Ruboto HeapAlloc
241
+ marker_topic ='Ruboto HeapAlloc'
242
+ begin_marker = "// BEGIN #{marker_topic}"
243
+ end_marker = "// END #{marker_topic}"
244
+ unless (heap_alloc = YAML.load(File.read(RUBOTO_CONFIG_FILE))['heap_alloc'])
245
+ heap_alloc = 13
246
+ comment = '// '
247
+ end
248
+ config = <<EOF
249
+ #{begin_marker}
250
+ #{comment}@SuppressWarnings("unused")
251
+ #{comment}byte[] arrayForHeapAllocation = new byte[#{heap_alloc} * 1024 * 1024];
252
+ #{comment}arrayForHeapAllocation = null;
253
+ #{end_marker}
247
254
  EOF
248
- else
249
- config = <<EOF
250
- // BEGIN Ruboto HeapAlloc
251
- // @SuppressWarnings("unused")
252
- // byte[] arrayForHeapAllocation = new byte[13 * 1024 * 1024];
253
- // arrayForHeapAllocation = null;
254
- // END Ruboto HeapAlloc
255
- EOF
256
- end
257
255
  source = File.read(JRUBY_ADAPTER_FILE)
258
- heap_alloc_pattern = %r{^\s*// BEGIN Ruboto HeapAlloc\n.*^\s*// END Ruboto HeapAlloc\n}m
256
+ heap_alloc_pattern = %r{^\s*#{begin_marker}\n.*^\s*#{end_marker}\n}m
259
257
  File.open(JRUBY_ADAPTER_FILE, 'w') { |f| f << source.sub(heap_alloc_pattern, config) }
260
258
  end
261
259
 
@@ -281,6 +279,9 @@ task :update_scripts => %w(install:quick) do
281
279
  update_scripts
282
280
  end
283
281
 
282
+ desc 'Copy scripts to emulator or device and reload'
283
+ task :boing => %w(update_scripts:reload)
284
+
284
285
  namespace :update_scripts do
285
286
  desc 'Copy scripts to emulator and restart the app'
286
287
  task :restart => APK_DEPENDENCIES - RUBY_SOURCE_FILES do |t|
@@ -299,7 +300,7 @@ namespace :update_scripts do
299
300
  else
300
301
  update_scripts
301
302
  end
302
- start_app # FIXME(uwe): Should trigger reload of updated scripts
303
+ start_app
303
304
  end
304
305
 
305
306
  desc 'Copy scripts to emulator and reload'
@@ -309,7 +310,13 @@ namespace :update_scripts do
309
310
  start_app
310
311
  else
311
312
  scripts = update_scripts
312
- reload_scripts(scripts) if scripts
313
+ if scripts
314
+ if app_running?
315
+ reload_scripts(scripts)
316
+ else
317
+ start_app
318
+ end
319
+ end
313
320
  end
314
321
  end
315
322
  end
@@ -380,6 +387,10 @@ file BUNDLE_JAR => [GEM_FILE, GEM_LOCK_FILE] do
380
387
  definition = Bundler.definition
381
388
  definition.validate_ruby!
382
389
  Bundler::Installer.install(Bundler.root, definition)
390
+ unless Dir["#{BUNDLE_PATH}/bundler/gems/"].empty?
391
+ system("mkdir -p '#{BUNDLE_PATH}/gems'")
392
+ system("mv #{BUNDLE_PATH}/bundler/gems/* #{BUNDLE_PATH}/gems/")
393
+ end
383
394
 
384
395
  # Restore RUBY_ENGINE (limit the scope of this hack)
385
396
  old_verbose, $VERBOSE = $VERBOSE, nil
@@ -389,7 +400,7 @@ file BUNDLE_JAR => [GEM_FILE, GEM_LOCK_FILE] do
389
400
  $VERBOSE = old_verbose
390
401
  end
391
402
  Gem.platforms = platforms
392
- Gem.paths = gem_paths["GEM_PATH"]
403
+ Gem.paths = gem_paths['GEM_PATH']
393
404
  else
394
405
  # Bundler.settings[:platform] = Gem::Platform::DALVIK
395
406
  sh "bundle install --gemfile #{GEM_FILE} --path=#{BUNDLE_PATH} --platform=dalvik#{sdk_level}"
@@ -527,6 +538,35 @@ Java::json.ext.ParserService.new.basicLoad(JRuby.runtime)
527
538
  FileUtils.rm_rf BUNDLE_PATH
528
539
  end
529
540
 
541
+ desc 'Log activity execution, accepts optional logcat filter'
542
+ task :log, [:filter] do |t, args|
543
+ puts '--- clearing logcat'
544
+ `adb logcat -c`
545
+ filter = args[:filter] ? args[:filter] : '' # filter log with filter-specs like TAG:LEVEL TAG:LEVEL ... '*:S'
546
+ logcat_cmd = "adb logcat ActivityManager #{filter}" # we always need ActivityManager logging to catch activity start
547
+ puts "--- starting logcat: #{logcat_cmd}"
548
+ IO.popen logcat_cmd do |logcat|
549
+ puts "--- waiting for activity #{package}/.#{main_activity} ..."
550
+ activity_started = false
551
+ started_regex = Regexp.new "^\\I/ActivityManager.+Start proc #{package} for activity #{package}/\\.#{main_activity}: pid=(?<pid>\\d+)"
552
+ restarted_regex = Regexp.new "^\\I/ActivityManager.+START u0 {cmp=#{package}/org.ruboto.RubotoActivity.+} from pid (?<pid>\\d+)"
553
+ related_regex = Regexp.new "#{package}|#{main_activity}"
554
+ pid_regex = nil
555
+ logcat.each_line do |line|
556
+ if (activity_start_match = started_regex.match(line) || restarted_regex.match(line))
557
+ activity_started = true
558
+ pid = activity_start_match[:pid]
559
+ pid_regex = Regexp.new "\\( *#{pid}\\): "
560
+ puts "--- activity PID=#{pid}"
561
+ end
562
+ if activity_started && (line =~ pid_regex || line =~ related_regex)
563
+ puts "#{Time.now.strftime('%Y%m%d %H%M%S.%6N')} #{line}"
564
+ end
565
+ end
566
+ puts '--- logcat closed'
567
+ end
568
+ end
569
+
530
570
  # Methods
531
571
 
532
572
  def sdk_level
@@ -717,17 +757,20 @@ def update_scripts
717
757
  return nil
718
758
  end
719
759
 
760
+ def app_running?
761
+ `adb shell ps | egrep -e " #{package}\r$"`.size > 0
762
+ end
763
+
720
764
  def start_app
721
765
  `adb shell am start -a android.intent.action.MAIN -n #{package}/.#{main_activity}`
722
766
  end
723
767
 
724
768
  # Triggers reload of updated scripts and restart of the current activity
725
769
  def reload_scripts(scripts)
726
- scripts.each.with_index do |s, i|
727
- cmd = "adb shell am broadcast -a android.intent.action.VIEW -e file #{s} #{'-e restart YES' if i == (scripts.size - 1)}"
728
- puts cmd
729
- system cmd
730
- end
770
+ s = scripts.map{|s| s.gsub(/[&;]/){|m| "&#{m[0]}"}}.join(';')
771
+ cmd = %Q{adb shell am broadcast -a android.intent.action.VIEW -e reload "#{s}"}
772
+ puts cmd
773
+ system cmd
731
774
  end
732
775
 
733
776
  def stop_app
@@ -60,11 +60,24 @@ public class THE_RUBOTO_CLASS THE_ACTION THE_ANDROID_CLASS {
60
60
  }
61
61
  }
62
62
 
63
- // FIXME(uwe): What is this for?
64
- public boolean rubotoAttachable() {
65
- return true;
63
+ public void onDestroy() {
64
+ if (ScriptLoader.isCalledFromJRuby()) {
65
+ super.onDestroy();
66
+ return;
67
+ }
68
+ if (!JRubyAdapter.isInitialized()) {
69
+ Log.i("Method called before JRuby runtime was initialized: RubotoActivity#onDestroy");
70
+ super.onDestroy();
71
+ return;
72
+ }
73
+ String rubyClassName = scriptInfo.getRubyClassName();
74
+ if (rubyClassName == null) {
75
+ super.onDestroy();
76
+ return;
77
+ }
78
+ ScriptLoader.callOnDestroy(this);
66
79
  }
67
- // EMXIF
80
+
68
81
 
69
82
  /****************************************************************************************
70
83
  *
@@ -86,6 +86,24 @@ public class THE_RUBOTO_CLASS THE_ACTION THE_ANDROID_CLASS {
86
86
  }
87
87
  }
88
88
 
89
+ public void onDestroy() {
90
+ if (ScriptLoader.isCalledFromJRuby()) {
91
+ super.onDestroy();
92
+ return;
93
+ }
94
+ if (!JRubyAdapter.isInitialized()) {
95
+ Log.i("Method called before JRuby runtime was initialized: RubotoActivity#onDestroy");
96
+ super.onDestroy();
97
+ return;
98
+ }
99
+ String rubyClassName = scriptInfo.getRubyClassName();
100
+ if (rubyClassName == null) {
101
+ super.onDestroy();
102
+ return;
103
+ }
104
+ ScriptLoader.callOnDestroy(this);
105
+ }
106
+
89
107
 
90
108
  /****************************************************************************************
91
109
  *
@@ -35,7 +35,7 @@ public class EntryPointActivity extends org.ruboto.RubotoActivity {
35
35
  // The Intent to to call when done. Defaults to calling this Activity again.
36
36
  // Override to change.
37
37
  protected Intent futureIntent() {
38
- if (getIntent().getAction().equals(Intent.ACTION_MAIN)) {
38
+ if (!getIntent().getAction().equals(Intent.ACTION_VIEW)) {
39
39
  return new Intent(getIntent()).setAction(Intent.ACTION_VIEW);
40
40
  } else {
41
41
  return getIntent();
@@ -272,6 +272,8 @@ public class JRubyAdapter {
272
272
  addLoadPath(scriptsDirName(appContext));
273
273
  put("$package_name", appContext.getPackageName());
274
274
 
275
+ runScriptlet("::RUBOTO_JAVA_PROXIES = {}");
276
+
275
277
  initialized = true;
276
278
  } catch (ClassNotFoundException e) {
277
279
  handleInitException(e);
@@ -353,7 +355,7 @@ public class JRubyAdapter {
353
355
  // FIXME(uwe): Remove when we stop supporting Ruby 1.8
354
356
  @Deprecated public static boolean isRubyOneNine() {
355
357
  String rv = ((String)get("RUBY_VERSION"));
356
- return rv.startsWith("2.0.") || rv.startsWith("1.9.");
358
+ return rv.startsWith("2.1.") || rv.startsWith("2.0.") || rv.startsWith("1.9.");
357
359
  }
358
360
 
359
361
  static void printStackTrace(Throwable t) {
@@ -1,6 +1,7 @@
1
1
  package org.ruboto;
2
2
 
3
3
  import java.io.IOException;
4
+ import java.util.Map;
4
5
 
5
6
  import android.app.ProgressDialog;
6
7
  import android.content.Context;
@@ -12,7 +13,7 @@ public class ScriptLoader {
12
13
  */
13
14
  public static boolean isCalledFromJRuby() {
14
15
  StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
15
- int maxLookBack = Math.min(9, stackTraceElements.length);
16
+ int maxLookBack = Math.min(8, stackTraceElements.length);
16
17
  for(int i = 0; i < maxLookBack ; i++){
17
18
  if (stackTraceElements[i].getClassName().startsWith("org.jruby.javasupport.JavaMethod")) {
18
19
  return true;
@@ -52,7 +53,6 @@ public class ScriptLoader {
52
53
  JRubyAdapter.put("$java_instance", component);
53
54
  rubyClass = JRubyAdapter.runScriptlet("class << $java_instance; self; end");
54
55
  } else if (JRubyAdapter.isRubyOneNine()) {
55
- JRubyAdapter.runScriptlet("Java::" + component.getClass().getName() + ".__persistent__ = true");
56
56
  rubyClass = JRubyAdapter.runRubyMethod(component, "singleton_class");
57
57
  } else {
58
58
  throw new RuntimeException("Unknown Ruby version: " + JRubyAdapter.get("RUBY_VERSION"));
@@ -67,7 +67,6 @@ public class ScriptLoader {
67
67
  Log.d("Script contains class definition");
68
68
  if (rubyClass == null && hasBackingJavaClass) {
69
69
  Log.d("Script has separate Java class");
70
- JRubyAdapter.runScriptlet("Java::" + component.getClass().getName() + ".__persistent__ = true");
71
70
  rubyClass = JRubyAdapter.runScriptlet("Java::" + component.getClass().getName());
72
71
  }
73
72
  Log.d("Set class: " + rubyClass);
@@ -116,16 +115,40 @@ public class ScriptLoader {
116
115
  }
117
116
 
118
117
  public static final void callOnCreate(final RubotoComponent component, Object... args) {
118
+ persistObjectProxy(component);
119
119
  if (component instanceof android.content.Context) {
120
120
  Log.d("Call onCreate on: " + component.getScriptInfo().getRubyInstance());
121
121
  // FIXME(uwe): Simplify when we stop support for snake case aliasing interface callback methods.
122
122
  if ((Boolean)JRubyAdapter.runScriptlet(component.getScriptInfo().getRubyClassName() + ".instance_methods(false).any?{|m| m.to_sym == :onCreate}")) {
123
123
  JRubyAdapter.runRubyMethod(component.getScriptInfo().getRubyInstance(), "onCreate", args);
124
- } else if ((Boolean)JRubyAdapter.runScriptlet(component.getScriptInfo().getRubyClassName() + ".instance_methods(false).any?{|m| m.to_sym == :on_create}")) {
124
+ } else if ((Boolean)JRubyAdapter.runScriptlet(component.getScriptInfo().getRubyClassName() + ".instance_methods(true).any?{|m| m.to_sym == :on_create}")) {
125
125
  JRubyAdapter.runRubyMethod(component.getScriptInfo().getRubyInstance(), "on_create", args);
126
+ } else {
127
+ JRubyAdapter.runRubyMethod(component.getScriptInfo().getRubyInstance(), "onCreate", args);
126
128
  }
127
129
  // EMXIF
128
130
  }
129
131
  }
130
132
 
133
+ public static final void callOnDestroy(final RubotoComponent component) {
134
+ String rubyClassName = component.getScriptInfo().getRubyClassName();
135
+ if ((Boolean)JRubyAdapter.runScriptlet(rubyClassName + ".instance_methods(false).any?{|m| m.to_sym == :onDestroy}")) {
136
+ JRubyAdapter.runRubyMethod(component.getScriptInfo().getRubyInstance(), "onDestroy");
137
+ } else if ((Boolean)JRubyAdapter.runScriptlet(rubyClassName + ".instance_methods(true).any?{|m| m.to_sym == :on_destroy}")) {
138
+ JRubyAdapter.runRubyMethod(component.getScriptInfo().getRubyInstance(), "on_destroy");
139
+ } else {
140
+ JRubyAdapter.runRubyMethod(component.getScriptInfo().getRubyInstance(), "onDestroy");
141
+ }
142
+ releaseObjectProxy(component);
143
+ }
144
+
145
+ private static void persistObjectProxy(RubotoComponent component) {
146
+ JRubyAdapter.runScriptlet("Java::" + component.getClass().getName() + ".__persistent__ = true");
147
+ ((Map)JRubyAdapter.get("RUBOTO_JAVA_PROXIES")).put(component.getScriptInfo().getRubyInstance(), component.getScriptInfo().getRubyInstance());
148
+ }
149
+
150
+ private static void releaseObjectProxy(RubotoComponent component) {
151
+ ((Map)JRubyAdapter.get("RUBOTO_JAVA_PROXIES")).remove(component.getScriptInfo().getRubyInstance());
152
+ }
153
+
131
154
  }
@@ -62,8 +62,9 @@ module Ruboto
62
62
  raise "Unknown options: #{options}" unless options.empty?
63
63
 
64
64
  if class_name.nil? && block_given?
65
+ src_desc = source_descriptor(block)
65
66
  class_name =
66
- "#{java_class.name.split('::').last}_#{source_descriptor(block)[0].split('/').last.gsub(/[.-]+/, '_')}_#{source_descriptor(block)[1]}"
67
+ "#{java_class.name.split('::').last}_#{src_desc[0].split('/').last.gsub(/[.-]+/, '_')}_#{src_desc[1]}"
67
68
  end
68
69
 
69
70
  class_name = class_name.to_s
@@ -85,8 +86,8 @@ module Ruboto
85
86
 
86
87
  private
87
88
 
88
- def source_descriptor(proc)
89
- if md = /^#<Proc:0x[0-9A-Fa-f]+@(.+):(\d+)(?: \(lambda\))?>$/.match(proc.inspect)
89
+ def source_descriptor(src_proc)
90
+ if (md = /^#<Proc:0x[0-9A-Fa-f-]+@(.+):(\d+)(?: \(lambda\))?>$/.match(src_proc.inspect))
90
91
  filename, line = md.captures
91
92
  return filename, line.to_i
92
93
  end
@@ -1,14 +1,16 @@
1
+ require 'ruboto/activity'
2
+
1
3
  module Ruboto::Activity::Reload
2
4
  import org.ruboto.Log
3
5
 
4
6
  def onResume
5
- Log.d "Ruboto::Activity::Reload onResume"
7
+ Log.d 'Ruboto::Activity::Reload onResume'
6
8
  super
7
9
 
8
10
  @ruboto_activity_reload_receiver = ReloadReceiver.new(self)
9
11
  filter = android.content.IntentFilter.new(android.content.Intent::ACTION_VIEW)
10
12
  registerReceiver(@ruboto_activity_reload_receiver, filter)
11
- Log.d "Ruboto::Activity::Reload registered reload receiver"
13
+ Log.d 'Ruboto::Activity::Reload registered reload receiver'
12
14
  rescue Exception
13
15
  Log.e "Exception registering reload listener: #{$!.message}"
14
16
  Log.e $!.backtrace.join("\n")
@@ -18,7 +20,7 @@ module Ruboto::Activity::Reload
18
20
  super
19
21
  unregisterReceiver(@ruboto_activity_reload_receiver)
20
22
  @ruboto_activity_reload_receiver = nil
21
- Log.d "Ruboto::Activity::Reload unregistered reload receiver"
23
+ Log.d 'Ruboto::Activity::Reload unregistered reload receiver'
22
24
  rescue Exception
23
25
  Log.e "Exception unregistering reload listener: #{$!.message}"
24
26
  Log.e $!.backtrace.join("\n")
@@ -38,17 +40,20 @@ module Ruboto::Activity::Reload
38
40
  # but have not found a way to do that.
39
41
  def onReceive(context, reload_intent)
40
42
  Log.d "Got reload intent: #{reload_intent.inspect}"
41
- file = reload_intent.get_string_extra('file')
42
- if file
43
- Log.d "load file: #{file.inspect}"
44
- load file
45
- end
46
- if (reload_intent.get_string_extra('restart'))
43
+ file_string = reload_intent.get_string_extra('reload')
44
+ if file_string
45
+ files = file_string.split(/(?<!&);/).map { |f| f.gsub(/&(.)/) { |m| m[1] } }
46
+ files.each do |file|
47
+ Log.d "load file: #{file.inspect}"
48
+ load file
49
+ end
47
50
  Log.d 'restart activity'
48
- if @activity.intent.action == android.content.Intent::ACTION_MAIN
49
- restart_intent = android.content.Intent.new(@activity.intent).setAction(android.content.Intent::ACTION_VIEW)
51
+ if @activity.intent.action == android.content.Intent::ACTION_MAIN ||
52
+ @activity.intent.action == android.hardware.usb.UsbManager::ACTION_USB_DEVICE_ATTACHED
53
+ restart_intent = android.content.Intent.new(@activity.intent).
54
+ setAction(android.content.Intent::ACTION_VIEW)
50
55
  else
51
- restart_intent = @activity.intent
56
+ restart_intent = @activity.intent
52
57
  end
53
58
  @activity.startActivity(restart_intent)
54
59
  @activity.finish
@@ -109,7 +109,7 @@ def ruboto_import_widget(class_name, package_name='android.widget')
109
109
 
110
110
  return unless klass
111
111
 
112
- RubotoActivity.class_eval "
112
+ method_str = "
113
113
  def #{(class_name.to_s.gsub(/([A-Z])/) { '_' + $1.downcase })[1..-1]}(params={})
114
114
  if force_style = params.delete(:default_style)
115
115
  rv = #{class_name}.new(self, nil, force_style)
@@ -134,6 +134,13 @@ def ruboto_import_widget(class_name, package_name='android.widget')
134
134
  rv
135
135
  end
136
136
  "
137
+ RubotoActivity.class_eval method_str
138
+
139
+ # FIXME(uwe): Remove condition when we stop support for api level < 11
140
+ if android.os.Build::VERSION::SDK_INT >= 11
141
+ android.app.Fragment.class_eval method_str.gsub('self', 'activity')
142
+ end
143
+ # EMXIF
137
144
 
138
145
  setup_list_view if class_name == :ListView
139
146
  setup_spinner if class_name == :Spinner
@@ -166,14 +173,12 @@ def setup_image_button
166
173
  end
167
174
 
168
175
  def setup_list_view
169
- Java::android.widget.ListView.__persistent__ = true
170
- Java::android.widget.ListView.class_eval do
176
+ android.widget.ListView.__persistent__ = true
177
+ android.widget.ListView.class_eval do
171
178
  def configure(context, params = {})
172
179
  if (list = params.delete(:list))
173
- @adapter_list = Java::java.util.ArrayList.new
174
- @adapter_list.addAll(list)
175
180
  item_layout = params.delete(:item_layout) || R::layout::simple_list_item_1
176
- params[:adapter] = Java::android.widget.ArrayAdapter.new(context, item_layout, @adapter_list)
181
+ params[:adapter] = android.widget.ArrayAdapter.new(context, item_layout, list)
177
182
  end
178
183
  super(context, params)
179
184
  end
@@ -188,19 +193,14 @@ def setup_list_view
188
193
  end
189
194
 
190
195
  def setup_spinner
191
- Java::android.widget.Spinner.__persistent__ = true
192
- Java::android.widget.Spinner.class_eval do
193
- attr_reader :adapter, :adapter_list
194
-
196
+ android.widget.Spinner.__persistent__ = true
197
+ android.widget.Spinner.class_eval do
195
198
  def configure(context, params = {})
196
- if params.has_key? :list
197
- @adapter_list = Java::java.util.ArrayList.new
198
- @adapter_list.addAll(params[:list])
199
- item_layout = params.delete(:item_layout) || R::layout::simple_spinner_item
200
- @adapter = Java::android.widget.ArrayAdapter.new(context, item_layout, @adapter_list)
201
- @adapter.setDropDownViewResource(params.delete(:dropdown_layout) || R::layout::simple_spinner_dropdown_item)
202
- setAdapter @adapter
203
- params.delete :list
199
+ if (list = params.delete(:list))
200
+ item_layout = params.delete(:item_layout)
201
+ params[:adapter] = android.widget.ArrayAdapter.new(context, item_layout || R::layout::simple_spinner_item, list)
202
+ dropdown_layout = params.delete(:dropdown_layout)
203
+ params[:adapter].setDropDownViewResource(dropdown_layout) if dropdown_layout
204
204
  end
205
205
  super(context, params)
206
206
  end