andparcel 0.1.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/.document +5 -0
- data/.gitignore +23 -0
- data/LICENSE +20 -0
- data/README.rdoc +7 -0
- data/Rakefile +60 -0
- data/TODO +92 -0
- data/VERSION +1 -0
- data/andparcel.gemspec +103 -0
- data/bin/parcel +161 -0
- data/lib/andparcel/base.rb +22 -0
- data/lib/andparcel/catalog.rb +75 -0
- data/lib/andparcel/fileref.rb +21 -0
- data/lib/andparcel/parcel.rb +533 -0
- data/lib/andparcel.rb +3 -0
- data/test/ParcelReceiver/AndroidManifest.xml +15 -0
- data/test/ParcelReceiver/build.properties +17 -0
- data/test/ParcelReceiver/build.xml +67 -0
- data/test/ParcelReceiver/default.properties +11 -0
- data/test/ParcelReceiver/local.properties +10 -0
- data/test/ParcelReceiver/res/layout/main.xml +13 -0
- data/test/ParcelReceiver/res/values/strings.xml +4 -0
- data/test/ParcelReceiver/src/com/commonsware/android/pr/ParcelReceiver.java +15 -0
- data/test/ParcelToPackage/AndroidManifest.xml +15 -0
- data/test/ParcelToPackage/build.properties +17 -0
- data/test/ParcelToPackage/build.xml +67 -0
- data/test/ParcelToPackage/default.properties +11 -0
- data/test/ParcelToPackage/docs/README +1 -0
- data/test/ParcelToPackage/docs/SomeOtherFile +0 -0
- data/test/ParcelToPackage/libs/one.jar +0 -0
- data/test/ParcelToPackage/libs/two.jar +0 -0
- data/test/ParcelToPackage/local.properties +10 -0
- data/test/ParcelToPackage/parcel.json +17 -0
- data/test/ParcelToPackage/res/layout/andParcel_test_row.xml +13 -0
- data/test/ParcelToPackage/res/values/strings.xml +4 -0
- data/test/ParcelToPackage/src/com/commonsware/android/p2pkg/ParcelToPackage.java +15 -0
- data/test/ParcelToPackage/tmp/andParcel-test_0.1.0.zip +0 -0
- data/test/test_init.rb +42 -0
- data/test/test_install.rb +170 -0
- data/test/test_package.rb +218 -0
- data/test/test_remove.rb +86 -0
- metadata +158 -0
@@ -0,0 +1,533 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require 'rubygems'
|
3
|
+
require 'zip/zip'
|
4
|
+
require 'zip/zipfilesystem'
|
5
|
+
require 'json'
|
6
|
+
require 'nokogiri'
|
7
|
+
require 'rio'
|
8
|
+
|
9
|
+
$WHITELIST=['attr', 'declare-styleable']
|
10
|
+
$COMPONENTS=['activity', 'service', 'receiver', 'provider']
|
11
|
+
|
12
|
+
module AndParcel
|
13
|
+
# Given a collection of directories or files, returns a
|
14
|
+
# list of files. Directories are expanded into all files
|
15
|
+
# found inside that directory (including any subdirectories).
|
16
|
+
# Attempts to ignore backup files (those ending in ~).
|
17
|
+
def self.glob(dirs_or_files, base)
|
18
|
+
files=[]
|
19
|
+
|
20
|
+
if dirs_or_files
|
21
|
+
dirs_or_files.each do |x|
|
22
|
+
if x.split('').last!='~'
|
23
|
+
path=base ? File.join(base, x) : x
|
24
|
+
if File.directory?(path)
|
25
|
+
files += FileRef[path]
|
26
|
+
else
|
27
|
+
files << FileRef.new(path, File.dirname(path))
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
files.delete_if {|fr| File.directory?(fr.local)}
|
33
|
+
end
|
34
|
+
|
35
|
+
files
|
36
|
+
end
|
37
|
+
|
38
|
+
class Parcel
|
39
|
+
def self.package(pkg_info, opts={})
|
40
|
+
AndParcel.init
|
41
|
+
|
42
|
+
if !opts[:project]
|
43
|
+
opts[:project]=File.dirname(pkg_info)
|
44
|
+
pkg_info=File.basename(pkg_info)
|
45
|
+
end
|
46
|
+
|
47
|
+
lint_opts=opts.dup
|
48
|
+
|
49
|
+
if LintRequest.new(lint_opts).lint(pkg_info)
|
50
|
+
PackageRequest.new(opts).package(pkg_info)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.install(parcel, opts={})
|
55
|
+
AndParcel.init
|
56
|
+
InstallRequest.new(opts).install(parcel)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.remove(parcel_name, opts={})
|
60
|
+
AndParcel.init
|
61
|
+
RemoveRequest.new(opts).remove(parcel_name)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.lint(pkg_info, opts={})
|
65
|
+
AndParcel.init
|
66
|
+
LintRequest.new(opts).lint(pkg_info)
|
67
|
+
end
|
68
|
+
|
69
|
+
def initialize(cat)
|
70
|
+
# todo
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
class ParcelSet
|
75
|
+
def initialize(root)
|
76
|
+
@root=root
|
77
|
+
@parcels=[]
|
78
|
+
end
|
79
|
+
|
80
|
+
def <<(parcel)
|
81
|
+
@parcels << Parcel.new(parcel)
|
82
|
+
end
|
83
|
+
|
84
|
+
def size
|
85
|
+
@parcels.size
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class PackageRequest
|
90
|
+
attr_reader :config, :tmps, :opts
|
91
|
+
|
92
|
+
def initialize(opts)
|
93
|
+
@opts=opts
|
94
|
+
@tmps=[]
|
95
|
+
end
|
96
|
+
|
97
|
+
def package(pkg_info)
|
98
|
+
@config=JSON.parse(open(File.join(opts[:project], pkg_info)) {|f| f.read})
|
99
|
+
@config['parcel-version']=AndParcel.version
|
100
|
+
|
101
|
+
dir=opts[:dir] || '.'
|
102
|
+
|
103
|
+
FileUtils.mkdir_p(dir) if !File.exists?(dir)
|
104
|
+
|
105
|
+
target=File.join(dir, config['name']+'_'+config['version']+'.zip')
|
106
|
+
|
107
|
+
File.delete(target) if File.exists?(target)
|
108
|
+
|
109
|
+
begin
|
110
|
+
Zip::ZipFile.open(target, Zip::ZipFile::CREATE) do |zf|
|
111
|
+
manifest(zf) if
|
112
|
+
resources(zf) if
|
113
|
+
docs(zf) if
|
114
|
+
libs(zf) if
|
115
|
+
save_config(zf)
|
116
|
+
end
|
117
|
+
|
118
|
+
target
|
119
|
+
rescue
|
120
|
+
File.delete(target) if target && File.exists?(target)
|
121
|
+
raise
|
122
|
+
ensure
|
123
|
+
tmps.each {|f| f.delete}
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
# Take the configuration hash, convert to JSON, and put it
|
128
|
+
# in the ZIP file as +config.json+.
|
129
|
+
def save_config(zf)
|
130
|
+
store_stream(zf, 'parcel.json', config.to_json)
|
131
|
+
|
132
|
+
true
|
133
|
+
end
|
134
|
+
|
135
|
+
# For each JAR to go into the ZIP file, add it
|
136
|
+
def libs(zf)
|
137
|
+
if opts[:jars]
|
138
|
+
files=AndParcel.glob(opts[:jars], opts[:project])
|
139
|
+
|
140
|
+
files.each do |fr|
|
141
|
+
zf.add(File.join('libs', File.basename(fr.local)), fr.local)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
true
|
146
|
+
end
|
147
|
+
|
148
|
+
# For each documentation file to go into the ZIP file, add it
|
149
|
+
def docs(zf)
|
150
|
+
if opts[:docs]
|
151
|
+
files=AndParcel.glob(opts[:docs], opts[:project])
|
152
|
+
|
153
|
+
files.each do |fr|
|
154
|
+
zf.add(File.join('docs', fr.relative), fr.local)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
true
|
159
|
+
end
|
160
|
+
|
161
|
+
# For each resource to go into the ZIP file, add it
|
162
|
+
def resources(zf)
|
163
|
+
if opts[:res]
|
164
|
+
files=AndParcel.glob(opts[:res], opts[:project])
|
165
|
+
|
166
|
+
files.each do |fr|
|
167
|
+
zf.add(File.join('res', fr.relative), fr.local)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
true
|
172
|
+
end
|
173
|
+
|
174
|
+
# Scan the manifest template and grab all children of
|
175
|
+
# the <application> element
|
176
|
+
def manifest(zf)
|
177
|
+
if opts[:manifest]
|
178
|
+
doc=Nokogiri::XML(open(File.join(opts[:project], opts[:manifest])))
|
179
|
+
out=Nokogiri::XML('<manifest-merge/>')
|
180
|
+
|
181
|
+
doc.search('application').children.each do |node|
|
182
|
+
if node.element?
|
183
|
+
out.root.add_child(node)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
store_stream(zf, 'ManifestMerge.xml', out.to_s)
|
188
|
+
end
|
189
|
+
|
190
|
+
true
|
191
|
+
end
|
192
|
+
|
193
|
+
# Helper method to take a hunk of text and a path and
|
194
|
+
# put in the ZIP file. The ZIP file gem being used does
|
195
|
+
# not appear to support putting in-memory text into
|
196
|
+
# arbitrary paths in the ZIP file. Hence, we write the
|
197
|
+
# text out to a temporary file, put that in the ZIP file,
|
198
|
+
# and make note to delete this temporary file sometime
|
199
|
+
# later.
|
200
|
+
def store_stream(zf, path, text)
|
201
|
+
tmp=Tempfile.new('parcel')
|
202
|
+
tmp.puts text
|
203
|
+
tmp.close
|
204
|
+
zf.add(path, tmp.path)
|
205
|
+
tmps << tmp
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
class InstallRequest
|
210
|
+
attr_reader :opts, :config, :root
|
211
|
+
|
212
|
+
def initialize(opts)
|
213
|
+
@opts=opts
|
214
|
+
@root=opts[:dir] || '.'
|
215
|
+
end
|
216
|
+
|
217
|
+
def install(target)
|
218
|
+
dir=File.join(@root, 'parcels')
|
219
|
+
|
220
|
+
FileUtils.mkdir_p(dir) if !File.exists?(dir)
|
221
|
+
|
222
|
+
if File.exists?(target)
|
223
|
+
dest=File.join(dir, File.basename(target))
|
224
|
+
FileUtils.cp target, dest
|
225
|
+
inject(dest)
|
226
|
+
elsif /(http|https):\/\/.+/.match(target)
|
227
|
+
install_from_url(target, dir)
|
228
|
+
else
|
229
|
+
url=AndParcel.catalogs.find(target)
|
230
|
+
|
231
|
+
if url
|
232
|
+
install_from_url(url, dir)
|
233
|
+
else
|
234
|
+
raise "Could not find parcel #{target}"
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
def install_from_url(target, dir)
|
240
|
+
rio_target=rio(target)
|
241
|
+
dest=File.join(dir,
|
242
|
+
rio_target.basename.to_s+rio_target.extname)
|
243
|
+
FileUtils.mkdir_p(File.dirname(dest))
|
244
|
+
rio(dest) < rio_target
|
245
|
+
inject(dest)
|
246
|
+
end
|
247
|
+
|
248
|
+
def inject(dest)
|
249
|
+
Zip::ZipFile.open(dest) do |zf|
|
250
|
+
begin
|
251
|
+
dependencies if
|
252
|
+
manifest(zf) if
|
253
|
+
resources(zf) if
|
254
|
+
docs(zf) if
|
255
|
+
libs(zf) if
|
256
|
+
load_config(zf)
|
257
|
+
|
258
|
+
FileUtils.mv dest, @parcel_root
|
259
|
+
ensure
|
260
|
+
File.unlink(dest) if File.exists?(dest)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
# Loads the configuration file for this parcel out of its
|
266
|
+
# ZIP archive.
|
267
|
+
def load_config(zf)
|
268
|
+
@config=JSON.parse(zf.read('parcel.json'))
|
269
|
+
@parcel_root=File.join(@root, 'parcels', @config['name'])
|
270
|
+
|
271
|
+
if File.exists?(@parcel_root)
|
272
|
+
if [opts[:replace]]
|
273
|
+
AndParcel::Parcel.remove(@config['name'], :dir=>opts[:dir])
|
274
|
+
else
|
275
|
+
raise "Parcel already installed: #{@config['name']}"
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
FileUtils.mkdir_p @parcel_root
|
280
|
+
|
281
|
+
true
|
282
|
+
end
|
283
|
+
|
284
|
+
# For each JAR in the parcel's +libs/+ directory, copy that
|
285
|
+
# JAR into the project's +libs/+ directory and note what we
|
286
|
+
# installed. We only need to track the files installed outside
|
287
|
+
# of the parcel-specific subdirectory in +parcels/+, as that
|
288
|
+
# whole directory can be removed on the corresponding
|
289
|
+
# +extract+ command.
|
290
|
+
def libs(zf)
|
291
|
+
zf.entries.each do |entry|
|
292
|
+
if ('libs/'==entry.parent_as_string)
|
293
|
+
dest=File.join(@root, 'libs', File.basename(entry.name))
|
294
|
+
FileUtils.mkdir_p File.dirname(dest)
|
295
|
+
File.unlink(dest) if File.exists?(dest)
|
296
|
+
entry.extract dest
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
true
|
301
|
+
end
|
302
|
+
|
303
|
+
# For each file in the parcel's +docs/+ directory, extract
|
304
|
+
# it into +parcel/.../docs/+, where +...+ is the ID of the
|
305
|
+
# parcel itself.
|
306
|
+
def docs(zf)
|
307
|
+
dir=File.join(@parcel_root, 'docs')
|
308
|
+
|
309
|
+
zf.entries.each do |entry|
|
310
|
+
if (/^docs\/(.+)$/.match entry.name)
|
311
|
+
dest=File.join(dir, $1)
|
312
|
+
FileUtils.mkdir_p File.dirname(dest)
|
313
|
+
File.unlink(dest) if File.exists?(dest)
|
314
|
+
entry.extract dest
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
true
|
319
|
+
end
|
320
|
+
|
321
|
+
# For each resource in the parcel's +res/+ directory, copy that
|
322
|
+
# resource into the project's +res/+ directory and note what we
|
323
|
+
# installed. We only need to track the files installed outside
|
324
|
+
# of the parcel-specific subdirectory in +parcels/+, as that
|
325
|
+
# whole directory can be removed on the corresponding
|
326
|
+
# +extract+ command.
|
327
|
+
def resources(zf)
|
328
|
+
dir=File.join(@root, 'res')
|
329
|
+
|
330
|
+
zf.entries.each do |entry|
|
331
|
+
if (/^res\/(.+)$/.match entry.name)
|
332
|
+
name=$1
|
333
|
+
dest=File.join(dir, File.dirname(name), File.basename(name))
|
334
|
+
FileUtils.mkdir_p File.dirname(dest)
|
335
|
+
File.unlink(dest) if File.exists?(dest)
|
336
|
+
entry.extract dest
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
true
|
341
|
+
end
|
342
|
+
|
343
|
+
# If the parcel has a +ManifestMerge.xml+ file, back up and
|
344
|
+
# then open the project's +AndroidManifest.xml+ file,
|
345
|
+
# and merge in anything with a distinct name.
|
346
|
+
def manifest(zf)
|
347
|
+
if zf.find_entry('ManifestMerge.xml')
|
348
|
+
dest=File.join(@root, 'AndroidManifest.xml')
|
349
|
+
|
350
|
+
if File.exists? dest
|
351
|
+
backup=dest+'~'
|
352
|
+
File.unlink backup if File.exists?(backup)
|
353
|
+
FileUtils.cp dest, backup
|
354
|
+
|
355
|
+
doc=Nokogiri::XML(open(dest))
|
356
|
+
app=doc.search('application')[0]
|
357
|
+
merge=Nokogiri::XML(zf.read('ManifestMerge.xml'))
|
358
|
+
|
359
|
+
merge.root.children.each do |node|
|
360
|
+
if node.element?
|
361
|
+
if $COMPONENTS.include?(node.name)
|
362
|
+
existing=app.xpath("*[@android:name='#{node['name']}']",
|
363
|
+
'android'=>"http://schemas.android.com/apk/res/android")
|
364
|
+
|
365
|
+
if existing.size==0
|
366
|
+
app.add_child(node)
|
367
|
+
end
|
368
|
+
else
|
369
|
+
# no support for other elements right now
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
open(dest, "w") {|f| f.puts doc.to_s }
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
true
|
379
|
+
end
|
380
|
+
|
381
|
+
# If there are parcels dependent upon this one, inject
|
382
|
+
# those as well.
|
383
|
+
def dependencies
|
384
|
+
(@config['dependencies'] || {}).each_pair do |dep, version|
|
385
|
+
AndParcel::Parcel.install(dep, opts)
|
386
|
+
end
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
class RemoveRequest
|
391
|
+
attr_reader :opts, :root
|
392
|
+
|
393
|
+
def initialize(opts)
|
394
|
+
@opts=opts
|
395
|
+
@root=opts[:dir] || '.'
|
396
|
+
end
|
397
|
+
|
398
|
+
def remove(parcel_name)
|
399
|
+
@parcel_root=File.join(root, 'parcels', parcel_name)
|
400
|
+
|
401
|
+
if File.exists?(@parcel_root)
|
402
|
+
dest=Dir[File.join(@parcel_root, '*.zip')][0]
|
403
|
+
|
404
|
+
if dest
|
405
|
+
Zip::ZipFile.open(dest) do |zf|
|
406
|
+
manifest(zf) if
|
407
|
+
resources(zf) if
|
408
|
+
libs(zf)
|
409
|
+
end
|
410
|
+
|
411
|
+
FileUtils.rm_rf @parcel_root
|
412
|
+
end
|
413
|
+
else
|
414
|
+
raise "Parcel not installed: #{parcel_name}"
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
def libs(zf)
|
419
|
+
zf.entries.each do |entry|
|
420
|
+
if ('libs/'==entry.parent_as_string)
|
421
|
+
dest=File.join(@root, 'libs', File.basename(entry.name))
|
422
|
+
File.unlink(dest) if File.exists?(dest)
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
true
|
427
|
+
end
|
428
|
+
|
429
|
+
def resources(zf)
|
430
|
+
dir=File.join(@root, 'res')
|
431
|
+
|
432
|
+
zf.entries.each do |entry|
|
433
|
+
if (/^res\/(.+)$/.match entry.name)
|
434
|
+
name=$1
|
435
|
+
dest=File.join(dir, File.dirname(name), File.basename(name))
|
436
|
+
File.unlink(dest) if File.exists?(dest)
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
true
|
441
|
+
end
|
442
|
+
|
443
|
+
def manifest(zf)
|
444
|
+
end
|
445
|
+
end
|
446
|
+
|
447
|
+
class LintRequest
|
448
|
+
attr_reader :opts, :out
|
449
|
+
|
450
|
+
def initialize(opts)
|
451
|
+
@opts=opts
|
452
|
+
end
|
453
|
+
|
454
|
+
def lint(pkg_info)
|
455
|
+
@out=opts[:out] || $stderr
|
456
|
+
path=File.join(opts[:project], pkg_info)
|
457
|
+
@config=JSON.parse(open(path) {|f| f.read})
|
458
|
+
@prefix=(@config['name'].gsub('.', '_').gsub('-','_'))+'_'
|
459
|
+
@prefix_regexp=Regexp.compile(@prefix+'.*')
|
460
|
+
@issues=0
|
461
|
+
|
462
|
+
resources=AndParcel.glob('res', opts[:project])
|
463
|
+
|
464
|
+
resources.each do |fr|
|
465
|
+
if fr.local.split('').last!='~'
|
466
|
+
if File.extname(fr.local)=='.xml'
|
467
|
+
doc=Nokogiri::XML(open(fr.local))
|
468
|
+
|
469
|
+
if (doc.root.name=='resources')
|
470
|
+
do_xml_resource(fr, doc)
|
471
|
+
else
|
472
|
+
do_simple_resource(fr)
|
473
|
+
end
|
474
|
+
else
|
475
|
+
do_simple_resource(fr)
|
476
|
+
end
|
477
|
+
end
|
478
|
+
end
|
479
|
+
|
480
|
+
if @issues>0
|
481
|
+
out.puts "#{@issues} issues reported #{'and fixed' if opts[:repair]}"
|
482
|
+
end
|
483
|
+
|
484
|
+
return(@issues==0)
|
485
|
+
end
|
486
|
+
|
487
|
+
# Confirm that a simple resource's name has the prefix, and
|
488
|
+
# repair it if requested. A simple resource is a resource
|
489
|
+
# whose name is the filename. Repairing it simply means
|
490
|
+
# renaming the file to one that has the desired prefix.
|
491
|
+
def do_simple_resource(fr)
|
492
|
+
if !(@prefix_regexp.match(File.basename(fr.local)))
|
493
|
+
out.puts "#{fr.local} does not have proper prefix: #{@prefix}"
|
494
|
+
@issues+=1
|
495
|
+
|
496
|
+
if opts[:repair]
|
497
|
+
rename=File.dirname(fr.local)+'/'+@prefix+File.basename(fr.local)
|
498
|
+
FileUtils.mv(fr.local, rename)
|
499
|
+
out.puts "...fixed!"
|
500
|
+
end
|
501
|
+
end
|
502
|
+
end
|
503
|
+
|
504
|
+
# Confirm that an "XML resource" has the prefix for all
|
505
|
+
# of its names. In this case, an "XML resource" refers to
|
506
|
+
# any XML file containing multiple actual resources,
|
507
|
+
# (e.g., res/values/strings.xml), as indicated by a
|
508
|
+
# <resources> root element. The rule is that each named
|
509
|
+
# child must have the prefix at the start of the name.
|
510
|
+
# Repairing this, if requested, involves modifying the XML
|
511
|
+
# file to adjust the name attributes.
|
512
|
+
def do_xml_resource(fr, doc)
|
513
|
+
dirty=false
|
514
|
+
|
515
|
+
doc.xpath('//@name').each do |node|
|
516
|
+
if (!$WHITELIST.include?(node.parent.name)) &&
|
517
|
+
!(@prefix_regexp.match(node.value))
|
518
|
+
out.puts "#{node.name}=\"#{node.value}\" in #{fr.local} does not have proper prefix: #{@prefix}"
|
519
|
+
@issues+=1
|
520
|
+
|
521
|
+
if opts[:repair]
|
522
|
+
node.value=@prefix+node.value
|
523
|
+
dirty=true
|
524
|
+
end
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
if dirty
|
529
|
+
open(fr.local, "w") {|f| f.puts doc.to_s }
|
530
|
+
end
|
531
|
+
end
|
532
|
+
end
|
533
|
+
end
|
data/lib/andparcel.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
3
|
+
package="com.commonsware.android.pr"
|
4
|
+
android:versionCode="1"
|
5
|
+
android:versionName="1.0">
|
6
|
+
<application android:label="@string/app_name">
|
7
|
+
<activity android:name="ParcelReceiver"
|
8
|
+
android:label="@string/app_name">
|
9
|
+
<intent-filter>
|
10
|
+
<action android:name="android.intent.action.MAIN" />
|
11
|
+
<category android:name="android.intent.category.LAUNCHER" />
|
12
|
+
</intent-filter>
|
13
|
+
</activity>
|
14
|
+
</application>
|
15
|
+
</manifest>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# This file is used to override default values used by the Ant build system.
|
2
|
+
#
|
3
|
+
# This file must be checked in Version Control Systems, as it is
|
4
|
+
# integral to the build system of your project.
|
5
|
+
|
6
|
+
# This file is only used by the Ant script.
|
7
|
+
|
8
|
+
# You can use this to override default values such as
|
9
|
+
# 'source.dir' for the location of your java source folder and
|
10
|
+
# 'out.dir' for the location of your output folder.
|
11
|
+
|
12
|
+
# You can also use it define how the release builds are signed by declaring
|
13
|
+
# the following properties:
|
14
|
+
# 'key.store' for the location of your keystore and
|
15
|
+
# 'key.alias' for the name of the key to use.
|
16
|
+
# The password will be asked during the build when you use the 'release' target.
|
17
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<project name="ParcelReceiver" default="help">
|
3
|
+
|
4
|
+
<!-- The local.properties file is created and updated by the 'android' tool.
|
5
|
+
It contains the path to the SDK. It should *NOT* be checked in in Version
|
6
|
+
Control Systems. -->
|
7
|
+
<property file="local.properties" />
|
8
|
+
|
9
|
+
<!-- The build.properties file can be created by you and is never touched
|
10
|
+
by the 'android' tool. This is the place to change some of the default property values
|
11
|
+
used by the Ant rules.
|
12
|
+
Here are some properties you may want to change/update:
|
13
|
+
|
14
|
+
application.package
|
15
|
+
the name of your application package as defined in the manifest. Used by the
|
16
|
+
'uninstall' rule.
|
17
|
+
source.dir
|
18
|
+
the name of the source directory. Default is 'src'.
|
19
|
+
out.dir
|
20
|
+
the name of the output directory. Default is 'bin'.
|
21
|
+
|
22
|
+
Properties related to the SDK location or the project target should be updated
|
23
|
+
using the 'android' tool with the 'update' action.
|
24
|
+
|
25
|
+
This file is an integral part of the build system for your application and
|
26
|
+
should be checked in in Version Control Systems.
|
27
|
+
|
28
|
+
-->
|
29
|
+
<property file="build.properties" />
|
30
|
+
|
31
|
+
<!-- The default.properties file is created and updated by the 'android' tool, as well
|
32
|
+
as ADT.
|
33
|
+
This file is an integral part of the build system for your application and
|
34
|
+
should be checked in in Version Control Systems. -->
|
35
|
+
<property file="default.properties" />
|
36
|
+
|
37
|
+
<!-- Custom Android task to deal with the project target, and import the proper rules.
|
38
|
+
This requires ant 1.6.0 or above. -->
|
39
|
+
<path id="android.antlibs">
|
40
|
+
<pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
|
41
|
+
<pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
|
42
|
+
<pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
|
43
|
+
<pathelement path="${sdk.dir}/tools/lib/apkbuilder.jar" />
|
44
|
+
<pathelement path="${sdk.dir}/tools/lib/jarutils.jar" />
|
45
|
+
</path>
|
46
|
+
|
47
|
+
<taskdef name="setup"
|
48
|
+
classname="com.android.ant.SetupTask"
|
49
|
+
classpathref="android.antlibs" />
|
50
|
+
|
51
|
+
<!-- Execute the Android Setup task that will setup some properties specific to the target,
|
52
|
+
and import the build rules files.
|
53
|
+
|
54
|
+
The rules file is imported from
|
55
|
+
<SDK>/platforms/<target_platform>/templates/android_rules.xml
|
56
|
+
|
57
|
+
To customize some build steps for your project:
|
58
|
+
- copy the content of the main node <project> from android_rules.xml
|
59
|
+
- paste it in this build.xml below the <setup /> task.
|
60
|
+
- disable the import by changing the setup task below to <setup import="false" />
|
61
|
+
|
62
|
+
This will ensure that the properties are setup correctly but that your customized
|
63
|
+
build steps are used.
|
64
|
+
-->
|
65
|
+
<setup />
|
66
|
+
|
67
|
+
</project>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# This file is automatically generated by Android Tools.
|
2
|
+
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
3
|
+
#
|
4
|
+
# This file must be checked in Version Control Systems.
|
5
|
+
#
|
6
|
+
# To customize properties used by the Ant build system use,
|
7
|
+
# "build.properties", and override values to adapt the script to your
|
8
|
+
# project structure.
|
9
|
+
|
10
|
+
# Project target.
|
11
|
+
target=android-4
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# This file is automatically generated by Android Tools.
|
2
|
+
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
3
|
+
#
|
4
|
+
# This file must *NOT* be checked in Version Control Systems,
|
5
|
+
# as it contains information specific to your local configuration.
|
6
|
+
|
7
|
+
# location of the SDK. This is only used by Ant
|
8
|
+
# For customization when using a Version Control System, please read the
|
9
|
+
# header note.
|
10
|
+
sdk.dir=/opt/android-sdk-linux_x86-1.6_r1
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
3
|
+
android:orientation="vertical"
|
4
|
+
android:layout_width="fill_parent"
|
5
|
+
android:layout_height="fill_parent"
|
6
|
+
>
|
7
|
+
<TextView
|
8
|
+
android:layout_width="fill_parent"
|
9
|
+
android:layout_height="wrap_content"
|
10
|
+
android:text="Hello World, ParcelReceiver"
|
11
|
+
/>
|
12
|
+
</LinearLayout>
|
13
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
package com.commonsware.android.pr;
|
2
|
+
|
3
|
+
import android.app.Activity;
|
4
|
+
import android.os.Bundle;
|
5
|
+
|
6
|
+
public class ParcelReceiver extends Activity
|
7
|
+
{
|
8
|
+
/** Called when the activity is first created. */
|
9
|
+
@Override
|
10
|
+
public void onCreate(Bundle savedInstanceState)
|
11
|
+
{
|
12
|
+
super.onCreate(savedInstanceState);
|
13
|
+
setContentView(R.layout.main);
|
14
|
+
}
|
15
|
+
}
|