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 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.dev'
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"}
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-z])",
43
+ "(?<=[A-Z])(?=[A-Z][a-z0-9])",
44
44
  "(?<=[^A-Z])(?=[A-Z])",
45
- "(?<=[A-Za-z])(?=[^A-Za-z])"
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
+ }
@@ -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
+ }
@@ -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
- update_dexmaker true unless params['with-jruby'].value
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
- update_dexmaker force
361
+ update_dx_jar force
362
362
  update_jruby force
363
363
  update_manifest nil, nil, force
364
364
  update_icons force
@@ -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
- # FIXME(uwe): Remove build.xml file to force regeneration.
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
- # FIXME(uwe): Remove build.xml file to force regeneration.
55
- # FIXME(uwe): Needed when updating apps from Android SDK <= 13 to 14
56
- FileUtils.rm_f "#{root}/test/build.xml"
57
- # EMXIF
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
- # FIXME(uwe): Cleanup when we stop supporting updating apps generated with Android SDK <= 13
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 ruboto -->
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 ruboto -->
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
- raise "Bad ANT script" unless ant_script.gsub!(ant_setup_line, "#{run_tests_override}\n\n\\1")
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
- log_action("Copying dexmaker.jar to libs") { copier.copy 'libs' }
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 update_dexmaker(force=nil)
202
- jar_file = Dir.glob("libs/dexmaker*.jar")[0]
186
+ def update_dx_jar(force=nil)
187
+ jar_file = Dir.glob("libs/dx.jar")[0]
203
188
 
204
- # FIXME(uwe): Skip copying dexmaker to apps using RubotoCore when we include dexmaker.jar in RubotoCore
205
- # return false if !jar_file && !force
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 dexmaker to apps using RubotoCore when we include dexmaker.jar in RubotoCore
209
- # log_action("Removing #{jar_file}") { File.delete *Dir.glob("libs/dexmaker*.jar") } if jar_file
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 dexmaker to apps using RubotoCore when we include dexmaker.jar in RubotoCore
213
- # if verify_target_sdk < 15
214
- log_action("Copying dexmaker.jar to libs") { copier.copy 'libs/dexmaker*.jar' }
215
- # end
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
- # FIXME(uwe): Remove when we stop updating from Ruboto 0.7.0 and older
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
- # EMXIF
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
- # TODO end
508
+ # ODOT
519
509
 
520
510
  lib_dirs.each do |ld|
521
511
  excluded_stdlibs.each do |d|
@@ -1,4 +1,4 @@
1
1
  module Ruboto
2
- VERSION = '0.8.1'
2
+ VERSION = '0.9.0.rc.0'
3
3
  UPDATE_VERSION_LIMIT = '0.5.2'
4
4
  end
@@ -10,13 +10,14 @@ setup do |activity|
10
10
  assert @text_view
11
11
  end
12
12
 
13
- # ANDROID: 10, PLATFORM: 0.4.7, JRuby: 1.7.0.dev '28334966' expected, but got '28335067'
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]*4,
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
@@ -1,4 +1,4 @@
1
- activity Java::org.ruboto.test_app.GenerateActivity
1
+ activity Java::org.ruboto.test_app.SubclassActivity
2
2
 
3
3
  setup do |activity|
4
4
  start = Time.now
@@ -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}"
@@ -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.2,
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.6,
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}"