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