ruboto 0.5.4 → 0.6.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/Gemfile.lock +9 -9
- data/README.md +2 -0
- data/Rakefile +71 -7
- data/assets/Rakefile +2 -407
- data/assets/libs/dexmaker20120305.jar +0 -0
- data/assets/rakelib/ruboto.rake +428 -0
- data/assets/samples/sample_broadcast_receiver.rb +7 -3
- data/assets/samples/sample_broadcast_receiver_test.rb +47 -1
- data/assets/src/RubotoActivity.java +6 -2
- data/assets/src/org/ruboto/EntryPointActivity.java +2 -2
- data/assets/src/org/ruboto/Script.java +91 -24
- data/assets/src/org/ruboto/test/ActivityTest.java +27 -24
- data/assets/src/org/ruboto/test/InstrumentationTestRunner.java +42 -8
- data/assets/src/ruboto/activity.rb +1 -1
- data/assets/src/ruboto/base.rb +17 -6
- data/assets/src/ruboto/generate.rb +458 -0
- data/assets/src/ruboto/legacy.rb +9 -12
- data/assets/src/ruboto/widget.rb +9 -1
- data/lib/java_class_gen/android_api.xml +1 -1
- data/lib/ruboto.rb +1 -2
- data/lib/ruboto/commands/base.rb +19 -4
- data/lib/ruboto/sdk_versions.rb +12 -0
- data/lib/ruboto/util/build.rb +10 -11
- data/lib/ruboto/util/update.rb +150 -51
- data/lib/ruboto/util/verify.rb +6 -4
- data/lib/ruboto/util/xml_element.rb +2 -2
- data/lib/ruboto/version.rb +1 -1
- data/test/activity/option_menu_activity.rb +5 -1
- data/test/activity/psych_activity.rb +11 -6
- data/test/activity/stack_activity_test.rb +13 -5
- data/test/app_test_methods.rb +4 -3
- data/test/broadcast_receiver_test.rb +86 -0
- data/test/minimal_app_test.rb +27 -19
- data/test/rake_test.rb +13 -2
- data/test/ruboto_gen_test.rb +17 -3
- data/test/ruboto_update_test.rb +24 -2
- data/test/service_test.rb +1 -1
- data/test/test_helper.rb +134 -62
- data/test/update_test_methods.rb +40 -14
- data/test/updated_example_test_methods.rb +41 -0
- metadata +12 -6
data/assets/src/ruboto/base.rb
CHANGED
@@ -76,13 +76,24 @@ end
|
|
76
76
|
# Import a class and set it up for handlers
|
77
77
|
#
|
78
78
|
|
79
|
-
def ruboto_import(
|
80
|
-
|
81
|
-
|
79
|
+
def ruboto_import(*package_classes)
|
80
|
+
already_classes = package_classes.select{|i| not i.is_a?(String) and not i.is_a?(Symbol)}
|
81
|
+
imported_classes = package_classes - already_classes
|
82
82
|
|
83
|
-
|
84
|
-
|
85
|
-
|
83
|
+
unless imported_classes.empty?
|
84
|
+
# TODO(uwe): The first part of this "if" is only needed for JRuby 1.6.x. Simplify when we stop supporting JRuby 1.6.x
|
85
|
+
if imported_classes.size == 1
|
86
|
+
imported_classes = [*(java_import(*imported_classes) || eval("Java::#{imported_classes[0]}"))]
|
87
|
+
else
|
88
|
+
imported_classes = java_import(imported_classes)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
(already_classes + imported_classes).each do |package_class|
|
93
|
+
package_class.class_eval do
|
94
|
+
extend Ruboto::CallbackClass
|
95
|
+
include Ruboto::Callbacks
|
96
|
+
end
|
86
97
|
end
|
87
98
|
end
|
88
99
|
|
@@ -0,0 +1,458 @@
|
|
1
|
+
######################################################
|
2
|
+
#
|
3
|
+
# generate.rb (by Scott Moyer)
|
4
|
+
#
|
5
|
+
# Uses the dexmaker project
|
6
|
+
# (http://code.google.com/p/dexmaker/)
|
7
|
+
# to generate Ruboto callbacks.
|
8
|
+
#
|
9
|
+
######################################################
|
10
|
+
|
11
|
+
require 'ruboto/base'
|
12
|
+
require 'fileutils'
|
13
|
+
|
14
|
+
######################################################
|
15
|
+
#
|
16
|
+
# Expand the functionality of TypeId
|
17
|
+
#
|
18
|
+
|
19
|
+
java_import 'com.google.dexmaker.TypeId'
|
20
|
+
class TypeId
|
21
|
+
@@convert_hash = {
|
22
|
+
nil => VOID,
|
23
|
+
"java.lang.String" => STRING,
|
24
|
+
"java.lang.Object" => OBJECT
|
25
|
+
}
|
26
|
+
|
27
|
+
@@corresponding_class = {
|
28
|
+
INT => get("Ljava/lang/Integer;"),
|
29
|
+
FLOAT => get("Ljava/lang/Float;"),
|
30
|
+
DOUBLE => get("Ljava/lang/Double;"),
|
31
|
+
BYTE => get("Ljava/lang/Byte;"),
|
32
|
+
BOOLEAN => get("Ljava/lang/Boolean;"),
|
33
|
+
CHAR => get("Ljava/lang/Char;"),
|
34
|
+
SHORT => get("Ljava/lang/Short;"),
|
35
|
+
LONG => get("Ljava/lang/Long;")
|
36
|
+
}
|
37
|
+
|
38
|
+
@@conversion_method = {}
|
39
|
+
|
40
|
+
%w(int float double byte boolean char short long).each do |i|
|
41
|
+
@@convert_hash[i] = const_get(i.upcase)
|
42
|
+
@@conversion_method[const_get(i.upcase)] = "#{i}Value"
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.convert_type(type)
|
46
|
+
# TODO: Handling arrays
|
47
|
+
rv = @@convert_hash[type]
|
48
|
+
unless rv
|
49
|
+
rv = type.split("[")
|
50
|
+
rv[-1] = "L#{rv[-1].gsub('.', '/')};" unless rv[-1].length == 1
|
51
|
+
rv = get(rv.join("["))
|
52
|
+
end
|
53
|
+
rv
|
54
|
+
end
|
55
|
+
|
56
|
+
def corresponding_class
|
57
|
+
@@corresponding_class[self]
|
58
|
+
end
|
59
|
+
|
60
|
+
def conversion_method
|
61
|
+
@@conversion_method[self]
|
62
|
+
end
|
63
|
+
|
64
|
+
def primitive?
|
65
|
+
@@corresponding_class.key? self
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
######################################################
|
70
|
+
#
|
71
|
+
# Helper methods for class generation
|
72
|
+
#
|
73
|
+
|
74
|
+
java_import 'com.google.dexmaker.Code'
|
75
|
+
class Code
|
76
|
+
def call_super(class_id, method_name, return_value, *parameters)
|
77
|
+
method_id = class_id.getMethod(return_value ? return_value.type : TypeId::VOID,
|
78
|
+
method_name, *(parameters.map{|i| i.type}))
|
79
|
+
invokeSuper(method_id, return_value, getThis(class_id), *parameters)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def create_constructor(dex_maker, super_class, class_id, *parameters)
|
84
|
+
constructor_id = class_id.getConstructor(*parameters)
|
85
|
+
dex_maker.declare(constructor_id, java.lang.reflect.Modifier::PUBLIC).instance_eval do
|
86
|
+
parameter_array = []
|
87
|
+
parameters.each_with_index{|param, i| parameter_array << getParameter(i, param)}
|
88
|
+
|
89
|
+
invokeDirect(super_class.getConstructor(*parameters), nil, getThis(class_id), *parameter_array)
|
90
|
+
returnVoid
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
######################################################
|
95
|
+
#
|
96
|
+
# Generate a new classes for an interface or class
|
97
|
+
# Takes a hash
|
98
|
+
# :use_cache (default true) or regenerate
|
99
|
+
# :reload (default false) or use existing constant
|
100
|
+
# :dex_file - where to put the generated jar
|
101
|
+
# -- for single classes default to use package as path
|
102
|
+
# -- for multiple classes default to classes.jar
|
103
|
+
# The remaining key/value pairs represent source => new_class
|
104
|
+
# -- source is either a string or the actual class/interface
|
105
|
+
# -- new_class is a string "package.class"
|
106
|
+
#
|
107
|
+
|
108
|
+
def ruboto_generate(options)
|
109
|
+
use_cache = options.key?(:use_cache) ? options.delete(:use_cache) : true
|
110
|
+
reload = options.key?(:reload) ? options.delete(:reload) : false
|
111
|
+
dex_file = options.delete(:dex_file)
|
112
|
+
|
113
|
+
#
|
114
|
+
# Already loaded? Just check the first one.
|
115
|
+
#
|
116
|
+
|
117
|
+
class_name = options.values[0].split('.')[-1]
|
118
|
+
return Object.const_get(class_name) if Object.const_defined?(class_name) and not reload
|
119
|
+
|
120
|
+
#
|
121
|
+
# Set up directory
|
122
|
+
#
|
123
|
+
|
124
|
+
base_dir = "#{$activity.files_dir.absolute_path}/dx"
|
125
|
+
if dex_file
|
126
|
+
components = dex_file.split('/')
|
127
|
+
components.unshift(base_dir) unless components[0] == ""
|
128
|
+
dex_dir = components[0..-2].join('/')
|
129
|
+
dex_file = components[-1]
|
130
|
+
elsif options.size == 1
|
131
|
+
dex_dir = "#{base_dir}/#{options.values[0].split('.')[0..-2].join('/')}"
|
132
|
+
dex_file = "#{options.values[0].split('.')[-1]}.jar"
|
133
|
+
else
|
134
|
+
dex_dir = base_dir
|
135
|
+
dex_file = "classes.jar"
|
136
|
+
end
|
137
|
+
FileUtils.mkpath dex_dir unless File.exists?(dex_dir)
|
138
|
+
jar_file = java.io.File.new("#{dex_dir}/#{dex_file}")
|
139
|
+
puts "Exists: #{jar_file}" if File.exists?(jar_file.to_s)
|
140
|
+
|
141
|
+
#
|
142
|
+
# Already generated?
|
143
|
+
#
|
144
|
+
|
145
|
+
if use_cache
|
146
|
+
rv = ruboto_load_class(jar_file.path, *options.values)
|
147
|
+
return rv if rv
|
148
|
+
end
|
149
|
+
|
150
|
+
if File.exists? jar_file.path
|
151
|
+
File.delete jar_file.path
|
152
|
+
File.delete jar_file.path.gsub(/\.jar$/, ".dex")
|
153
|
+
end
|
154
|
+
|
155
|
+
puts "Generating: #{jar_file.path}"
|
156
|
+
|
157
|
+
dex_maker = com.google.dexmaker.DexMaker.new
|
158
|
+
options.each{|k, v| ruboto_generate_class(dex_maker, k, v)}
|
159
|
+
|
160
|
+
#
|
161
|
+
# Generate and save
|
162
|
+
#
|
163
|
+
|
164
|
+
dex = dex_maker.generate
|
165
|
+
jar_file.createNewFile
|
166
|
+
jarOut = java.util.jar.JarOutputStream.new(java.io.FileOutputStream.new(jar_file))
|
167
|
+
jarOut.putNextEntry(java.util.jar.JarEntry.new("classes.dex"))
|
168
|
+
jarOut.write(dex)
|
169
|
+
jarOut.closeEntry
|
170
|
+
jarOut.close
|
171
|
+
|
172
|
+
return ruboto_load_class(jar_file.path, *options.values)
|
173
|
+
end
|
174
|
+
|
175
|
+
######################################################
|
176
|
+
#
|
177
|
+
# Open a dex jar and load the class(es)
|
178
|
+
#
|
179
|
+
|
180
|
+
def ruboto_load_class(file_name, *package_class_names)
|
181
|
+
return nil unless File.exists? file_name
|
182
|
+
|
183
|
+
loader = Java::dalvik.system.DexClassLoader.new(file_name, file_name.split('/')[0..-2].join('/'), nil,
|
184
|
+
com.google.dexmaker.DexMaker.java_class.class_loader)
|
185
|
+
|
186
|
+
runtime = org.jruby.Ruby.getGlobalRuntime
|
187
|
+
|
188
|
+
rv = []
|
189
|
+
package_class_names.each do |i|
|
190
|
+
tmp = org.jruby.javasupport.Java.getProxyClass(runtime,
|
191
|
+
org.jruby.javasupport.JavaClass.get(runtime, loader.loadClass(i)))
|
192
|
+
Object.const_set(i.split('.')[-1], tmp)
|
193
|
+
ruboto_import tmp
|
194
|
+
rv << tmp
|
195
|
+
end
|
196
|
+
|
197
|
+
rv.length == 1 ? rv[0] : rv
|
198
|
+
end
|
199
|
+
|
200
|
+
######################################################
|
201
|
+
#
|
202
|
+
# Does the hard work of generating one class
|
203
|
+
#
|
204
|
+
|
205
|
+
def ruboto_generate_class(dex_maker, interface_or_class_name, package_class_name)
|
206
|
+
#
|
207
|
+
# Basic set up
|
208
|
+
#
|
209
|
+
|
210
|
+
if interface_or_class_name.is_a?(String)
|
211
|
+
interface_or_class = eval("Java::#{interface_or_class_name.gsub('$', '::')}")
|
212
|
+
else
|
213
|
+
interface_or_class = interface_or_class_name
|
214
|
+
interface_or_class_name = interface_or_class.java_class.name
|
215
|
+
end
|
216
|
+
interface_or_class_id = TypeId.convert_type(interface_or_class_name)
|
217
|
+
interface = interface_or_class.java_class.interface?
|
218
|
+
class_type_id = TypeId.convert_type(package_class_name)
|
219
|
+
parameters = [class_type_id, "#{package_class_name.split('.')[-1]}.generated", java.lang.reflect.Modifier::PUBLIC,
|
220
|
+
interface ? TypeId::OBJECT : interface_or_class_id]
|
221
|
+
parameters << TypeId.convert_type(interface_or_class_name) if interface
|
222
|
+
dex_maker.declare(*parameters)
|
223
|
+
|
224
|
+
#
|
225
|
+
# Create callbacks field
|
226
|
+
#
|
227
|
+
|
228
|
+
callbackProcs_field = class_type_id.getField(TypeId.get("[Ljava/lang/Object;"), "callbackProcs")
|
229
|
+
dex_maker.declare(callbackProcs_field, java.lang.reflect.Modifier::PRIVATE, nil)
|
230
|
+
|
231
|
+
#
|
232
|
+
# Build constructor and create callbacks array
|
233
|
+
#
|
234
|
+
|
235
|
+
if interface
|
236
|
+
create_constructor dex_maker, TypeId::OBJECT, class_type_id
|
237
|
+
else
|
238
|
+
interface_or_class.java_class.constructors.each do |c|
|
239
|
+
parameter_type_array = c.parameter_types.map{|p| TypeId.convert_type(p.name)}
|
240
|
+
create_constructor dex_maker, interface_or_class_id, class_type_id, *parameter_type_array
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
#
|
245
|
+
# Build a list of methods
|
246
|
+
#
|
247
|
+
|
248
|
+
methods = []
|
249
|
+
if interface
|
250
|
+
methods = interface_or_class.java_class.declared_instance_methods
|
251
|
+
else
|
252
|
+
method_hash, klass = {}, interface_or_class
|
253
|
+
while klass != nil
|
254
|
+
klass.java_class.declared_instance_methods.each do |i|
|
255
|
+
if (i.name[0..1] == "on" or (i.modifiers & java.lang.reflect.Modifier::ABSTRACT) != 0) and
|
256
|
+
(i.modifiers & java.lang.reflect.Modifier::FINAL) == 0 and not method_hash[i.name]
|
257
|
+
method_hash[i.name] = i
|
258
|
+
methods << i
|
259
|
+
end
|
260
|
+
end
|
261
|
+
klass = klass == java.lang.Object ? nil : klass.superclass
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
#
|
266
|
+
# Build setCallbackProc method
|
267
|
+
#
|
268
|
+
|
269
|
+
method_id = class_type_id.getMethod(TypeId::VOID, "setCallbackProc", TypeId::INT, TypeId::OBJECT)
|
270
|
+
dex_maker.declare(method_id, java.lang.reflect.Modifier::PUBLIC).instance_eval do
|
271
|
+
index = getParameter(0, TypeId::INT)
|
272
|
+
block = getParameter(1, TypeId::OBJECT)
|
273
|
+
array = newLocal(TypeId.get("[Ljava/lang/Object;"))
|
274
|
+
size = newLocal(TypeId::INT)
|
275
|
+
null = newLocal(TypeId::OBJECT)
|
276
|
+
|
277
|
+
array_exists = com.google.dexmaker.Label.new
|
278
|
+
|
279
|
+
# Does the calback proc array exist yet?
|
280
|
+
iget(callbackProcs_field, array, getThis(class_type_id))
|
281
|
+
loadConstant(null, nil)
|
282
|
+
compare(com.google.dexmaker.Comparison::NE, array_exists, array, null)
|
283
|
+
|
284
|
+
# Create the array the first time
|
285
|
+
loadConstant(size, methods.length)
|
286
|
+
newArray(array, size)
|
287
|
+
iput(callbackProcs_field, getThis(class_type_id), array)
|
288
|
+
|
289
|
+
mark(array_exists)
|
290
|
+
aput(array, index, block)
|
291
|
+
|
292
|
+
returnVoid
|
293
|
+
end
|
294
|
+
|
295
|
+
#
|
296
|
+
# Loop through and build a constant and method for each method in the interface
|
297
|
+
#
|
298
|
+
|
299
|
+
methods.each_with_index do |m, count|
|
300
|
+
# Define the constant
|
301
|
+
constant_name = "CB_" + m.name.gsub(/[A-Z]/, '_\0').upcase.gsub(/^ON_/, "")
|
302
|
+
const = class_type_id.getField(TypeId::INT, constant_name)
|
303
|
+
dex_maker.declare(const,
|
304
|
+
java.lang.reflect.Modifier::PUBLIC | java.lang.reflect.Modifier::STATIC | java.lang.reflect.Modifier::FINAL,
|
305
|
+
count.to_java(:int))
|
306
|
+
|
307
|
+
# Build the method
|
308
|
+
parameter_type_array = m.parameter_types.map{|j| TypeId.convert_type(j.name)}
|
309
|
+
method_id = class_type_id.getMethod(TypeId.convert_type(m.return_type ? m.return_type.name : nil), m.name, *parameter_type_array)
|
310
|
+
dex_maker.declare(method_id, java.lang.reflect.Modifier::PUBLIC).instance_eval do
|
311
|
+
parameter_array = []
|
312
|
+
parameter_type_array.each_with_index{|j, k| parameter_array << getParameter(k, j)}
|
313
|
+
|
314
|
+
# Callback procs array
|
315
|
+
index = newLocal(TypeId::INT)
|
316
|
+
array = newLocal(TypeId.get("[Ljava/lang/Object;"))
|
317
|
+
block = newLocal(TypeId::OBJECT)
|
318
|
+
|
319
|
+
if parameter_array.length > 1
|
320
|
+
# Call arguments array
|
321
|
+
p_arr = newLocal(TypeId.get("[Ljava/lang/Object;"))
|
322
|
+
p_size = newLocal(TypeId::INT)
|
323
|
+
p_index = newLocal(TypeId::INT)
|
324
|
+
end
|
325
|
+
|
326
|
+
# Holds nil for comparison
|
327
|
+
null = newLocal(TypeId::OBJECT)
|
328
|
+
|
329
|
+
# Holds method name
|
330
|
+
call_string = newLocal(TypeId::STRING)
|
331
|
+
|
332
|
+
# Locals for possible return
|
333
|
+
ret = retObject = nil
|
334
|
+
if m.return_type
|
335
|
+
ret = newLocal(TypeId.get(m.return_type))
|
336
|
+
retObject = newLocal(TypeId::OBJECT)
|
337
|
+
retClass = newLocal(TypeId.convert_type("java.lang.Class"))
|
338
|
+
end
|
339
|
+
|
340
|
+
# Create a local to help convert primitives
|
341
|
+
tmp_locals = {}
|
342
|
+
parameter_type_array.each do |p|
|
343
|
+
tmp_locals[p] = newLocal(p.corresponding_class) if p.primitive?
|
344
|
+
end
|
345
|
+
tmp_locals[ret.type] = newLocal(ret.type.corresponding_class) if ret and ret.type.primitive? and tmp_locals[ret.type] == nil
|
346
|
+
|
347
|
+
no_block = com.google.dexmaker.Label.new
|
348
|
+
done = com.google.dexmaker.Label.new
|
349
|
+
|
350
|
+
# Does the calback proc array exist yet?
|
351
|
+
iget(callbackProcs_field, array, getThis(class_type_id))
|
352
|
+
loadConstant(null, nil)
|
353
|
+
compare(com.google.dexmaker.Comparison::EQ, no_block, array, null)
|
354
|
+
|
355
|
+
# Do we have a callback proc?
|
356
|
+
loadConstant(index, count)
|
357
|
+
aget(block, array, index)
|
358
|
+
compare(com.google.dexmaker.Comparison::EQ, no_block, block, null)
|
359
|
+
|
360
|
+
call_super(class_type_id, m.name, ret, *parameter_array) unless interface
|
361
|
+
|
362
|
+
# Prepare to call Script to call the method
|
363
|
+
script_class_type_id = TypeId.convert_type("org.ruboto.Script")
|
364
|
+
loadConstant(call_string, "call")
|
365
|
+
parameter_types = [ret ? TypeId::OBJECT : TypeId::VOID, "callMethod", TypeId::OBJECT, TypeId::STRING]
|
366
|
+
method_parameters = [retObject, block, call_string]
|
367
|
+
|
368
|
+
# Set up for different arity
|
369
|
+
if parameter_array.length == 1
|
370
|
+
parameter_types << TypeId::OBJECT
|
371
|
+
# Cast ?
|
372
|
+
p = parameter_array[0]
|
373
|
+
# Need to convert primitives to add to array
|
374
|
+
if p.type.primitive?
|
375
|
+
newInstance(tmp_locals[p.type], p.type.corresponding_class.getConstructor(p.type), p)
|
376
|
+
method_parameters << tmp_locals[p.type]
|
377
|
+
else
|
378
|
+
method_parameters << p
|
379
|
+
end
|
380
|
+
elsif parameter_array.length > 1
|
381
|
+
# Create and populate an array for method parameters
|
382
|
+
loadConstant(p_size, parameter_type_array.length.to_java(:int))
|
383
|
+
newArray(p_arr, p_size)
|
384
|
+
parameter_array.each_with_index do |p, i|
|
385
|
+
loadConstant(p_index, i)
|
386
|
+
|
387
|
+
# Need to convert primitives to add to array
|
388
|
+
if p.type.primitive?
|
389
|
+
newInstance(tmp_locals[p.type], p.type.corresponding_class.getConstructor(p.type), p)
|
390
|
+
aput(p_arr, p_index, tmp_locals[p.type])
|
391
|
+
else
|
392
|
+
aput(p_arr, p_index, p)
|
393
|
+
end
|
394
|
+
end
|
395
|
+
|
396
|
+
parameter_types << TypeId.get("[Ljava/lang/Object;")
|
397
|
+
method_parameters << p_arr
|
398
|
+
end
|
399
|
+
|
400
|
+
# Add return class to the call
|
401
|
+
if ret
|
402
|
+
parameter_types << TypeId.convert_type("java.lang.Class")
|
403
|
+
loadConstant(retClass, java.lang.Boolean.java_class)
|
404
|
+
method_parameters << retClass
|
405
|
+
end
|
406
|
+
|
407
|
+
# Make the call
|
408
|
+
method_parameters = [script_class_type_id.getMethod(*parameter_types)] + method_parameters
|
409
|
+
invokeStatic(*method_parameters)
|
410
|
+
|
411
|
+
# Cast the return
|
412
|
+
if ret and ret.type.primitive?
|
413
|
+
cast(tmp_locals[ret.type], retObject)
|
414
|
+
invokeVirtual(tmp_locals[ret.type].type.getMethod(ret.type, ret.type.conversion_method), ret, tmp_locals[ret.type])
|
415
|
+
elsif ret
|
416
|
+
# May need to just copy if type is OBJECT
|
417
|
+
cast(ret, retObject)
|
418
|
+
end
|
419
|
+
|
420
|
+
jump(done)
|
421
|
+
mark(no_block)
|
422
|
+
|
423
|
+
call_super(class_type_id, m.name, ret, *parameter_array) unless interface
|
424
|
+
|
425
|
+
mark(done)
|
426
|
+
ret ? returnValue(ret) : returnVoid
|
427
|
+
end
|
428
|
+
end
|
429
|
+
end
|
430
|
+
|
431
|
+
######################################################
|
432
|
+
#
|
433
|
+
# Clear all generated dex jars
|
434
|
+
#
|
435
|
+
|
436
|
+
def ruboto_clear_dex_cache
|
437
|
+
FileUtils.remove_dir "#{$activity.files_dir.absolute_path}/dx"
|
438
|
+
end
|
439
|
+
|
440
|
+
######################################################
|
441
|
+
#
|
442
|
+
# Generate classes and configure any widgets
|
443
|
+
#
|
444
|
+
|
445
|
+
def ruboto_generate_widget(options)
|
446
|
+
ruboto_generate_widgets(options)
|
447
|
+
end
|
448
|
+
|
449
|
+
def ruboto_generate_widgets(options)
|
450
|
+
rv = ruboto_generate(options)
|
451
|
+
if rv.is_a?(Array)
|
452
|
+
rv.each{|i| ruboto_import_widget i if i < android.view.View}
|
453
|
+
else
|
454
|
+
ruboto_import_widget rv
|
455
|
+
end
|
456
|
+
rv
|
457
|
+
end
|
458
|
+
|