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 +3 -2
- data/Rakefile +10 -12
- data/assets/.gitignore +3 -1
- data/assets/rakelib/ruboto.rake +37 -25
- data/assets/src/RubotoActivity.java +3 -18
- data/assets/src/RubotoService.java +110 -7
- data/assets/src/org/ruboto/EntryPointActivity.java +1 -1
- data/assets/src/org/ruboto/JRubyAdapter.java +10 -4
- data/assets/src/org/ruboto/Script.java +10 -10
- data/assets/src/org/ruboto/ScriptInfo.java +21 -0
- data/assets/src/ruboto/activity.rb +2 -1
- data/assets/src/ruboto/service.rb +15 -4
- data/assets/src/ruboto/widget.rb +4 -4
- data/lib/ruboto/commands/base.rb +1 -20
- data/lib/ruboto/core_ext/rexml.rb +15 -0
- data/lib/ruboto/sdk_versions.rb +7 -1
- data/lib/ruboto/util/build.rb +1 -1
- data/lib/ruboto/util/update.rb +52 -15
- data/lib/ruboto/util/verify.rb +1 -1
- data/lib/ruboto/version.rb +1 -1
- data/test/activity/navigation_activity.rb +11 -4
- data/test/activity/navigation_activity_test.rb +32 -112
- data/test/activity/stack_activity_test.rb +6 -10
- data/test/minimal_app_test.rb +3 -1
- data/test/ruboto_gen_test.rb +3 -1
- data/test/test_helper.rb +1 -2
- metadata +5 -4
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,
|
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
|
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/
|
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 "
|
297
|
-
Dir.chdir
|
298
|
-
|
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
|
-
|
332
|
+
uri = URI('https://raw.github.com/ruboto/ruboto-core/master/dist/RubotoCore-release.apk')
|
339
333
|
begin
|
340
|
-
|
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
data/assets/rakelib/ruboto.rake
CHANGED
@@ -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
|
-
|
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
|
-
|
79
|
-
|
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
|
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 "
|
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("
|
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
|
-
|
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
|
-
|
21
|
-
|
22
|
-
|
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
|
-
|
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
|
-
|
27
|
-
|
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
|
-
|
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/
|
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
|
-
|
443
|
-
|
444
|
-
|
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("
|
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
|
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("
|
30
|
-
self.startService
|
40
|
+
i.putExtra("Ruboto Config", b)
|
41
|
+
self.startService i
|
31
42
|
self
|
32
43
|
end
|
33
44
|
end
|
data/assets/src/ruboto/widget.rb
CHANGED
@@ -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
|
-
|
173
|
+
adapter.notifyDataSetChanged
|
174
174
|
invalidate
|
175
175
|
end
|
176
176
|
end
|
data/lib/ruboto/commands/base.rb
CHANGED
@@ -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
|
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
|
data/lib/ruboto/sdk_versions.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/ruboto/util/build.rb
CHANGED
@@ -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]
|
data/lib/ruboto/util/update.rb
CHANGED
@@ -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|
|
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):
|
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
|
-
|
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.
|
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 = [
|
data/lib/ruboto/util/verify.rb
CHANGED
@@ -17,7 +17,7 @@ module Ruboto
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def save_manifest
|
20
|
-
File.open("AndroidManifest.xml", 'w') {|f|
|
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
|
data/lib/ruboto/version.rb
CHANGED
@@ -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('
|
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('
|
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('
|
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('
|
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
|
-
|
24
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
156
|
-
|
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
|
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
|
-
|
178
|
-
|
179
|
-
|
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,
|
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
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
40
|
-
|
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
|
data/test/minimal_app_test.rb
CHANGED
@@ -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}"
|
data/test/ruboto_gen_test.rb
CHANGED
@@ -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
|
-
|
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:
|
4
|
+
hash: 53
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 10
|
9
|
-
-
|
10
|
-
version: 0.10.
|
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:
|
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
|