ruboto 0.8.1 → 0.9.0.rc.0
Sign up to get free protection for your applications and to get access to all the features.
- 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}"
|