ruboto 0.8.1 → 0.9.0.rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +75 -1
- data/assets/libs/dx.jar +0 -0
- data/assets/src/org/ruboto/JRubyAdapter.java +6 -1
- data/assets/src/org/ruboto/Script.java +2 -2
- data/lib/DalvikProxyClassFactory.java +107 -0
- data/lib/DexClient.java +85 -0
- data/lib/ruboto/commands/base.rb +2 -2
- data/lib/ruboto/util/update.rb +38 -48
- data/lib/ruboto/version.rb +1 -1
- data/test/activity/stack_activity_test.rb +4 -2
- data/test/activity/subclass_activity.rb +33 -0
- data/test/activity/{generate_activity_test.rb → subclass_activity_test.rb} +1 -1
- data/test/app_test_methods.rb +4 -0
- data/test/block_def_activity/stack_activity_test.rb +1 -0
- data/test/handle_activity/stack_activity_test.rb +1 -0
- data/test/minimal_app_test.rb +10 -2
- data/test/ruboto_gen_test.rb +31 -11
- data/test/sqldroid_test.rb +13 -15
- data/test/test_helper.rb +40 -27
- metadata +19 -14
- data/assets/libs/dexmaker20120305.jar +0 -0
- data/assets/src/ruboto/generate.rb +0 -462
- data/test/activity/generate_activity.rb +0 -35
data/Rakefile
CHANGED
@@ -142,6 +142,80 @@ task :release_docs do
|
|
142
142
|
puts "* https://github.com/ruboto/ruboto/issues?state=closed&milestone=#{milestone}\n\n"
|
143
143
|
end
|
144
144
|
|
145
|
+
desc 'Fetch download stats form rubygems.org'
|
146
|
+
task :stats do
|
147
|
+
require 'rubygems'
|
148
|
+
require 'uri'
|
149
|
+
require 'net/http'
|
150
|
+
require 'net/https'
|
151
|
+
require 'openssl'
|
152
|
+
require 'yaml'
|
153
|
+
host = 'rubygems.org'
|
154
|
+
base_uri = "https://#{host}/api/v1"
|
155
|
+
https = Net::HTTP.new(host, 443)
|
156
|
+
https.use_ssl = true
|
157
|
+
https.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
158
|
+
|
159
|
+
counts_per_month = Hash.new{|h, k| h[k] = Hash.new{|mh,mk| mh[mk] = 0 }}
|
160
|
+
total = 0
|
161
|
+
|
162
|
+
%w{ruboto-core ruboto}.each do |gem|
|
163
|
+
versions_uri = URI("#{base_uri}/versions/#{gem}.yaml")
|
164
|
+
req = Net::HTTP::Get.new(versions_uri.request_uri)
|
165
|
+
res = https.start { |http| http.request(req) }
|
166
|
+
versions = YAML.load(res.body).sort_by { |v| Gem::Version.new(v['number']) }
|
167
|
+
puts "\n#{gem}:\n#{versions.map { |v| "#{'%10s' % v['number']} #{v['downloads_count']}" }.join("\n")}"
|
168
|
+
|
169
|
+
versions.each do |v|
|
170
|
+
downloads_uri = URI("#{base_uri}/versions/#{gem}-#{v['number']}/downloads/search.yaml?from=2010-08-01&to=#{Date.today}")
|
171
|
+
req = Net::HTTP::Get.new(downloads_uri.request_uri)
|
172
|
+
res = https.start { |http| http.request(req) }
|
173
|
+
counts = YAML.load(res.body)
|
174
|
+
counts.each do |date_str, count|
|
175
|
+
date = Date.parse(date_str)
|
176
|
+
counts_per_month[date.year][date.month] += count
|
177
|
+
total += count
|
178
|
+
end
|
179
|
+
print '.' ; STDOUT.flush
|
180
|
+
end
|
181
|
+
puts
|
182
|
+
end
|
183
|
+
|
184
|
+
puts "\nDownloads statistics per month:"
|
185
|
+
years = counts_per_month.keys
|
186
|
+
puts "\n #{years.map{|year| '%6s:' % year}.join(' ')}"
|
187
|
+
(1..12).each do |month|
|
188
|
+
print "#{'%2d' % month}:"
|
189
|
+
years.each do |year|
|
190
|
+
count = counts_per_month[year][month]
|
191
|
+
print count > 0 ? '%8d' % count : ' ' * 8
|
192
|
+
end
|
193
|
+
puts
|
194
|
+
end
|
195
|
+
|
196
|
+
puts "\nTotal: #{total}\n\n"
|
197
|
+
|
198
|
+
puts "\nRubyGems download statistics per month:"
|
199
|
+
years = counts_per_month.keys
|
200
|
+
puts ' ' + years.map{|year| '%-12s' % year}.join
|
201
|
+
(0..20).each do |l|
|
202
|
+
print (l % 10 == 0) ? '%4d' % ((20-l) * 100) : ' '
|
203
|
+
years.each do |year|
|
204
|
+
(1..12).each do |month|
|
205
|
+
count = counts_per_month[year][month]
|
206
|
+
if [year, month] == [Date.today.year, Date.today.month]
|
207
|
+
count *= (Date.new(Date.today.year, Date.today.month, -1).day.to_f / Date.today.day).to_i
|
208
|
+
end
|
209
|
+
print count > ((20-l) * 100) ? '*' : ' '
|
210
|
+
end
|
211
|
+
end
|
212
|
+
puts
|
213
|
+
end
|
214
|
+
puts ' ' + years.map{|year| '%-12s' % year}.join
|
215
|
+
|
216
|
+
puts "\nTotal: #{total}\n\n"
|
217
|
+
end
|
218
|
+
|
145
219
|
desc "Push the gem to RubyGems"
|
146
220
|
task :release => [:clean, :gem] do
|
147
221
|
output = `git status --porcelain`
|
@@ -180,7 +254,7 @@ namespace :platform do
|
|
180
254
|
Dir.chdir(PLATFORM_PROJECT) do
|
181
255
|
manifest = REXML::Document.new(File.read(MANIFEST_FILE))
|
182
256
|
manifest.root.attributes['android:versionCode'] = '408'
|
183
|
-
manifest.root.attributes['android:versionName'] = '0.4.8
|
257
|
+
manifest.root.attributes['android:versionName'] = '0.4.8'
|
184
258
|
manifest.root.attributes['android:installLocation'] = 'auto' # or 'preferExternal' ?
|
185
259
|
File.open(MANIFEST_FILE, 'w') { |f| manifest.document.write(f, 4) }
|
186
260
|
File.open('Gemfile.apk', 'w'){|f| f << "source :rubygems\n\ngem 'activerecord-jdbc-adapter'\n"}
|
data/assets/libs/dx.jar
ADDED
Binary file
|
@@ -238,7 +238,8 @@ public class JRubyAdapter {
|
|
238
238
|
// END Ruboto HeapAlloc
|
239
239
|
setDebugBuild(appContext);
|
240
240
|
Log.d("Setting up JRuby runtime (" + (isDebugBuild ? "DEBUG" : "RELEASE") + ")");
|
241
|
-
System.setProperty("jruby.compile.mode", "OFF"); // OFF OFFIR
|
241
|
+
System.setProperty("jruby.compile.mode", "OFF"); // OFF OFFIR JITIR? FORCEIR
|
242
|
+
// System.setProperty("jruby.compile.backend", "DALVIK");
|
242
243
|
System.setProperty("jruby.bytecode.version", "1.6");
|
243
244
|
System.setProperty("jruby.interfaces.useProxy", "true");
|
244
245
|
System.setProperty("jruby.management.enabled", "false");
|
@@ -253,6 +254,10 @@ public class JRubyAdapter {
|
|
253
254
|
// System.setProperty("jruby.debug.loadService", "true");
|
254
255
|
// System.setProperty("jruby.debug.loadService.timing", "true");
|
255
256
|
|
257
|
+
// Used to enable JRuby to generate proxy classes
|
258
|
+
System.setProperty("jruby.ji.proxyClassFactory", "org.ruboto.DalvikProxyClassFactory");
|
259
|
+
System.setProperty("jruby.class.cache.path", appContext.getDir("dex", 0).getAbsolutePath());
|
260
|
+
|
256
261
|
ClassLoader classLoader;
|
257
262
|
Class<?> scriptingContainerClass;
|
258
263
|
String apkName = null;
|
@@ -40,9 +40,9 @@ public class Script {
|
|
40
40
|
public static String toSnakeCase(String s) {
|
41
41
|
return s.replaceAll(
|
42
42
|
String.format("%s|%s|%s",
|
43
|
-
"(?<=[A-Z])(?=[A-Z][a-
|
43
|
+
"(?<=[A-Z])(?=[A-Z][a-z0-9])",
|
44
44
|
"(?<=[^A-Z])(?=[A-Z])",
|
45
|
-
"(?<=[A-Za-
|
45
|
+
"(?<=[A-Za-z0-9])(?=[^A-Za-z0-9])"
|
46
46
|
),
|
47
47
|
"_"
|
48
48
|
).replace("__", "_").toLowerCase();
|
@@ -0,0 +1,107 @@
|
|
1
|
+
package org.ruboto;
|
2
|
+
|
3
|
+
import java.io.File;
|
4
|
+
import java.io.FileOutputStream;
|
5
|
+
import java.io.IOException;
|
6
|
+
import java.io.OutputStream;
|
7
|
+
import java.lang.reflect.Constructor;
|
8
|
+
import java.lang.reflect.Field;
|
9
|
+
import java.lang.reflect.InvocationTargetException;
|
10
|
+
import java.lang.reflect.Method;
|
11
|
+
import java.lang.reflect.Modifier;
|
12
|
+
import java.lang.reflect.UndeclaredThrowableException;
|
13
|
+
import java.security.AccessController;
|
14
|
+
import java.security.PrivilegedAction;
|
15
|
+
import java.security.ProtectionDomain;
|
16
|
+
import java.util.Arrays;
|
17
|
+
import java.util.HashMap;
|
18
|
+
import java.util.HashSet;
|
19
|
+
import java.util.Iterator;
|
20
|
+
import java.util.Map;
|
21
|
+
import java.util.Set;
|
22
|
+
import java.util.TreeMap;
|
23
|
+
import java.util.jar.Attributes;
|
24
|
+
import java.util.jar.JarEntry;
|
25
|
+
import java.util.jar.JarOutputStream;
|
26
|
+
import java.util.jar.Manifest;
|
27
|
+
|
28
|
+
import com.android.dx.Version;
|
29
|
+
import com.headius.android.dex.DexClient;
|
30
|
+
|
31
|
+
import dalvik.system.DexClassLoader;
|
32
|
+
|
33
|
+
public class DalvikProxyClassFactory extends org.jruby.javasupport.proxy.JavaProxyClassFactory {
|
34
|
+
private static final String DEX_IN_JAR_NAME = "classes.dex";
|
35
|
+
private static final Attributes.Name CREATED_BY = new Attributes.Name("Created-By");
|
36
|
+
|
37
|
+
public Class invokeDefineClass(ClassLoader loader, String className, byte[] data) {
|
38
|
+
String cachePath = System.getProperty("jruby.class.cache.path");
|
39
|
+
if (cachePath != null) {
|
40
|
+
byte[] dalvikByteCode = new DexClient().classesToDex(
|
41
|
+
new String[] { className.replace('.', '/') + ".class" }, new byte[][] { data });
|
42
|
+
String jarFileName = cachePath + "/" + className.replace('.', '/') + ".jar";
|
43
|
+
createJar(jarFileName, dalvikByteCode);
|
44
|
+
try {
|
45
|
+
return new DexClassLoader(jarFileName, cachePath, null, loader)
|
46
|
+
.loadClass(className);
|
47
|
+
} catch (ClassNotFoundException e1) {
|
48
|
+
System.out.println("Exception loading class with DexClassLoader: " + e1);
|
49
|
+
e1.printStackTrace();
|
50
|
+
}
|
51
|
+
}
|
52
|
+
return null;
|
53
|
+
}
|
54
|
+
|
55
|
+
private static boolean createJar(String fileName, byte[] dexArray) {
|
56
|
+
File parentFile = new File(fileName).getParentFile();
|
57
|
+
if (!parentFile.exists()) {
|
58
|
+
System.out.println("Creating directory: " + parentFile);
|
59
|
+
parentFile.mkdirs();
|
60
|
+
}
|
61
|
+
try {
|
62
|
+
TreeMap<String, byte[]> outputResources = new TreeMap<String, byte[]>();
|
63
|
+
Manifest manifest = makeManifest();
|
64
|
+
OutputStream out = (fileName.equals("-") || fileName.startsWith("-.")) ? System.out
|
65
|
+
: new FileOutputStream(fileName);
|
66
|
+
JarOutputStream jarOut = new JarOutputStream(out, manifest);
|
67
|
+
outputResources.put(DEX_IN_JAR_NAME, dexArray);
|
68
|
+
try {
|
69
|
+
for (Map.Entry<String, byte[]> e : outputResources.entrySet()) {
|
70
|
+
String name = e.getKey();
|
71
|
+
byte[] contents = e.getValue();
|
72
|
+
JarEntry entry = new JarEntry(name);
|
73
|
+
entry.setSize(contents.length);
|
74
|
+
jarOut.putNextEntry(entry);
|
75
|
+
jarOut.write(contents);
|
76
|
+
jarOut.closeEntry();
|
77
|
+
}
|
78
|
+
} finally {
|
79
|
+
jarOut.finish();
|
80
|
+
jarOut.flush();
|
81
|
+
if (out != null) {
|
82
|
+
out.flush();
|
83
|
+
if (out != System.out) {
|
84
|
+
out.close();
|
85
|
+
}
|
86
|
+
}
|
87
|
+
jarOut.close();
|
88
|
+
}
|
89
|
+
} catch (Exception ex) {
|
90
|
+
System.out.println("Exception writing jar: " + fileName);
|
91
|
+
System.out.println("Exception writing jar: " + ex);
|
92
|
+
ex.printStackTrace();
|
93
|
+
return false;
|
94
|
+
}
|
95
|
+
return true;
|
96
|
+
}
|
97
|
+
|
98
|
+
private static Manifest makeManifest() throws IOException {
|
99
|
+
Manifest manifest = new Manifest();
|
100
|
+
Attributes attribs = manifest.getMainAttributes();
|
101
|
+
attribs.put(Attributes.Name.MANIFEST_VERSION, "1.0");
|
102
|
+
attribs.put(CREATED_BY, "dx " + Version.VERSION);
|
103
|
+
attribs.putValue("Dex-Location", DEX_IN_JAR_NAME);
|
104
|
+
return manifest;
|
105
|
+
}
|
106
|
+
|
107
|
+
}
|
data/lib/DexClient.java
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
package com.headius.android.dex;
|
2
|
+
|
3
|
+
import java.io.ByteArrayOutputStream;
|
4
|
+
import java.io.OutputStreamWriter;
|
5
|
+
|
6
|
+
import com.android.dx.cf.iface.ParseException;
|
7
|
+
import com.android.dx.dex.cf.CfOptions;
|
8
|
+
import com.android.dx.dex.cf.CfTranslator;
|
9
|
+
import com.android.dx.dex.code.PositionList;
|
10
|
+
import com.android.dx.dex.file.ClassDefItem;
|
11
|
+
import com.android.dx.dex.file.DexFile;
|
12
|
+
|
13
|
+
public class DexClient {
|
14
|
+
/** {@code non-null;} output file in-progress */
|
15
|
+
private static DexFile outputDex;
|
16
|
+
|
17
|
+
private final CfOptions cfOptions;
|
18
|
+
|
19
|
+
public DexClient() {
|
20
|
+
outputDex = new DexFile();
|
21
|
+
cfOptions = new CfOptions();
|
22
|
+
|
23
|
+
cfOptions.positionInfo = PositionList.LINES;
|
24
|
+
cfOptions.localInfo = true;
|
25
|
+
cfOptions.strictNameCheck = true;
|
26
|
+
cfOptions.optimize = false;
|
27
|
+
cfOptions.optimizeListFile = null;
|
28
|
+
cfOptions.dontOptimizeListFile = null;
|
29
|
+
cfOptions.statistics = false;
|
30
|
+
}
|
31
|
+
|
32
|
+
public byte[] classesToDex(String[] names, byte[][] byteArrays) {
|
33
|
+
for (int i = 0; i < names.length; i++) {
|
34
|
+
String name = names[i];
|
35
|
+
byte[] byteArray = byteArrays[i];
|
36
|
+
processClass(name, byteArray);
|
37
|
+
}
|
38
|
+
|
39
|
+
byte[] outputArray = writeDex();
|
40
|
+
|
41
|
+
return outputArray;
|
42
|
+
}
|
43
|
+
|
44
|
+
/**
|
45
|
+
* Processes one classfile.
|
46
|
+
*
|
47
|
+
* @param name {@code non-null;} name of the file, clipped such that it
|
48
|
+
* <i>should</i> correspond to the name of the class it contains
|
49
|
+
* @param bytes {@code non-null;} contents of the file
|
50
|
+
* @return whether processing was successful
|
51
|
+
*/
|
52
|
+
private boolean processClass(String name, byte[] bytes) {
|
53
|
+
try {
|
54
|
+
ClassDefItem clazz =
|
55
|
+
CfTranslator.translate(name, bytes, cfOptions);
|
56
|
+
outputDex.add(clazz);
|
57
|
+
return true;
|
58
|
+
} catch (ParseException ex) {
|
59
|
+
ex.printStackTrace();
|
60
|
+
}
|
61
|
+
|
62
|
+
return false;
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Converts {@link #outputDex} into a {@code byte[]}, write
|
67
|
+
* it out to the proper file (if any), and also do whatever human-oriented
|
68
|
+
* dumping is required.
|
69
|
+
*
|
70
|
+
* @return {@code null-ok;} the converted {@code byte[]} or {@code null}
|
71
|
+
* if there was a problem
|
72
|
+
*/
|
73
|
+
private byte[] writeDex() {
|
74
|
+
byte[] outArray = null;
|
75
|
+
|
76
|
+
OutputStreamWriter out = new OutputStreamWriter(new ByteArrayOutputStream());
|
77
|
+
try {
|
78
|
+
outArray = outputDex.toDex(out, false);
|
79
|
+
} catch (Exception ex) {
|
80
|
+
ex.printStackTrace();
|
81
|
+
}
|
82
|
+
|
83
|
+
return outArray;
|
84
|
+
}
|
85
|
+
}
|
data/lib/ruboto/commands/base.rb
CHANGED
@@ -97,7 +97,7 @@ module Ruboto
|
|
97
97
|
update_icons true
|
98
98
|
update_classes nil, true
|
99
99
|
update_jruby true if params['with-jruby'].value
|
100
|
-
|
100
|
+
update_dx_jar true unless params['with-jruby'].value
|
101
101
|
update_core_classes "exclude"
|
102
102
|
|
103
103
|
log_action("Generating the default Activity and script") do
|
@@ -358,7 +358,7 @@ module Ruboto
|
|
358
358
|
update_assets
|
359
359
|
update_ruboto force
|
360
360
|
update_classes old_version, force
|
361
|
-
|
361
|
+
update_dx_jar force
|
362
362
|
update_jruby force
|
363
363
|
update_manifest nil, nil, force
|
364
364
|
update_icons force
|
data/lib/ruboto/util/update.rb
CHANGED
@@ -14,21 +14,9 @@ module Ruboto
|
|
14
14
|
def update_android
|
15
15
|
root = Dir.getwd
|
16
16
|
build_xml_file = "#{root}/build.xml"
|
17
|
-
new_prop_file = "#{root}/project.properties"
|
18
|
-
old_prop_file = "#{root}/default.properties"
|
19
17
|
name = REXML::Document.new(File.read(build_xml_file)).root.attributes['name']
|
20
18
|
|
21
|
-
|
22
|
-
# FIXME(uwe): Needed when updating apps from Android SDK <= 13 to 14
|
23
|
-
# FIXME(uwe): Remove when we stop supporting upgrading apps from Android SDK <= 13
|
24
|
-
if File.read(build_xml_file) !~ /<!-- version-tag: 1 -->/
|
25
|
-
puts "Forcing generation of new build.xml since upgrading a project generated with Android SDK 13 or older."
|
26
|
-
FileUtils.rm_f build_xml_file
|
27
|
-
end
|
28
|
-
# EMXIF
|
29
|
-
|
30
|
-
# FIXME(uwe): Simplify when we stop supporting upgrading apps from Android SDK <= 13
|
31
|
-
prop_file = File.exists?(new_prop_file) ? new_prop_file : old_prop_file
|
19
|
+
prop_file = "#{root}/project.properties"
|
32
20
|
version_regexp = /^(target=android-)(\d+)$/
|
33
21
|
if (project_property_file = File.read(prop_file)) =~ version_regexp
|
34
22
|
if $2.to_i < MINIMUM_SUPPORTED_SDK_LEVEL
|
@@ -36,9 +24,8 @@ module Ruboto
|
|
36
24
|
File.open(prop_file, 'w') { |f| f << project_property_file.gsub(version_regexp, "\\1#{MINIMUM_SUPPORTED_SDK_LEVEL}") }
|
37
25
|
end
|
38
26
|
end
|
39
|
-
# EMXIF
|
40
27
|
|
41
|
-
system "android update project -p #{root} -n #{name}"
|
28
|
+
system "android update project -p #{root} -n #{name} --subprojects"
|
42
29
|
raise "android update project failed with return code #{$?}" unless $? == 0
|
43
30
|
end
|
44
31
|
|
@@ -51,14 +38,11 @@ module Ruboto
|
|
51
38
|
FileUtils.rm_rf File.join(root, 'test', 'src', verify_package.split('.'))
|
52
39
|
puts "Done"
|
53
40
|
else
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
puts "\nUpdating Android test project #{name} in #{root}/test..."
|
60
|
-
system "android update test-project -m #{root} -p #{root}/test"
|
61
|
-
raise "android update test-project failed with return code #{$?}" unless $? == 0
|
41
|
+
test_ant_properties_file = 'test/ant.properties'
|
42
|
+
test_ant_properties = File.read(test_ant_properties_file)
|
43
|
+
if test_ant_properties.gsub!(/^tested.project.dir=.*$/, 'tested.project.dir=../')
|
44
|
+
File.open(test_ant_properties_file, 'w') { |f| f << test_ant_properties }
|
45
|
+
end
|
62
46
|
end
|
63
47
|
|
64
48
|
Dir.chdir File.join(root, 'test') do
|
@@ -83,15 +67,12 @@ module Ruboto
|
|
83
67
|
File.open("AndroidManifest.xml", 'w') { |f| test_manifest.document.write(f, 4) }
|
84
68
|
instrumentation_property = "test.runner=org.ruboto.test.InstrumentationTestRunner\n"
|
85
69
|
|
86
|
-
|
87
|
-
prop_file = %w{ant.properties build.properties}.find { |f| File.exists?(f) }
|
70
|
+
prop_file = 'ant.properties'
|
88
71
|
prop_lines = File.readlines(prop_file)
|
89
72
|
File.open(prop_file, 'a') { |f| f << instrumentation_property } unless prop_lines.include?(instrumentation_property)
|
90
|
-
# EMXIF
|
91
73
|
|
92
|
-
ant_setup_line = /^(\s*<\/project>)/
|
93
74
|
run_tests_override = <<-EOF
|
94
|
-
<!-- BEGIN added by
|
75
|
+
<!-- BEGIN added by Ruboto -->
|
95
76
|
|
96
77
|
<macrodef name="run-tests-helper">
|
97
78
|
<attribute name="emma.enabled" default="false"/>
|
@@ -132,12 +113,16 @@ module Ruboto
|
|
132
113
|
<target name="run-tests-quick" description="Runs tests with previously installed packages">
|
133
114
|
<run-tests-helper />
|
134
115
|
</target>
|
135
|
-
<!-- END added by
|
136
|
-
|
116
|
+
<!-- END added by Ruboto -->
|
137
117
|
EOF
|
138
118
|
ant_script = File.read('build.xml')
|
119
|
+
|
120
|
+
# FIXME(uwe): Remove when we stop support for updating from Ruboto 0.8.1 and older
|
139
121
|
ant_script.gsub!(/\s*<!-- BEGIN added by ruboto(?:-core)? -->.*?<!-- END added by ruboto(?:-core)? -->\s*/m, '')
|
140
|
-
|
122
|
+
# EMXIF
|
123
|
+
|
124
|
+
ant_script.gsub!(/\s*<!-- BEGIN added by Ruboto -->.*?<!-- END added by Ruboto -->\s*/m, '')
|
125
|
+
raise "Bad ANT script" unless ant_script.gsub!(/\s*(<\/project>)/, "\n\n#{run_tests_override}\n\n\\1")
|
141
126
|
File.open('build.xml', 'w') { |f| f << ant_script }
|
142
127
|
|
143
128
|
# FIXME(uwe): Remove when we stop supporting update from Ruboto < 0.5.3
|
@@ -189,7 +174,7 @@ module Ruboto
|
|
189
174
|
|
190
175
|
# FIXME(uwe): Try keeping the class count low to enable installation on Android 2.3 devices
|
191
176
|
# unless new_jruby_version =~ /^1.7.0/ && verify_target_sdk < 15
|
192
|
-
|
177
|
+
log_action("Copying dx.jar to libs") { copier.copy 'libs' }
|
193
178
|
# end
|
194
179
|
|
195
180
|
reconfigure_jruby_libs(new_jruby_version)
|
@@ -198,21 +183,21 @@ module Ruboto
|
|
198
183
|
true
|
199
184
|
end
|
200
185
|
|
201
|
-
def
|
202
|
-
jar_file = Dir.glob("libs/
|
186
|
+
def update_dx_jar(force=nil)
|
187
|
+
jar_file = Dir.glob("libs/dx.jar")[0]
|
203
188
|
|
204
|
-
# FIXME(uwe): Skip copying
|
205
|
-
|
189
|
+
# FIXME(uwe): Skip copying dx.jar to apps using RubotoCore when we include dx.jar in RubotoCore
|
190
|
+
return if !jar_file && !force
|
206
191
|
|
207
192
|
copier = AssetCopier.new Ruboto::ASSETS, File.expand_path(".")
|
208
|
-
# FIXME(uwe): Skip copying
|
209
|
-
|
193
|
+
# FIXME(uwe): Skip copying dx.jar to apps using RubotoCore when we include dx.jar in RubotoCore
|
194
|
+
log_action("Removing #{jar_file}") { File.delete jar_file } if jar_file
|
210
195
|
|
211
196
|
# FIXME(uwe): Try keeping the class count low to enable installation on Android 2.3 devices
|
212
|
-
# FIXME(uwe): Skip copying
|
213
|
-
#
|
214
|
-
|
215
|
-
#
|
197
|
+
# FIXME(uwe): Skip copying dx.jar to apps using RubotoCore when we include dx.jar in RubotoCore
|
198
|
+
#if verify_target_sdk < 15
|
199
|
+
# log_action("Copying dx.jar to libs") { copier.copy 'libs' }
|
200
|
+
#end
|
216
201
|
# EMXIF
|
217
202
|
end
|
218
203
|
|
@@ -275,7 +260,7 @@ module Ruboto
|
|
275
260
|
puts "Adding explicit super call in #{script_file}"
|
276
261
|
script_content = File.read(script_file)
|
277
262
|
script_content.gsub! /^(\s*)(def on_(?:create\(bundle\)|start|resume|pause|destroy)\n)/, "\\1\\2\\1 super\n"
|
278
|
-
File.open(script_file, 'w'){|of| of << script_content}
|
263
|
+
File.open(script_file, 'w') { |of| of << script_content }
|
279
264
|
end
|
280
265
|
# EMXIF
|
281
266
|
|
@@ -285,14 +270,14 @@ module Ruboto
|
|
285
270
|
generate_inheriting_file 'Class', subclass_name
|
286
271
|
generate_subclass_or_interface(:package => package, :template => 'InheritingClass', :class => class_name,
|
287
272
|
:name => subclass_name, :method_base => method_base, :force => force)
|
288
|
-
|
273
|
+
# FIXME(uwe): Remove when we stop updating from Ruboto 0.7.0 and older
|
289
274
|
elsif source_code =~ /^\s*package\s+(\S+?)\s*;.*public\s+class\s+(\S+?)\s+extends\s+(.*?)\s\{.*^\s*private Object\[\] callbackProcs = new Object\[\d+\];/m
|
290
275
|
package, subclass_name, class_name = $1, $2, $3
|
291
276
|
puts "Regenerating subclass #{package}.#{subclass_name}"
|
292
277
|
generate_inheriting_file 'Class', subclass_name
|
293
278
|
generate_subclass_or_interface(:package => package, :template => 'InheritingClass', :class => class_name,
|
294
279
|
:name => subclass_name, :method_base => 'on', :force => force)
|
295
|
-
|
280
|
+
# EMXIF
|
296
281
|
end
|
297
282
|
end
|
298
283
|
end
|
@@ -400,7 +385,8 @@ module Ruboto
|
|
400
385
|
if jruby_core_version >= '1.7.0'
|
401
386
|
excluded_core_packages = [
|
402
387
|
'META-INF', 'cext',
|
403
|
-
'com/headius',
|
388
|
+
# 'com/headius', included since we are trying to use DexClient
|
389
|
+
'com/headius/invokebinder',
|
404
390
|
'com/kenai/constantine', 'com/kenai/jffi', 'com/martiansoftware', 'ext', 'java',
|
405
391
|
'jline', 'jni',
|
406
392
|
'jnr/constants/platform/darwin', 'jnr/constants/platform/fake', 'jnr/constants/platform/freebsd',
|
@@ -468,7 +454,7 @@ module Ruboto
|
|
468
454
|
# FIXME(uwe): Add a Ruboto.yml config for this if it works
|
469
455
|
# Reduces the installation footprint, but also reduces performance and stack usage
|
470
456
|
# FIXME(uwe): Measure the performance change
|
471
|
-
if false && jruby_core_version =~ /^1.7.0/ && Dir.chdir('../..'){verify_target_sdk < 15}
|
457
|
+
if false && jruby_core_version =~ /^1.7.0/ && Dir.chdir('../..') { verify_target_sdk < 15 }
|
472
458
|
invokers = Dir['**/*${INVOKER$*,POPULATOR}.class']
|
473
459
|
log_action("Removing invokers & populators(#{invokers.size})") do
|
474
460
|
FileUtils.rm invokers
|
@@ -481,6 +467,10 @@ module Ruboto
|
|
481
467
|
# FileUtils.rm_rf dir
|
482
468
|
#end
|
483
469
|
|
470
|
+
# Add our proxy class factory
|
471
|
+
`javac -source 1.6 -target 1.6 -cp .:#{Ruboto::ASSETS}/libs/dx.jar:#{Dir["#{Ruboto::SdkVersions::ANDROID_HOME}/platforms/android-*/android.jar"][0]} -d . #{Ruboto::GEM_ROOT}/lib/*.java`
|
472
|
+
raise "Compile failed" unless $? == 0
|
473
|
+
|
484
474
|
`jar -cf ../#{jruby_core} .`
|
485
475
|
end
|
486
476
|
FileUtils.remove_dir "tmp", true
|
@@ -515,7 +505,7 @@ module Ruboto
|
|
515
505
|
else
|
516
506
|
lib_dirs = ['1.8', '1.9', 'shared']
|
517
507
|
end
|
518
|
-
#
|
508
|
+
# ODOT
|
519
509
|
|
520
510
|
lib_dirs.each do |ld|
|
521
511
|
excluded_stdlibs.each do |d|
|
data/lib/ruboto/version.rb
CHANGED
@@ -10,13 +10,14 @@ setup do |activity|
|
|
10
10
|
assert @text_view
|
11
11
|
end
|
12
12
|
|
13
|
-
# ANDROID: 10, PLATFORM: 0.4.7,
|
13
|
+
# ANDROID: 10, PLATFORM: 0.4.7, JRuby: 1.7.0.dev '28334966' expected, but got '28335067'
|
14
|
+
# ANDROID: 16, PLATFORM: 0.4.8.dev, JRuby: 1.7.0.preview2 '[29, 34, 47, 64]' expected, but got '[28, 33, 47, 64]'
|
14
15
|
|
15
16
|
test('stack depth') do |activity|
|
16
17
|
os_offset = {
|
17
18
|
13 => [1]*4,
|
18
19
|
15 => [0, 0, 1, 1],
|
19
|
-
16 => [1]
|
20
|
+
16 => [0, 0, 1, 1],
|
20
21
|
}[android.os.Build::VERSION::SDK_INT] || [0, 0, 0, 0]
|
21
22
|
if org.ruboto.JRubyAdapter.uses_platform_apk?
|
22
23
|
jruby_offset = {
|
@@ -27,6 +28,7 @@ test('stack depth') do |activity|
|
|
27
28
|
jruby_offset = {
|
28
29
|
'1.7.0.dev' => [1, 1, 1, 1],
|
29
30
|
'1.7.0.preview2' => [0, 0, -4, -4],
|
31
|
+
'1.7.0.rc1' => [0, 0, -4, -4],
|
30
32
|
}[org.jruby.runtime.Constants::VERSION] || [0, 0, 0, 0]
|
31
33
|
end
|
32
34
|
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}"
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'ruboto/activity'
|
2
|
+
require 'ruboto/widget'
|
3
|
+
|
4
|
+
ruboto_import_widgets :LinearLayout, :ListView, :TextView
|
5
|
+
|
6
|
+
class SubclassOfArrayAdapter < Java::AndroidWidget::ArrayAdapter
|
7
|
+
def get_view(position, convert_view, parent)
|
8
|
+
puts "IN get_view!!!"
|
9
|
+
@inflater ||= context.getSystemService(Context::LAYOUT_INFLATER_SERVICE)
|
10
|
+
row = convert_view ? convert_view : @inflater.inflate(mResource, nil)
|
11
|
+
row.findViewById(mFieldId).text = get_item(position)
|
12
|
+
row
|
13
|
+
rescue Exception
|
14
|
+
puts "Exception getting list item view: #$!"
|
15
|
+
puts $!.backtrace.join("\n")
|
16
|
+
convert_view
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class SubclassActivity
|
21
|
+
def on_create(bundle)
|
22
|
+
super
|
23
|
+
setTitle File.basename(__FILE__).chomp('_activity.rb').split('_').map { |s| "#{s[0..0].upcase}#{s[1..-1]}" }.join(' ')
|
24
|
+
|
25
|
+
adapter = SubclassOfArrayAdapter.new(self, android.R.layout.simple_list_item_1 , AndroidIds::text1, ['Record one', 'Record two'])
|
26
|
+
|
27
|
+
self.content_view =
|
28
|
+
linear_layout :orientation => LinearLayout::VERTICAL do
|
29
|
+
@text_view_margins = text_view :text => 'What hath Matz wrought?', :id => 42
|
30
|
+
@list_view = list_view :adapter => adapter, :id => 43
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/test/app_test_methods.rb
CHANGED
@@ -39,6 +39,10 @@ module AppTestMethods
|
|
39
39
|
def run_activity_tests(activity_dir)
|
40
40
|
Dir[File.expand_path("#{activity_dir}/*_test.rb", File.dirname(__FILE__))].each do |test_src|
|
41
41
|
snake_name = test_src.chomp('_test.rb')
|
42
|
+
|
43
|
+
# FIXME(uwe): Remove when we stop testing JRuby < 1.7.0.rc1
|
44
|
+
next if snake_name =~ /subclass/ && (RUBOTO_PLATFORM == 'CURRENT' || JRUBY_JARS_VERSION < Gem::Version.new('1.7.0.rc1'))
|
45
|
+
|
42
46
|
activity_name = File.basename(snake_name).split('_').map { |s| "#{s[0..0].upcase}#{s[1..-1]}" }.join
|
43
47
|
Dir.chdir APP_DIR do
|
44
48
|
system "#{RUBOTO_CMD} gen class Activity --name #{activity_name}"
|
@@ -21,6 +21,7 @@ test('stack depth') do |activity|
|
|
21
21
|
jruby_offset = {
|
22
22
|
'1.7.0.preview1' => [0, -1, -1, -1],
|
23
23
|
'1.7.0.preview2' => [0, -1, 0, 0],
|
24
|
+
'1.7.0.rc1' => [0, -1, 0, 0],
|
24
25
|
}[org.jruby.runtime.Constants::VERSION] || [0, 0, 0, 0]
|
25
26
|
end
|
26
27
|
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}"
|
@@ -27,6 +27,7 @@ test('stack depth') do |activity|
|
|
27
27
|
'1.7.0.dev' => [1, 0, 0, 0],
|
28
28
|
'1.7.0.preview1' => [0, -1, -1, -1],
|
29
29
|
'1.7.0.preview2' => [0, -1, -1, -1],
|
30
|
+
'1.7.0.rc1' => [0, -1, -1, -1],
|
30
31
|
}[org.jruby.runtime.Constants::VERSION] || [0, 0, 0, 0]
|
31
32
|
end
|
32
33
|
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}"
|
data/test/minimal_app_test.rb
CHANGED
@@ -13,12 +13,20 @@ if RubotoTest::RUBOTO_PLATFORM == 'STANDALONE'
|
|
13
13
|
cleanup_app
|
14
14
|
end
|
15
15
|
|
16
|
+
# APK was larger than 3.2MB: 3.3MB. JRuby: 1.6.7.2, ANDROID_TARGET: 10.
|
17
|
+
# 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
|
+
# APK was larger than 4.6MB: 4.9MB. JRuby: 1.7.0.preview2, ANDROID_TARGET: 15.
|
20
|
+
|
16
21
|
def test_minimal_apk_is_less_than_3_mb
|
17
22
|
apk_size = BigDecimal(File.size("#{APP_DIR}/bin/RubotoTestApp-debug.apk").to_s) / (1024 * 1024)
|
18
23
|
upper_limit = {
|
19
|
-
'1.6.7' => 3.
|
24
|
+
'1.6.7' => 3.5,
|
25
|
+
'1.6.7.2' => 3.5,
|
26
|
+
'1.6.8' => 3.5,
|
20
27
|
'1.7.0.preview1' => 4.6,
|
21
|
-
'1.7.0.preview2' => 4.
|
28
|
+
'1.7.0.preview2' => ANDROID_TARGET < 15 ? 4.7 : 4.9,
|
29
|
+
'1.7.0.rc1' => ANDROID_TARGET < 15 ? 4.7 : 4.9,
|
22
30
|
}[JRUBY_JARS_VERSION.to_s] || 3.2
|
23
31
|
lower_limit = upper_limit * 0.9
|
24
32
|
version_message ="JRuby: #{JRUBY_JARS_VERSION}, ANDROID_TARGET: #{ANDROID_TARGET}"
|