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.
Files changed (41) hide show
  1. data/.document +5 -0
  2. data/.gitignore +23 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +7 -0
  5. data/Rakefile +60 -0
  6. data/TODO +92 -0
  7. data/VERSION +1 -0
  8. data/andparcel.gemspec +103 -0
  9. data/bin/parcel +161 -0
  10. data/lib/andparcel/base.rb +22 -0
  11. data/lib/andparcel/catalog.rb +75 -0
  12. data/lib/andparcel/fileref.rb +21 -0
  13. data/lib/andparcel/parcel.rb +533 -0
  14. data/lib/andparcel.rb +3 -0
  15. data/test/ParcelReceiver/AndroidManifest.xml +15 -0
  16. data/test/ParcelReceiver/build.properties +17 -0
  17. data/test/ParcelReceiver/build.xml +67 -0
  18. data/test/ParcelReceiver/default.properties +11 -0
  19. data/test/ParcelReceiver/local.properties +10 -0
  20. data/test/ParcelReceiver/res/layout/main.xml +13 -0
  21. data/test/ParcelReceiver/res/values/strings.xml +4 -0
  22. data/test/ParcelReceiver/src/com/commonsware/android/pr/ParcelReceiver.java +15 -0
  23. data/test/ParcelToPackage/AndroidManifest.xml +15 -0
  24. data/test/ParcelToPackage/build.properties +17 -0
  25. data/test/ParcelToPackage/build.xml +67 -0
  26. data/test/ParcelToPackage/default.properties +11 -0
  27. data/test/ParcelToPackage/docs/README +1 -0
  28. data/test/ParcelToPackage/docs/SomeOtherFile +0 -0
  29. data/test/ParcelToPackage/libs/one.jar +0 -0
  30. data/test/ParcelToPackage/libs/two.jar +0 -0
  31. data/test/ParcelToPackage/local.properties +10 -0
  32. data/test/ParcelToPackage/parcel.json +17 -0
  33. data/test/ParcelToPackage/res/layout/andParcel_test_row.xml +13 -0
  34. data/test/ParcelToPackage/res/values/strings.xml +4 -0
  35. data/test/ParcelToPackage/src/com/commonsware/android/p2pkg/ParcelToPackage.java +15 -0
  36. data/test/ParcelToPackage/tmp/andParcel-test_0.1.0.zip +0 -0
  37. data/test/test_init.rb +42 -0
  38. data/test/test_install.rb +170 -0
  39. data/test/test_package.rb +218 -0
  40. data/test/test_remove.rb +86 -0
  41. 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,3 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ Dir[File::join(File.dirname(__FILE__), 'andparcel', '**', '*.rb')].sort.each {|f| require f if !File.directory?(f) }
@@ -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,4 @@
1
+ <?xml version="1.0" encoding="utf-8"?>
2
+ <resources>
3
+ <string name="app_name">ParcelReceiver</string>
4
+ </resources>
@@ -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
+ }