ruboto 0.10.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -16,6 +16,7 @@ Before you use Ruboto, you should do the following things:
16
16
  * Install the JDK if it's not on your system already
17
17
  * Install [jruby](http://jruby.org/) if you don't already have it. JRuby has a [very easy install process](http://jruby.org/#2), or you can use [rvm](http://rvm.beginrescueend.com/)
18
18
  * Install [the Android SDK](http://developer.android.com/sdk/index.html)
19
+ * Add the sdk to `$ANDROID_HOME` as an absolute path (Java does not expand tildes `~`)
19
20
  * Add the sdk's `tools/` and `platform-tools/` directory to your `$PATH`
20
21
  * Generate an [Emulator](http://developer.android.com/guide/developing/tools/emulator.html) image unless you want to develop using your phone.
21
22
 
@@ -241,9 +242,9 @@ If you have an "eclair" emulator that runs Android 2.1 and a "froyo" one that ru
241
242
  Alternatives
242
243
  ------------
243
244
 
244
- If Ruboto's performance is a problem for you, or you want something that gives you total access to the android API (as Ruboto does not yet do), check out [Mirah](http://mirah.org/) and [Garrett](http://github.com/technomancy/Garrett).
245
+ If Ruboto's performance is a problem for you, check out [Mirah](http://mirah.org/) and [Garrett](http://github.com/technomancy/Garrett).
245
246
 
246
- Mirah, formerly known as Duby, is a language with Ruby-like syntax that compiles to java files. This means that it adds no big runtime dependencies and has essentially the same performance as writing Java code because it essentially generates the same Java code that you would write. This makes it extremely well-suited for mobile devices where performance is a much bigger consideration.
247
+ Mirah is a language with Ruby-like syntax that compiles to java files. This means that it adds no big runtime dependencies and has essentially the same performance as writing Java code because it essentially generates the same Java code that you would write. This makes it extremely well-suited for mobile devices where performance is a much bigger consideration.
247
248
 
248
249
  Garrett is a "playground for Mirah exploration on Android."
249
250
 
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'ruboto/version'
5
5
  require 'ruboto/description'
6
6
  require 'ruboto/sdk_versions'
7
7
  require 'uri'
8
- require 'net/http'
8
+ require 'net/https'
9
9
 
10
10
  PLATFORM_PROJECT = File.expand_path('tmp/RubotoCore', File.dirname(__FILE__))
11
11
  PLATFORM_DEBUG_APK = "#{PLATFORM_PROJECT}/bin/RubotoCore-debug.apk"
@@ -293,15 +293,9 @@ namespace :platform do
293
293
  task :project => PLATFORM_PROJECT
294
294
 
295
295
  file PLATFORM_PROJECT do
296
- sh "ruby -rubygems -I#{File.expand_path('lib', File.dirname(__FILE__))} bin/ruboto gen app --package org.ruboto.core --name RubotoCore --with-jruby --path #{PLATFORM_PROJECT} --min-sdk #{Ruboto::SdkVersions::MINIMUM_SUPPORTED_SDK} --target #{Ruboto::SdkVersions::DEFAULT_TARGET_SDK}"
297
- Dir.chdir(PLATFORM_PROJECT) do
298
- manifest = REXML::Document.new(File.read(MANIFEST_FILE))
299
- manifest.root.attributes['android:versionCode'] = '409'
300
- manifest.root.attributes['android:versionName'] = '0.4.9'
301
- manifest.root.attributes['android:installLocation'] = 'auto' # or 'preferExternal' ?
302
- File.open(MANIFEST_FILE, 'w') { |f| manifest.document.write(f, 4) }
303
- File.open('Gemfile.apk', 'w'){|f| f << "source :rubygems\n\ngem 'activerecord-jdbc-adapter'\n"}
304
- File.open('ant.properties', 'a'){|f| f << "key.store=${user.home}/ruboto_core.keystore\nkey.alias=Ruboto\n"}
296
+ sh "git clone --depth 1 https://github.com/ruboto/ruboto-core.git #{PLATFORM_PROJECT}"
297
+ Dir.chdir PLATFORM_PROJECT do
298
+ sh "ruby -rubygems -I#{File.expand_path('lib', File.dirname(__FILE__))} ../../bin/ruboto update app"
305
299
  end
306
300
  end
307
301
 
@@ -335,9 +329,13 @@ namespace :platform do
335
329
  desc 'Download the current RubotoCore platform release apk'
336
330
  file PLATFORM_CURRENT_RELEASE_APK do
337
331
  puts 'Downloading the current RubotoCore platform release apk'
338
- url = 'http://cloud.github.com/downloads/ruboto/ruboto/RubotoCore-release.apk'
332
+ uri = URI('https://raw.github.com/ruboto/ruboto-core/master/dist/RubotoCore-release.apk')
339
333
  begin
340
- File.open(PLATFORM_CURRENT_RELEASE_APK, 'w') { |f| f << Net::HTTP.get(URI.parse url) }
334
+ http = Net::HTTP.new(uri.host, uri.port)
335
+ http.use_ssl = true
336
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
337
+ content = http.request(Net::HTTP::Get.new(uri.request_uri)).body
338
+ File.open(PLATFORM_CURRENT_RELEASE_APK, 'w') { |f| f << content }
341
339
  rescue Exception, SystemExit
342
340
  FileUtils.rm(PLATFORM_CURRENT_RELEASE_APK) if File.exists?(PLATFORM_CURRENT_RELEASE_APK)
343
341
  raise
data/assets/.gitignore CHANGED
@@ -1,4 +1,6 @@
1
- /.idea
1
+ .bundle
2
+ .DS_Store
3
+ .idea
2
4
  bin
3
5
  gen
4
6
  tmp
@@ -1,4 +1,8 @@
1
1
  require 'rbconfig'
2
+ require 'rubygems'
3
+ require 'time'
4
+ require 'rake/clean'
5
+ require 'rexml/document'
2
6
 
3
7
  ANT_CMD = (RbConfig::CONFIG['host_os'] =~ /mswin|mingw/i) ? "ant.bat" : "ant"
4
8
 
@@ -7,7 +11,21 @@ if `#{ANT_CMD} -version` !~ /version (\d+)\.(\d+)\.(\d+)/ || $1.to_i < 1 || ($1.
7
11
  exit 1
8
12
  end
9
13
 
10
- require 'time'
14
+ adb_version_str = `adb version`
15
+ (puts "Android SDK platform tools not in PATH (adb command not found).";exit 1) unless $? == 0
16
+ (puts "Unrecognized adb version: #$1";exit 1) unless adb_version_str =~ /Android Debug Bridge version (\d+\.\d+\.\d+)/
17
+ (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')
18
+ adb_path = `which adb`
19
+ ENV['ANDROID_HOME'] ||= File.dirname(File.dirname(adb_path)) if $? == 0
20
+
21
+ dx_filename = "#{ENV['ANDROID_HOME']}/platform-tools/dx"
22
+ old_dx_content = File.read(dx_filename)
23
+ new_dx_content = old_dx_content.dup
24
+ if new_dx_content =~ /^defaultMx="-Xmx(\d+)(M|G)"/ &&
25
+ ($1.to_i * 1024 ** {'M' => 2, 'G' => 3, 'T' => 4}[$2]) < 3*1024**3
26
+ new_dx_content.sub(/^defaultMx="-Xmx\d+(M|G)"/, 'defaultMx="-Xmx3G"')
27
+ File.open(dx_filename, 'w') { |f| f << new_dx_content }
28
+ end
11
29
 
12
30
  def manifest() @manifest ||= REXML::Document.new(File.read(MANIFEST_FILE)) end
13
31
  def package() manifest.root.attribute('package') end
@@ -15,9 +33,6 @@ def build_project_name() @build_project_name ||= REXML::Document.new(File.read('
15
33
  def scripts_path() @sdcard_path ||= "/mnt/sdcard/Android/data/#{package}/files/scripts" end
16
34
  def app_files_path() @app_files_path ||= "/data/data/#{package}/files" end
17
35
 
18
- require 'rake/clean'
19
- require 'rexml/document'
20
-
21
36
  PROJECT_DIR = File.expand_path('..', File.dirname(__FILE__))
22
37
  UPDATE_MARKER_FILE = File.join(PROJECT_DIR, 'bin', 'LAST_UPDATE')
23
38
  BUNDLE_JAR = File.expand_path 'libs/bundle.jar'
@@ -38,7 +53,7 @@ APK_DEPENDENCIES = [MANIFEST_FILE, RUBOTO_CONFIG_FILE, BUNDLE_JAR] + JRUBY_JAR
38
53
  KEYSTORE_FILE = (key_store = File.readlines('ant.properties').grep(/^key.store=/).first) ? File.expand_path(key_store.chomp.sub(/^key.store=/, '').sub('${user.home}', '~')) : "#{build_project_name}.keystore"
39
54
  KEYSTORE_ALIAS = (key_alias = File.readlines('ant.properties').grep(/^key.alias=/).first) ? key_alias.chomp.sub(/^key.alias=/, '') : build_project_name
40
55
 
41
- CLEAN.include('bin')
56
+ CLEAN.include('bin', 'gen')
42
57
 
43
58
  task :default => :debug
44
59
 
@@ -74,9 +89,15 @@ task :install => APK_FILE do
74
89
  install_apk
75
90
  end
76
91
 
92
+ desc 'uninstall, build, and install the application'
93
+ task :reinstall => [:uninstall, APK_FILE, :install]
94
+
77
95
  namespace :install do
78
- desc 'uninstall, build, and install the application'
79
- task :clean => [:uninstall, APK_FILE, :install]
96
+ # FIXME(uwe): Remove in 2013
97
+ desc 'Deprecated: use "reinstall" instead.'
98
+ task :clean => :reinstall do
99
+ puts '"rake install:clean" is deprecated. Use "rake reinstall" instead.'
100
+ end
80
101
 
81
102
  desc 'Install the application, but only if compiled files are changed.'
82
103
  task :quick => 'debug:quick' do
@@ -85,13 +106,15 @@ namespace :install do
85
106
  end
86
107
 
87
108
  desc 'Build APK for release'
88
- task :release => RELEASE_APK_FILE
109
+ task :release => [:tag, RELEASE_APK_FILE]
89
110
 
90
111
  file RELEASE_APK_FILE => [KEYSTORE_FILE] + APK_DEPENDENCIES do |t|
91
112
  build_apk(t, true)
92
113
  end
93
114
 
94
115
  desc 'Create a keystore for signing the release APK'
116
+ task :keystore => KEYSTORE_FILE
117
+
95
118
  file KEYSTORE_FILE do
96
119
  unless File.read('ant.properties') =~ /^key.store=/
97
120
  File.open('ant.properties', 'a'){|f| f << "\nkey.store=#{KEYSTORE_FILE}\n"}
@@ -103,30 +126,19 @@ file KEYSTORE_FILE do
103
126
  end
104
127
 
105
128
  desc 'Tag this working copy with the current version'
106
- task :tag => :release do
129
+ task :tag do
130
+ next unless File.exists?('.git') && `git --version` =~ /git version /
107
131
  unless `git branch` =~ /^\* master$/
108
132
  puts "You must be on the master branch to release!"
109
133
  exit!
110
134
  end
111
135
  # sh "git commit --allow-empty -a -m 'Release #{version}'"
112
136
  output = `git status --porcelain`
113
- raise "Workspace not clean!\n#{output}" unless output.empty?
137
+ raise "\nWorkspace not clean!\n#{output}" unless output.empty?
114
138
  sh "git tag #{version}"
115
139
  sh "git push origin master --tags"
116
140
  end
117
141
 
118
- task :sign => :release do
119
- sh "jarsigner -keystore #{ENV['RUBOTO_KEYSTORE']} -signedjar bin/#{build_project_name}.apk bin/#{build_project_name}-unsigned.apk #{ENV['RUBOTO_KEY_ALIAS']}"
120
- end
121
-
122
- task :align => :sign do
123
- sh "zipalign 4 bin/#{build_project_name}.apk #{build_project_name}.apk"
124
- end
125
-
126
- task :publish => :align do
127
- puts "#{build_project_name}.apk is ready for the market!"
128
- end
129
-
130
142
  desc 'Start the emulator with larger disk'
131
143
  task :emulator do
132
144
  sh 'emulator -partition-size 1024 -avd Android_3.0'
@@ -332,15 +344,15 @@ def strings(name)
332
344
  value.text
333
345
  end
334
346
 
335
- def version()
347
+ def version
336
348
  strings :version_name
337
349
  end
338
350
 
339
- def app_name()
351
+ def app_name
340
352
  strings :app_name
341
353
  end
342
354
 
343
- def main_activity()
355
+ def main_activity
344
356
  manifest.root.elements['application'].elements["activity[@android:label='@string/app_name']"].attribute('android:name')
345
357
  end
346
358
 
@@ -11,7 +11,6 @@ public class THE_RUBOTO_CLASS THE_ACTION THE_ANDROID_CLASS {
11
11
  private final ScriptInfo scriptInfo = new ScriptInfo();
12
12
  private String remoteVariable = null;
13
13
  Bundle[] args;
14
- private Bundle configBundle = null;
15
14
 
16
15
  public THE_RUBOTO_CLASS setRemoteVariable(String var) {
17
16
  remoteVariable = var;
@@ -40,29 +39,15 @@ public class THE_RUBOTO_CLASS THE_ACTION THE_ANDROID_CLASS {
40
39
  args = new Bundle[1];
41
40
  args[0] = bundle;
42
41
 
43
- configBundle = getIntent().getBundleExtra("RubotoActivity Config");
44
-
42
+ Bundle configBundle = getIntent().getBundleExtra("Ruboto Config");
45
43
  if (configBundle != null) {
46
44
  if (configBundle.containsKey("Theme")) {
47
45
  setTheme(configBundle.getInt("Theme"));
48
46
  }
49
- if (configBundle.containsKey("ClassName")) {
50
- if (this.getClass().getName() == THE_RUBOTO_CLASS.class.getName()) {
51
- scriptInfo.setRubyClassName(configBundle.getString("ClassName"));
52
- } else {
53
- throw new IllegalArgumentException("Only local Intents may set class name.");
54
- }
55
- }
56
- if (configBundle.containsKey("Script")) {
57
- if (this.getClass().getName() == THE_RUBOTO_CLASS.class.getName()) {
58
- scriptInfo.setScriptName(configBundle.getString("Script"));
59
- } else {
60
- throw new IllegalArgumentException("Only local Intents may set script name.");
61
- }
62
- }
47
+ scriptInfo.setFromIntent(getIntent());
63
48
  }
64
49
 
65
- if (JRubyAdapter.isInitialized()) {
50
+ if (JRubyAdapter.isInitialized() && scriptInfo.isReadyToLoad()) {
66
51
  ScriptLoader.loadScript(this, (Object[]) args);
67
52
  } else {
68
53
  super.onCreate(bundle);
@@ -17,18 +17,121 @@ public class THE_RUBOTO_CLASS THE_ACTION THE_ANDROID_CLASS {
17
17
  */
18
18
  @Override
19
19
  public void onCreate() {
20
- if (ScriptLoader.isCalledFromJRuby()) {
21
- super.onCreate();
22
- return;
20
+ System.out.println("RubotoService onCreate(): " + getClass().getName());
21
+
22
+ if (ScriptLoader.isCalledFromJRuby()) {
23
+ super.onCreate();
24
+ return;
25
+ }
26
+
27
+ if (JRubyAdapter.isInitialized() && scriptInfo.isReadyToLoad()) {
28
+ ScriptLoader.loadScript(this);
29
+ } else {
30
+ super.onCreate();
31
+ }
32
+ }
33
+
34
+ @Override
35
+ public int onStartCommand(android.content.Intent intent, int flags, int startId) {
36
+ if (ScriptLoader.isCalledFromJRuby()) return super.onStartCommand(intent, flags, startId);
37
+
38
+ if (!JRubyAdapter.isInitialized()) {
39
+ Log.i("Method called before JRuby runtime was initialized: RubotoService#onStartCommand");
40
+ return super.onStartCommand(intent, flags, startId);
41
+ }
42
+
43
+ if (JRubyAdapter.isInitialized() && !scriptInfo.isLoaded()) {
44
+ scriptInfo.setFromIntent(intent);
45
+ ScriptLoader.loadScript(this);
46
+ }
47
+
48
+ String rubyClassName = scriptInfo.getRubyClassName();
49
+ if (rubyClassName == null) return super.onStartCommand(intent, flags, startId);
50
+ if ((Boolean)JRubyAdapter.runScriptlet(rubyClassName + ".instance_methods(false).any?{|m| m.to_sym == :on_start_command}")) {
51
+ // FIXME(uwe): Simplify when we stop support for RubotoCore 0.4.7
52
+ if (JRubyAdapter.isJRubyPreOneSeven()) {
53
+ JRubyAdapter.put("$arg_intent", intent);
54
+ JRubyAdapter.put("$arg_flags", flags);
55
+ JRubyAdapter.put("$arg_startId", startId);
56
+ JRubyAdapter.put("$ruby_instance", scriptInfo.getRubyInstance());
57
+ return (Integer) ((Number)JRubyAdapter.runScriptlet("$ruby_instance.on_start_command($arg_intent, $arg_flags, $arg_startId)")).intValue();
58
+ } else {
59
+ if (JRubyAdapter.isJRubyOneSeven()) {
60
+ return (Integer) JRubyAdapter.runRubyMethod(Integer.class, scriptInfo.getRubyInstance(), "on_start_command", new Object[]{intent, flags, startId});
61
+ } else {
62
+ throw new RuntimeException("Unknown JRuby version: " + JRubyAdapter.get("JRUBY_VERSION"));
23
63
  }
24
- System.out.println("RubotoService.onCreate()");
64
+ }
65
+ } else {
66
+ if ((Boolean)JRubyAdapter.runScriptlet(rubyClassName + ".instance_methods(false).any?{|m| m.to_sym == :onStartCommand}")) {
67
+ // FIXME(uwe): Simplify when we stop support for RubotoCore 0.4.7
68
+ if (JRubyAdapter.isJRubyPreOneSeven()) {
69
+ JRubyAdapter.put("$arg_intent", intent);
70
+ JRubyAdapter.put("$arg_flags", flags);
71
+ JRubyAdapter.put("$arg_startId", startId);
72
+ JRubyAdapter.put("$ruby_instance", scriptInfo.getRubyInstance());
73
+ return (Integer) ((Number)JRubyAdapter.runScriptlet("$ruby_instance.onStartCommand($arg_intent, $arg_flags, $arg_startId)")).intValue();
74
+ } else {
75
+ if (JRubyAdapter.isJRubyOneSeven()) {
76
+ return (Integer) JRubyAdapter.runRubyMethod(Integer.class, scriptInfo.getRubyInstance(), "onStartCommand", new Object[]{intent, flags, startId});
77
+ } else {
78
+ throw new RuntimeException("Unknown JRuby version: " + JRubyAdapter.get("JRUBY_VERSION"));
79
+ }
80
+ }
81
+ } else {
82
+ return super.onStartCommand(intent, flags, startId);
83
+ }
84
+ }
85
+ }
86
+
87
+ @Override
88
+ public android.os.IBinder onBind(android.content.Intent intent) {
89
+ if (ScriptLoader.isCalledFromJRuby()) return null;
90
+ if (!JRubyAdapter.isInitialized()) {
91
+ Log.i("Method called before JRuby runtime was initialized: RubotoService#onBind");
92
+ return null;
93
+ }
25
94
 
26
- if (JRubyAdapter.setUpJRuby(this)) {
27
- ScriptLoader.loadScript(this);
95
+ if (JRubyAdapter.isInitialized() && !scriptInfo.isLoaded()) {
96
+ scriptInfo.setFromIntent(intent);
97
+ ScriptLoader.loadScript(this);
98
+ }
99
+
100
+ String rubyClassName = scriptInfo.getRubyClassName();
101
+ if (rubyClassName == null) return null;
102
+ if ((Boolean)JRubyAdapter.runScriptlet(rubyClassName + ".instance_methods(false).any?{|m| m.to_sym == :on_bind}")) {
103
+ // FIXME(uwe): Simplify when we stop support for RubotoCore 0.4.7
104
+ if (JRubyAdapter.isJRubyPreOneSeven()) {
105
+ JRubyAdapter.put("$arg_intent", intent);
106
+ JRubyAdapter.put("$ruby_instance", scriptInfo.getRubyInstance());
107
+ return (android.os.IBinder) JRubyAdapter.runScriptlet("$ruby_instance.on_bind($arg_intent)");
108
+ } else {
109
+ if (JRubyAdapter.isJRubyOneSeven()) {
110
+ return (android.os.IBinder) JRubyAdapter.runRubyMethod(android.os.IBinder.class, scriptInfo.getRubyInstance(), "on_bind", intent);
111
+ } else {
112
+ throw new RuntimeException("Unknown JRuby version: " + JRubyAdapter.get("JRUBY_VERSION"));
113
+ }
114
+ }
115
+ } else {
116
+ if ((Boolean)JRubyAdapter.runScriptlet(rubyClassName + ".instance_methods(false).any?{|m| m.to_sym == :onBind}")) {
117
+ // FIXME(uwe): Simplify when we stop support for RubotoCore 0.4.7
118
+ if (JRubyAdapter.isJRubyPreOneSeven()) {
119
+ JRubyAdapter.put("$arg_intent", intent);
120
+ JRubyAdapter.put("$ruby_instance", scriptInfo.getRubyInstance());
121
+ return (android.os.IBinder) JRubyAdapter.runScriptlet("$ruby_instance.onBind($arg_intent)");
28
122
  } else {
29
- // FIXME(uwe): What to do if the Ruboto Core platform cannot be found?
123
+ if (JRubyAdapter.isJRubyOneSeven()) {
124
+ return (android.os.IBinder) JRubyAdapter.runRubyMethod(android.os.IBinder.class, scriptInfo.getRubyInstance(), "onBind", intent);
125
+ } else {
126
+ throw new RuntimeException("Unknown JRuby version: " + JRubyAdapter.get("JRUBY_VERSION"));
127
+ }
30
128
  }
129
+ } else {
130
+ return null;
131
+ }
31
132
  }
133
+ }
134
+
32
135
 
33
136
  /****************************************************************************************
34
137
  *
@@ -131,7 +131,7 @@ public class EntryPointActivity extends org.ruboto.RubotoActivity {
131
131
  }
132
132
 
133
133
  private static final String RUBOTO_APK = "RubotoCore-release.apk";
134
- private static final String RUBOTO_URL = "https://github.com/downloads/ruboto/ruboto/" + RUBOTO_APK;
134
+ private static final String RUBOTO_URL = "https://raw.github.com/ruboto/ruboto-core/master/dist/" + RUBOTO_APK;
135
135
 
136
136
  // Called when the button is pressed.
137
137
  public void getRubotoCore(View view) {
@@ -262,6 +262,11 @@ public class JRubyAdapter {
262
262
  System.setProperty("jruby.ji.proxyClassFactory", "org.ruboto.DalvikProxyClassFactory");
263
263
  System.setProperty("jruby.class.cache.path", appContext.getDir("dex", 0).getAbsolutePath());
264
264
 
265
+ // Workaround for bug in Android 2.2
266
+ // http://code.google.com/p/android/issues/detail?id=9431
267
+ // System.setProperty("java.net.preferIPv4Stack", "true");
268
+ // System.setProperty("java.net.preferIPv6Addresses", "false");
269
+
265
270
  ClassLoader classLoader;
266
271
  Class<?> scriptingContainerClass;
267
272
  String apkName = null;
@@ -439,14 +444,15 @@ public class JRubyAdapter {
439
444
 
440
445
  static void printStackTrace(Throwable t) {
441
446
  // TODO(uwe): Simplify this when Issue #144 is resolved
442
- try {
443
- t.printStackTrace(output);
444
- } catch (NullPointerException npe) {
447
+ // TODO(scott): printStackTrace is causing too many problems
448
+ //try {
449
+ // t.printStackTrace(output);
450
+ //} catch (NullPointerException npe) {
445
451
  // TODO(uwe): printStackTrace should not fail
446
452
  for (java.lang.StackTraceElement ste : t.getStackTrace()) {
447
453
  output.append(ste.toString() + "\n");
448
454
  }
449
- }
455
+ //}
450
456
  }
451
457
 
452
458
  private static String scriptsDirName(Context context) {
@@ -128,6 +128,16 @@ public class Script {
128
128
  return null;
129
129
  }
130
130
 
131
+ public File getFile() {
132
+ for (String dir : scriptsDir) {
133
+ File f = new File(dir, name);
134
+ if (f.exists()) {
135
+ return f;
136
+ }
137
+ }
138
+ return new File(scriptsDir[0], name);
139
+ }
140
+
131
141
  public String getContents() throws IOException {
132
142
  InputStream is = null;
133
143
  BufferedReader buffer = null;
@@ -152,16 +162,6 @@ public class Script {
152
162
  }
153
163
  }
154
164
 
155
- public File getFile() {
156
- for (String dir : scriptsDir) {
157
- File f = new File(dir, name);
158
- if (f.exists()) {
159
- return f;
160
- }
161
- }
162
- return new File(scriptsDir[0], name);
163
- }
164
-
165
165
  public String getName() {
166
166
  return name;
167
167
  }
@@ -5,6 +5,27 @@ public class ScriptInfo {
5
5
  private String scriptName;
6
6
  private Object rubyInstance;
7
7
 
8
+ public boolean isReadyToLoad() {
9
+ return rubyClassName != null || scriptName != null;
10
+ }
11
+
12
+ public boolean isLoaded() {
13
+ return rubyInstance != null;
14
+ }
15
+
16
+ public void setFromIntent(android.content.Intent intent) {
17
+ android.os.Bundle configBundle = intent.getBundleExtra("Ruboto Config");
18
+
19
+ if (configBundle != null) {
20
+ if (configBundle.containsKey("ClassName")) {
21
+ setRubyClassName(configBundle.getString("ClassName"));
22
+ }
23
+ if (configBundle.containsKey("Script")) {
24
+ setScriptName(configBundle.getString("Script"));
25
+ }
26
+ }
27
+ }
28
+
8
29
  public String getRubyClassName() {
9
30
  if (rubyClassName == null && scriptName != null) {
10
31
  return Script.toCamelCase(scriptName);
@@ -40,9 +40,10 @@ module Ruboto
40
40
  b = Java::android.os.Bundle.new
41
41
  b.putInt("Theme", theme) if theme
42
42
  b.putString("ClassName", class_name)
43
+ b.putString("Script", options[:script]) if options[:script]
43
44
  i = android.content.Intent.new
44
45
  i.setClass self, klass.java_class
45
- i.putExtra("RubotoActivity Config", b)
46
+ i.putExtra("Ruboto Config", b)
46
47
  startActivity i
47
48
  self
48
49
  end
@@ -14,7 +14,18 @@ java_import "org.ruboto.RubotoService"
14
14
 
15
15
  module Ruboto
16
16
  module Context
17
- def start_ruboto_service(global_variable_name = '$service', klass=RubotoService, &block)
17
+ def start_ruboto_service(global_variable_name='$service', klass=RubotoService, options={}, &block)
18
+ # FIXME(uwe): Translate old positional signature to new options-based signature.
19
+ # FIXME(uwe): Remove when we stop supporting Ruboto 0.8.0 or older.
20
+ if options.nil?
21
+ if global_variable_name.is_a?(Hash)
22
+ options = global_variable_name
23
+ else
24
+ options = {}
25
+ end
26
+ global_variable_name = nil
27
+ end
28
+
18
29
  class_name = options[:class_name] || "#{klass.name.split('::').last}_#{source_descriptor(block)[0].split("/").last.gsub(/[.-]+/, '_')}_#{source_descriptor(block)[1]}"
19
30
  if !Object.const_defined?(class_name)
20
31
  Object.const_set(class_name, Class.new(&block))
@@ -22,12 +33,12 @@ module Ruboto
22
33
  Object.const_get(class_name).class_eval(&block) if block_given?
23
34
  end
24
35
  b = Java::android.os.Bundle.new
25
- b.putInt("Theme", theme) if theme
26
36
  b.putString("ClassName", class_name)
37
+ b.putString("Script", options[:script]) if options[:script]
27
38
  i = android.content.Intent.new
28
39
  i.setClass self, klass.java_class
29
- i.putExtra("RubotoActivity Config", b)
30
- self.startService Java::android.content.Intent.new(self, klass.java_class)
40
+ i.putExtra("Ruboto Config", b)
41
+ self.startService i
31
42
  self
32
43
  end
33
44
  end
@@ -159,10 +159,10 @@ def setup_list_view
159
159
  Java::android.widget.ListView.class_eval do
160
160
  def configure(context, params = {})
161
161
  if list = params.delete(:list)
162
- adapter_list = Java::java.util.ArrayList.new
163
- adapter_list.addAll(list)
162
+ @adapter_list = Java::java.util.ArrayList.new
163
+ @adapter_list.addAll(list)
164
164
  item_layout = params.delete(:item_layout) || R::layout::simple_list_item_1
165
- params[:adapter] = Java::android.widget.ArrayAdapter.new(context, item_layout, adapter_list)
165
+ params[:adapter] = Java::android.widget.ArrayAdapter.new(context, item_layout, @adapter_list)
166
166
  end
167
167
  super(context, params)
168
168
  end
@@ -170,7 +170,7 @@ def setup_list_view
170
170
  def reload_list(list)
171
171
  @adapter_list.clear
172
172
  @adapter_list.addAll(list)
173
- @adapter.notifyDataSetChanged
173
+ adapter.notifyDataSetChanged
174
174
  invalidate
175
175
  end
176
176
  end
@@ -104,7 +104,7 @@ module Ruboto
104
104
  update_icons true
105
105
  update_classes nil, true
106
106
  update_jruby true if with_jruby
107
- update_dx_jar true unless params['with-jruby'].value
107
+ update_dx_jar true if with_jruby
108
108
  update_core_classes 'include'
109
109
 
110
110
  log_action("Generating the default Activity and script") do
@@ -312,25 +312,6 @@ module Ruboto
312
312
  generate_core_classes [:class, :method_base, :method_include, :method_exclude, :implements, :force].inject({}) {|h, i| h[i] = params[i.to_s].value; h}
313
313
  end
314
314
  end
315
-
316
- mode "key" do
317
- option("keystore"){
318
- default "~/.android/production.keystore"
319
- description "path to where the keystore will be saved. defaults to ~/.android/production.keystore"
320
- }
321
-
322
- option("alias"){
323
- required
324
- description "The 'alias' for the key. Identifies the key within the keystore. Required"
325
- }
326
-
327
- def run
328
- keystore = params['keystore'].value
329
- key_alias = params['alias'].value
330
-
331
- `keytool -genkey -keyalg rsa -keysize 4096 -validity 1000000 -keystore #{keystore} -alias #{key_alias}`
332
- end
333
- end
334
315
  end
335
316
 
336
317
  mode "update" do
@@ -0,0 +1,15 @@
1
+ class REXML::Formatters::OrderedAttributes < REXML::Formatters::Pretty
2
+ def write_element(elm, out)
3
+ att = elm.attributes
4
+
5
+ class <<att
6
+ alias _each_attribute each_attribute
7
+
8
+ def each_attribute(&b)
9
+ to_enum(:_each_attribute).sort_by { |x| [x.prefix, x.name] }.each(&b)
10
+ end
11
+ end
12
+
13
+ super(elm, out)
14
+ end
15
+ end
@@ -6,7 +6,13 @@ module Ruboto
6
6
  MINIMUM_SUPPORTED_SDK = "android-#{MINIMUM_SUPPORTED_SDK_LEVEL}"
7
7
  DEFAULT_TARGET_SDK_LEVEL = 8
8
8
  DEFAULT_TARGET_SDK = "android-#{DEFAULT_TARGET_SDK_LEVEL}"
9
- ANDROID_HOME = ENV['ANDROID_HOME'] || File.dirname(File.dirname(Pathname.new(`#{RUBY_PLATFORM =~ /mingw|mswin/ ? "where" : "which"} adb`.chomp).realpath))
9
+ if ENV['ANDROID_HOME']
10
+ ANDROID_HOME = ENV['ANDROID_HOME']
11
+ else
12
+ adb_location = `#{RUBY_PLATFORM =~ /mingw|mswin/ ? "where" : "which"} adb`.chomp
13
+ raise 'Unable to locate ANDROID_HOME. Either set the ANDROID_HOME environment variable or add the location of the "adb" command to your path.' if adb_location.empty?
14
+ ANDROID_HOME = File.dirname(File.dirname(Pathname.new(adb_location).realpath))
15
+ end
10
16
  ANDROID_TOOLS_REVISION = File.read("#{ANDROID_HOME}/tools/source.properties").slice(/Pkg.Revision=\d+/).slice(/\d+$/).to_i
11
17
  end
12
18
  end
@@ -135,7 +135,7 @@ module Ruboto
135
135
  def generate_core_classes(params)
136
136
  hash = {:package => "org.ruboto"}
137
137
  %w(method_base method_include implements force).inject(hash) {|h, i| h[i.to_sym] = params[i.to_sym]; h}
138
- hash[:method_exclude] = params[:method_exclude].split(",").push("onCreate").join(",")
138
+ hash[:method_exclude] = params[:method_exclude].split(",").push("onCreate").push("onBind").push("onStartCommand").join(",")
139
139
 
140
140
  %w(android.app.Activity android.app.Service android.content.BroadcastReceiver).each do |i|
141
141
  name = i.split(".")[-1]
@@ -1,4 +1,5 @@
1
1
  require 'ruboto/version'
2
+ require 'ruboto/core_ext/rexml'
2
3
 
3
4
  module Ruboto
4
5
  module Util
@@ -66,7 +67,7 @@ module Ruboto
66
67
  # puts 'Added external permission tag'
67
68
  # end
68
69
 
69
- File.open("AndroidManifest.xml", 'w') { |f| test_manifest.document.write(f, 4) }
70
+ File.open("AndroidManifest.xml", 'w') { |f| REXML::Formatters::OrderedAttributes.new(4).write(test_manifest.document, f) }
70
71
 
71
72
  run_tests_override = <<-EOF
72
73
  <!-- BEGIN added by Ruboto -->
@@ -160,13 +161,11 @@ module Ruboto
160
161
  log_action("Copying #{JRubyJars::core_jar_path} to libs") { copier.copy_from_absolute_path JRubyJars::core_jar_path, "libs" }
161
162
  log_action("Copying #{JRubyJars::stdlib_jar_path} to libs") { copier.copy_from_absolute_path JRubyJars::stdlib_jar_path, "libs" }
162
163
 
163
- # FIXME(uwe): Try keeping the class count low to enable installation on Android 2.3 devices
164
- # unless new_jruby_version =~ /^1.7.0/ && verify_target_sdk < 15
165
164
  log_action("Copying dx.jar to libs") do
166
165
  copier.copy 'libs'
166
+ # FIXME(uwe): We may need this for newer Android SDK versions. Keeping as reminder.
167
167
  # File.open('project.properties', 'a'){|f| f << "dex.force.jumbo=true\n"}
168
168
  end
169
- # end
170
169
 
171
170
  reconfigure_jruby_libs(new_jruby_version)
172
171
 
@@ -181,19 +180,15 @@ module Ruboto
181
180
 
182
181
  jar_file = Dir.glob("libs/dx.jar")[0]
183
182
 
184
- # FIXME(uwe): Skip copying dx.jar to apps using RubotoCore when we include dx.jar in RubotoCore
183
+ # FIXME(uwe): Remove when we stop updating from Ruboto 0.10.0 and older.
184
+ jruby_present = !!Dir.glob("libs/jruby-core-*.jar")[0]
185
+ log_action("Removing #{jar_file}") { File.delete jar_file } if jar_file && !jruby_present
186
+ # EMXIF
187
+
185
188
  return if !jar_file && !force
186
189
 
187
190
  copier = AssetCopier.new Ruboto::ASSETS, File.expand_path(".")
188
- # FIXME(uwe): Skip copying dx.jar to apps using RubotoCore when we include dx.jar in RubotoCore
189
- log_action("Removing #{jar_file}") { File.delete jar_file } if jar_file
190
-
191
- # FIXME(uwe): Try keeping the class count low to enable installation on Android 2.3 devices
192
- # FIXME(uwe): Skip copying dx.jar to apps using RubotoCore when we include dx.jar in RubotoCore
193
- #if verify_target_sdk < 15
194
- # log_action("Copying dx.jar to libs") { copier.copy 'libs' }
195
- #end
196
- # EMXIF
191
+ log_action("Copying dx.jar to libs") { copier.copy 'libs' }
197
192
  end
198
193
 
199
194
  def update_assets
@@ -362,7 +357,7 @@ module Ruboto
362
357
  `jar -xf #{jruby_core}`
363
358
  raise "Unpacking jruby-core jar failed: #$?" unless $? == 0
364
359
  File.delete jruby_core
365
- if Gem::Version.new(jruby_core_version) >= Gem::Version.new('1.7.1.dev')
360
+ if Gem::Version.new(jruby_core_version) >= Gem::Version.new('1.7.2.dev')
366
361
  excluded_core_packages = [
367
362
  '**/*Darwin*',
368
363
  '**/*Ruby20*',
@@ -404,6 +399,48 @@ module Ruboto
404
399
 
405
400
  # 'org/jruby/runtime/invokedynamic', # Should be excluded
406
401
  ]
402
+ elsif Gem::Version.new(jruby_core_version) >= Gem::Version.new('1.7.1.dev')
403
+ excluded_core_packages = [
404
+ '**/*Darwin*',
405
+ '**/*Ruby20*',
406
+ '**/*Solaris*',
407
+ '**/*windows*',
408
+ '**/*Windows*',
409
+ 'META-INF',
410
+ 'com/headius',
411
+ 'com/kenai/constantine', 'com/kenai/jffi', 'com/martiansoftware',
412
+ 'jline', 'jni',
413
+ 'jnr/constants/platform/darwin', 'jnr/constants/platform/fake', 'jnr/constants/platform/freebsd',
414
+ 'jnr/constants/platform/openbsd', 'jnr/constants/platform/sunos',
415
+ 'jnr/ffi/annotations', 'jnr/ffi/byref',
416
+ 'jnr/ffi/provider', 'jnr/ffi/util',
417
+ 'jnr/ffi/Struct$*',
418
+ 'jnr/ffi/types',
419
+ 'jnr/posix/MacOS*',
420
+ 'jnr/posix/OpenBSD*',
421
+ 'org/apache',
422
+ 'org/fusesource',
423
+ 'org/jruby/ant',
424
+ 'org/jruby/cext',
425
+ # 'org/jruby/compiler', # Needed for initialization, but shoud not be necessary
426
+ # 'org/jruby/compiler/impl', # Needed for initialization, but shoud not be necessary
427
+ 'org/jruby/compiler/util',
428
+ 'org/jruby/demo',
429
+ 'org/jruby/embed/bsf',
430
+ 'org/jruby/embed/jsr223',
431
+ 'org/jruby/embed/osgi',
432
+ # 'org/jruby/ext/ffi', # Used by several JRuby core classes, but should not be needed unless we add FFI support
433
+ 'org/jruby/ext/ffi/io',
434
+ 'org/jruby/ext/ffi/jffi',
435
+ 'org/jruby/ext/openssl', # TODO(uwe): Issue #154 Add back when we add jruby-openssl.
436
+ 'org/jruby/javasupport/bsf',
437
+
438
+ # 'org/jruby/management', # should be excluded
439
+
440
+ 'org/jruby/org/bouncycastle', # TODO(uwe): Issue #154 Add back when we add jruby-openssl. The bouncycastle included in Android is cripled.
441
+
442
+ # 'org/jruby/runtime/invokedynamic', # Should be excluded
443
+ ]
407
444
  elsif Gem::Version.new(jruby_core_version) >= Gem::Version.new('1.7.0')
408
445
  # TODO(uwe): Remove when we stop supporting jruby-jars 1.7.0
409
446
  excluded_core_packages = [
@@ -17,7 +17,7 @@ module Ruboto
17
17
  end
18
18
 
19
19
  def save_manifest
20
- File.open("AndroidManifest.xml", 'w') {|f| verify_manifest.document.write(f, 4)}
20
+ File.open("AndroidManifest.xml", 'w') {|f| REXML::Formatters::OrderedAttributes.new(4).write(verify_manifest.document, f)}
21
21
  end
22
22
 
23
23
  def verify_test_manifest
@@ -1,4 +1,4 @@
1
1
  module Ruboto
2
- VERSION = '0.10.0'
2
+ VERSION = '0.10.1'
3
3
  UPDATE_VERSION_LIMIT = '0.7.0'
4
4
  end
@@ -19,6 +19,7 @@ class NavigationActivity
19
19
  button :text => 'Inline block with options', :width => :match_parent, :id => 47, :on_click_listener => proc { start_inline_activity_with_options }
20
20
  button :text => 'Infile class', :width => :match_parent, :id => 48, :on_click_listener => proc { start_infile_activity }
21
21
  button :text => 'Ruby file activity', :width => :match_parent, :id => 49, :on_click_listener => proc { start_ruby_file_activity }
22
+ button :text => 'RubotoActivity no config', :width => :match_parent, :id => 50, :on_click_listener => proc { start_ruboto_activity_no_config }
22
23
  end
23
24
  end
24
25
 
@@ -35,7 +36,7 @@ class NavigationActivity
35
36
  i.setClassName($package_name, 'org.ruboto.RubotoActivity')
36
37
  configBundle = android.os.Bundle.new
37
38
  configBundle.put_string('ClassName', 'NavigationTargetActivity')
38
- i.putExtra('RubotoActivity Config', configBundle)
39
+ i.putExtra('Ruboto Config', configBundle)
39
40
  startActivity(i)
40
41
  end
41
42
 
@@ -44,7 +45,7 @@ class NavigationActivity
44
45
  i.setClassName($package_name, 'org.ruboto.RubotoActivity')
45
46
  configBundle = android.os.Bundle.new
46
47
  configBundle.put_string('Script', 'navigation_target_activity.rb')
47
- i.putExtra('RubotoActivity Config', configBundle)
48
+ i.putExtra('Ruboto Config', configBundle)
48
49
  startActivity(i)
49
50
  end
50
51
 
@@ -81,7 +82,7 @@ class NavigationActivity
81
82
  i.setClassName($package_name, 'org.ruboto.RubotoActivity')
82
83
  configBundle = android.os.Bundle.new
83
84
  configBundle.put_string('ClassName', 'InfileActivity')
84
- i.putExtra('RubotoActivity Config', configBundle)
85
+ i.putExtra('Ruboto Config', configBundle)
85
86
  startActivity(i)
86
87
  end
87
88
 
@@ -90,7 +91,13 @@ class NavigationActivity
90
91
  i.setClassName($package_name, 'org.ruboto.RubotoActivity')
91
92
  configBundle = android.os.Bundle.new
92
93
  configBundle.put_string('ClassName', 'RubyFileActivity')
93
- i.putExtra('RubotoActivity Config', configBundle)
94
+ i.putExtra('Ruboto Config', configBundle)
95
+ startActivity(i)
96
+ end
97
+
98
+ def start_ruboto_activity_no_config
99
+ i = android.content.Intent.new
100
+ i.setClassName($package_name, 'org.ruboto.RubotoActivity')
94
101
  startActivity(i)
95
102
  end
96
103
 
@@ -12,134 +12,35 @@ end
12
12
 
13
13
  test('Java backed activity is reloaded if source already loaded', :ui => false) do |activity|
14
14
  require 'navigation_target_activity'
15
- #::NavigationTargetActivity = ::RubyFileActivity
16
- #Object.const_set(:NavigationTargetActivity, RubyFileActivity)
17
- #Kernel.const_set(:NavigationTargetActivity, RubyFileActivity)
18
15
  button_activity_text 43, activity, 42, 'This is the navigation target activity.',
19
16
  'org.ruboto.test_app.NavigationTargetActivity'
20
17
  end
21
18
 
22
19
  test('button starts Java activity', :ui => false) do |activity|
23
- monitor = add_monitor('org.ruboto.test_app.NavigationTargetActivity', nil, false)
24
- begin
25
- activity.run_on_ui_thread { activity.find_view_by_id(43).perform_click }
26
- current_activity = wait_for_monitor_with_timeout(monitor, 5000)
27
- assert current_activity
28
- current_activity.run_on_ui_thread { current_activity.finish }
29
- # FIXME(uwe): Replace sleep with proper monitor
30
- sleep 3
31
- ensure
32
- puts "Removing monitor"
33
- removeMonitor(monitor)
34
- end
20
+ button_activity_text 43, activity, 42, 'This is the navigation target activity.',
21
+ 'org.ruboto.test_app.NavigationTargetActivity'
35
22
  end
36
23
 
37
24
  test('button starts Ruby activity', :ui => false) do |activity|
38
- monitor = add_monitor('org.ruboto.RubotoActivity', nil, false)
39
- begin
40
- activity.run_on_ui_thread { activity.find_view_by_id(44).perform_click }
41
- current_activity = wait_for_monitor_with_timeout(monitor, 5000)
42
- assert current_activity
43
- current_activity.run_on_ui_thread { current_activity.finish }
44
- # FIXME(uwe): Replace sleep with proper monitor
45
- sleep 3
46
- ensure
47
- puts "Removing monitor"
48
- removeMonitor(monitor)
49
- end
25
+ button_activity_text 44, activity, 42, 'This is the navigation target activity.'
50
26
  end
51
27
 
52
28
  test('button starts activity by script name', :ui => false) do |activity|
53
- monitor = add_monitor('org.ruboto.RubotoActivity', nil, false)
54
- begin
55
- activity.run_on_ui_thread { activity.find_view_by_id(45).perform_click }
56
- current_activity = wait_for_monitor_with_timeout(monitor, 5000)
57
- assert current_activity
58
- current_activity.run_on_ui_thread { current_activity.finish }
59
- # FIXME(uwe): Replace sleep with proper monitor
60
- sleep 3
61
- ensure
62
- puts "Removing monitor"
63
- removeMonitor(monitor)
64
- end
29
+ button_activity_text 45, activity, 42, 'This is the navigation target activity.'
65
30
  end
66
31
 
67
32
  test('button starts inline activity', :ui => false) do |activity|
68
- monitor = add_monitor('org.ruboto.RubotoActivity', nil, false)
69
- begin
70
- activity.run_on_ui_thread { activity.find_view_by_id(46).perform_click }
71
- current_activity = wait_for_monitor_with_timeout(monitor, 5000)
72
- assert current_activity
73
- current_activity.run_on_ui_thread { current_activity.finish }
74
- # FIXME(uwe): Replace sleep with proper monitor
75
- sleep 3
76
- ensure
77
- puts "Removing monitor"
78
- removeMonitor(monitor)
79
- end
80
-
81
- start = Time.now
82
- loop do
83
- @text_view = current_activity.find_view_by_id(42)
84
- break if (@text_view && @text_view.text == 'This is an inline activity.') || (Time.now - start > 10)
85
- puts 'wait for text'
86
- sleep 0.5
87
- end
88
- assert @text_view
89
- assert_equal 'This is an inline activity.', @text_view.text
33
+ button_activity_text 46, activity, 42, 'This is an inline activity.'
90
34
  end
91
35
 
92
36
  test('button starts inline activity with options', :ui => false) do |activity|
93
- monitor = add_monitor('org.ruboto.RubotoActivity', nil, false)
94
- begin
95
- activity.run_on_ui_thread { activity.find_view_by_id(47).perform_click }
96
- current_activity = wait_for_monitor_with_timeout(monitor, 5000)
97
- assert current_activity
98
- current_activity.run_on_ui_thread { current_activity.finish }
99
- # FIXME(uwe): Replace sleep with proper monitor
100
- sleep 3
101
- ensure
102
- puts "Removing monitor"
103
- removeMonitor(monitor)
104
- end
105
-
106
- start = Time.now
107
- loop do
108
- @text_view = current_activity.find_view_by_id(42)
109
- break if (@text_view && @text_view.text == 'This is an inline activity.') || (Time.now - start > 10)
110
- puts 'wait for text'
111
- sleep 0.5
112
- end
113
- assert @text_view
114
- assert_equal 'This is an inline activity.', @text_view.text
37
+ button_activity_text 47, activity, 42, 'This is an inline activity.'
115
38
  end
116
39
 
117
40
  test('button starts infile class activity', :ui => false) do |activity|
118
- monitor = add_monitor('org.ruboto.RubotoActivity', nil, false)
119
- begin
120
- activity.run_on_ui_thread { activity.find_view_by_id(48).perform_click }
121
- current_activity = wait_for_monitor_with_timeout(monitor, 5000)
122
- ensure
123
- removeMonitor(monitor)
124
- end
125
- puts "new activity: #{current_activity.inspect}"
126
- assert current_activity
127
- assert current_activity.is_a? Java::OrgRuboto::RubotoActivity
128
- start = Time.now
129
- loop do
130
- @text_view = current_activity.find_view_by_id(42)
131
- break if @text_view || (Time.now - start > 10)
132
- puts 'wait for text'
133
- sleep 1
134
- end
135
- assert @text_view
136
- assert_equal 'This is an infile activity.', @text_view.text
137
- current_activity.run_on_ui_thread { current_activity.finish }
138
- # FIXME(uwe): Replace sleep with proper monitor
139
- sleep 3
41
+ button_activity_text 48, activity, 42, 'This is an infile activity.'
140
42
  end
141
43
 
142
-
143
44
  test("infile activity starts again", :ui => false) do |activity|
144
45
  button_activity_text 48, activity, 42, 'This is an infile activity.'
145
46
  end
@@ -152,17 +53,31 @@ test("start ruby file activity again", :ui => false) do |activity|
152
53
  button_activity_text 49, activity, 42, 'This is a Ruby file activity.'
153
54
  end
154
55
 
155
- def button_activity_text button_id, activity, expected_text_id, expected_text_string,
156
- activity_class_name = 'org.ruboto.RubotoActivity'
56
+ test("start ruboto activity without config", :ui => false) do |activity|
57
+ a = start_activity_by_button activity, 50
58
+ assert_equal 'Ruboto Test App', a.title
59
+ end
60
+
61
+ def start_activity_by_button(activity, button_id, activity_class_name = 'org.ruboto.RubotoActivity')
157
62
  monitor = add_monitor(activity_class_name, nil, false)
158
63
  begin
159
- activity.run_on_ui_thread { activity.find_view_by_id(button_id).perform_click }
64
+ activity.run_on_ui_thread do
65
+ btn = activity.find_view_by_id(button_id)
66
+ btn.request_focus
67
+ btn.perform_click
68
+ end
160
69
  current_activity = wait_for_monitor_with_timeout(monitor, 5000)
161
70
  ensure
162
71
  removeMonitor(monitor)
163
72
  end
164
73
  puts "new activity: #{current_activity.inspect}"
165
74
  assert current_activity.is_a? Java::OrgRuboto::RubotoActivity
75
+ current_activity
76
+ end
77
+
78
+ def button_activity_text button_id, activity, expected_text_id, expected_text_string,
79
+ activity_class_name = 'org.ruboto.RubotoActivity'
80
+ current_activity = start_activity_by_button(activity, button_id, activity_class_name)
166
81
  start = Time.now
167
82
  loop do
168
83
  @text_view = current_activity.find_view_by_id(expected_text_id)
@@ -174,8 +89,13 @@ def button_activity_text button_id, activity, expected_text_id, expected_text_st
174
89
  assert_equal expected_text_string, @text_view.text
175
90
  ensure
176
91
  if current_activity
177
- current_activity.run_on_ui_thread { current_activity.finish }
178
- # FIXME(uwe): Replace sleep with proper monitor
179
- sleep 3
92
+ finish_at = Time.now
93
+ finished = false
94
+ current_activity.run_on_ui_thread { current_activity.finish ; finished = true }
95
+ loop do
96
+ break if finished || (Time.now - finish_at > 10)
97
+ puts 'wait for finish'
98
+ sleep 0.1
99
+ end
180
100
  end
181
101
  end
@@ -21,23 +21,19 @@ test('stack depth') do |activity|
21
21
  }[android.os.Build::VERSION::SDK_INT] || [0, 0, 0, 0]
22
22
  if org.ruboto.JRubyAdapter.uses_platform_apk?
23
23
  jruby_offset = {
24
- '0.4.7' => [0, 0, 0, 0],
25
- '0.4.8.dev' => [0, 0, -4, -4],
26
- '0.4.8' => [0, 0, -4, -4],
27
- '0.4.9' => [0, 0, -4, -4],
24
+ '0.4.7' => [0, 0, 4, 4],
28
25
  }[org.ruboto.JRubyAdapter.platform_version_name] || [0, 0, 0, 0]
29
26
  else # STANDALONE
30
27
  jruby_offset = {
31
- '1.7.0.dev' => [1, 1, 1, 1],
32
- '1.7.0' => [0, 0, -4, -4],
33
- '1.7.1.dev' => [0, 0, -4, -4],
34
- }[org.jruby.runtime.Constants::VERSION] || [0, 0, 0, 0]
28
+ /^1\.6/ => [0, 0, 4, 4],
29
+ // => [0, 0, 0, 0],
30
+ }.find{|k,v| org.jruby.runtime.Constants::VERSION =~ k}[1]
35
31
  end
36
32
  version_message ="ANDROID: #{android.os.Build::VERSION::SDK_INT}, PLATFORM: #{org.ruboto.JRubyAdapter.uses_platform_apk ? org.ruboto.JRubyAdapter.platform_version_name : 'STANDALONE'}, JRuby: #{org.jruby.runtime.Constants::VERSION}"
37
33
  assert_equal [28 + os_offset[0] + jruby_offset[0],
38
34
  33 + os_offset[1] + jruby_offset[1],
39
- 50 + os_offset[2] + jruby_offset[2],
40
- 67 + os_offset[3] + jruby_offset[3]], [activity.find_view_by_id(42).text.to_i,
35
+ 46 + os_offset[2] + jruby_offset[2],
36
+ 63 + os_offset[3] + jruby_offset[3]], [activity.find_view_by_id(42).text.to_i,
41
37
  activity.find_view_by_id(43).text.to_i,
42
38
  activity.find_view_by_id(44).text.to_i,
43
39
  activity.find_view_by_id(45).text.to_i], version_message
@@ -13,11 +13,12 @@ if RubotoTest::RUBOTO_PLATFORM == 'STANDALONE'
13
13
  cleanup_app
14
14
  end
15
15
 
16
+ # APK was larger than 3.2MB: 3.5MB. JRuby: 1.6.7, ANDROID_TARGET: 15.
16
17
  # APK was larger than 3.2MB: 3.3MB. JRuby: 1.6.7.2, ANDROID_TARGET: 10.
17
18
  # APK was larger than 4.4MB: 4.7MB. JRuby: 1.7.0.preview2, ANDROID_TARGET: 10.
18
- # APK was larger than 3.2MB: 3.5MB. JRuby: 1.6.7, ANDROID_TARGET: 15.
19
19
  # APK was larger than 4.6MB: 4.9MB. JRuby: 1.7.0.preview2, ANDROID_TARGET: 15.
20
20
  # APK was larger than 3.2MB: 4.7MB. JRuby: 1.7.0, ANDROID_TARGET: 15.
21
+ # APK was larger than 4.9MB: 7.2MB. JRuby: 1.7.2.dev, ANDROID_TARGET: 10.
21
22
 
22
23
  def test_minimal_apk_is_less_than_3_mb
23
24
  apk_size = BigDecimal(File.size("#{APP_DIR}/bin/RubotoTestApp-debug.apk").to_s) / (1024 * 1024)
@@ -27,6 +28,7 @@ if RubotoTest::RUBOTO_PLATFORM == 'STANDALONE'
27
28
  '1.6.8' => 3.5,
28
29
  '1.7.0' => ANDROID_TARGET < 15 ? 4.7 : 4.9,
29
30
  '1.7.1.dev' => ANDROID_TARGET < 15 ? 4.7 : 4.9,
31
+ '1.7.2.dev' => 7.2,
30
32
  }[JRUBY_JARS_VERSION.to_s] || 4.9
31
33
  lower_limit = upper_limit * 0.9
32
34
  version_message ="JRuby: #{JRUBY_JARS_VERSION}, ANDROID_TARGET: #{ANDROID_TARGET}"
@@ -50,11 +50,12 @@ class RubotoGenTest < Test::Unit::TestCase
50
50
  end
51
51
 
52
52
  # APK was smaller than 277.2KB: 61.9KB. PLATFORM: CURRENT, ANDROID_TARGET: 10.
53
- # APK was larger than 7100.0KB: 7341.1KB. PLATFORM: STANDALONE, ANDROID_TARGET: 10, JRuby: 1.7.0.preview2.
54
53
  # APK was smaller than 278.1KB: 67.2KB. PLATFORM: CURRENT, ANDROID_TARGET: 15.
55
54
  # APK was larger than 5800.0KB: 5879.2KB. PLATFORM: STANDALONE, ANDROID_TARGET: 15, JRuby: 1.6.7.
55
+ # APK was larger than 7100.0KB: 7341.1KB. PLATFORM: STANDALONE, ANDROID_TARGET: 10, JRuby: 1.7.0.preview2.
56
56
  # APK was larger than 7308.0KB: 7558.3KB. PLATFORM: STANDALONE, ANDROID_TARGET: 15, JRuby: 1.7.0.preview2.
57
57
  # APK was larger than 4200.0KB: 7380.0KB. PLATFORM: STANDALONE, ANDROID_TARGET: 15, JRuby: 1.7.0.
58
+ # APK was larger than 7600.0KB: 9962.1KB. PLATFORM: STANDALONE, ANDROID_TARGET: 10, JRuby: 1.7.2.dev.
58
59
 
59
60
  def test_new_apk_size_is_within_limits
60
61
  apk_size = BigDecimal(File.size("#{APP_DIR}/bin/RubotoTestApp-debug.apk").to_s) / 1024
@@ -66,6 +67,7 @@ class RubotoGenTest < Test::Unit::TestCase
66
67
  '1.6.8' => 5900.0,
67
68
  '1.7.0' => ANDROID_TARGET < 15 ? 7400.0 : 7600.0,
68
69
  '1.7.1.dev' => ANDROID_TARGET < 15 ? 7400.0 : 7600.0,
70
+ '1.7.2.dev' => 9970.0,
69
71
  }[JRUBY_JARS_VERSION.to_s] || 7600.0
70
72
  version << ", JRuby: #{JRUBY_JARS_VERSION.to_s}"
71
73
  else
data/test/test_helper.rb CHANGED
@@ -302,8 +302,7 @@ class Test::Unit::TestCase
302
302
  fail "Unknown Ruboto platform: #{RUBOTO_PLATFORM.inspect}"
303
303
  end
304
304
  if $? != 0
305
- # FIXME(uwe): Delete failed RubotoCore. Kept temporarily for debuging.
306
- # FileUtils.rm_rf 'tmp/RubotoCore'
305
+ FileUtils.rm_rf 'tmp/RubotoCore'
307
306
  fail 'Error (un)installing RubotoCore'
308
307
  end
309
308
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruboto
3
3
  version: !ruby/object:Gem::Version
4
- hash: 55
4
+ hash: 53
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 10
9
- - 0
10
- version: 0.10.0
9
+ - 1
10
+ version: 0.10.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Daniel Jackoway
@@ -18,7 +18,7 @@ autorequire:
18
18
  bindir: bin
19
19
  cert_chain: []
20
20
 
21
- date: 2012-12-01 00:00:00 Z
21
+ date: 2013-01-01 00:00:00 Z
22
22
  dependencies:
23
23
  - !ruby/object:Gem::Dependency
24
24
  name: main
@@ -117,6 +117,7 @@ files:
117
117
  - lib/ruboto/commands/base.rb
118
118
  - lib/ruboto/core_ext/array.rb
119
119
  - lib/ruboto/core_ext/object.rb
120
+ - lib/ruboto/core_ext/rexml.rb
120
121
  - lib/ruboto/description.rb
121
122
  - lib/ruboto/sdk_versions.rb
122
123
  - lib/ruboto/util/asset_copier.rb