Create the tag canon. It fires tags.
Jeff Hamilton [Tue, 19 Oct 2010 19:53:34 +0000 (14:53 -0500)]
Change-Id: I52a256a2f71e797c9a7f3d26cdd9388f21427474

canon/Android.mk [new file with mode: 0644]
canon/AndroidManifest.xml [new file with mode: 0644]
canon/res/drawable-hdpi/ic_launcher_nfc.png [new file with mode: 0644]
canon/res/drawable-mdpi/ic_launcher_nfc.png [new file with mode: 0644]
canon/src/com/android/apps/tagcanon/TagCanon.java [new file with mode: 0644]

diff --git a/canon/Android.mk b/canon/Android.mk
new file mode 100644 (file)
index 0000000..ea15614
--- /dev/null
@@ -0,0 +1,13 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files) \
+    ../tests/src/com/android/apps/tag/MockNdefMessages.java \
+
+LOCAL_STATIC_JAVA_LIBRARIES := guava
+
+LOCAL_PACKAGE_NAME := TagCanon
+
+LOCAL_MODULE_TAGS := tests
+
+include $(BUILD_PACKAGE)
diff --git a/canon/AndroidManifest.xml b/canon/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..2b7bcab
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.android.apps.tagcanon">
+
+    <application>
+        <activity android:name="TagCanon"
+            android:label="Tag Canon"
+        >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN"/>
+                <category android:name="android.intent.category.LAUNCHER"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/canon/res/drawable-hdpi/ic_launcher_nfc.png b/canon/res/drawable-hdpi/ic_launcher_nfc.png
new file mode 100644 (file)
index 0000000..9b076ab
Binary files /dev/null and b/canon/res/drawable-hdpi/ic_launcher_nfc.png differ
diff --git a/canon/res/drawable-mdpi/ic_launcher_nfc.png b/canon/res/drawable-mdpi/ic_launcher_nfc.png
new file mode 100644 (file)
index 0000000..525f5b5
Binary files /dev/null and b/canon/res/drawable-mdpi/ic_launcher_nfc.png differ
diff --git a/canon/src/com/android/apps/tagcanon/TagCanon.java b/canon/src/com/android/apps/tagcanon/TagCanon.java
new file mode 100644 (file)
index 0000000..a636dbe
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.apps.tagcanon;
+
+import com.android.apps.tag.MockNdefMessages;
+import com.google.common.base.Preconditions;
+import com.google.common.primitives.Bytes;
+
+import android.app.ListActivity;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.nfc.NdefMessage;
+import android.nfc.NdefRecord;
+import android.nfc.NdefTag;
+import android.nfc.NfcAdapter;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.charset.Charsets;
+import java.util.Locale;
+
+/**
+ * A test activity that launches tags as if they had been scanned.
+ */
+public class TagCanon extends ListActivity {
+    static final String TAG = "TagCanon";
+    static final byte[] UID = new byte[] { 0x05, 0x00, 0x03, 0x08 };
+
+    ArrayAdapter<TagDescription> mAdapter;
+
+    public static NdefRecord newTextRecord(String text, Locale locale, boolean encodeInUtf8) {
+        Preconditions.checkNotNull(text);
+        Preconditions.checkNotNull(locale);
+
+        byte[] langBytes = locale.getLanguage().getBytes(Charsets.US_ASCII);
+
+        Charset utfEncoding = encodeInUtf8 ? Charsets.UTF_8 : Charset.forName("UTF-16");
+        byte[] textBytes = text.getBytes(utfEncoding);
+
+        int utfBit = encodeInUtf8 ? 0 : (1 << 7);
+        char status = (char) (utfBit + langBytes.length);
+
+        byte[] data = Bytes.concat(
+           new byte[] { (byte) status },
+           langBytes,
+           textBytes
+        );
+
+        return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data);
+    }
+
+    public static NdefRecord newMimeRecord(String type, byte[] data) {
+        Preconditions.checkNotNull(type);
+        Preconditions.checkNotNull(data);
+
+        byte[] typeBytes = type.getBytes(Charsets.US_ASCII);
+
+        return new NdefRecord(NdefRecord.TNF_MIME_MEDIA, typeBytes, new byte[0], data);
+    }
+
+    final NdefMessage[] buildImageMessages() {
+        Resources res = getResources();
+        Drawable drawable = res.getDrawable(R.drawable.ic_launcher_nfc);
+        Bitmap photo = ((BitmapDrawable) drawable).getBitmap();
+        final int size = photo.getWidth() * photo.getHeight() * 4;
+        final ByteArrayOutputStream out = new ByteArrayOutputStream(size);
+
+        try {
+            photo.compress(Bitmap.CompressFormat.PNG, 100, out);
+            out.flush();
+            byte[] payload = out.toByteArray();
+            out.close();
+
+            NdefRecord text = newTextRecord("There's an image below this text!", Locale.US, true);
+            NdefRecord image = newMimeRecord("image/png", payload);
+            NdefMessage[] msgs = new NdefMessage[] { 
+                    new NdefMessage(new NdefRecord[] { text, image }) };
+
+            return msgs;
+        } catch (IOException e) {
+            throw new RuntimeException("Failed to compress image", e);
+        }
+    }
+
+    static final class TagDescription {
+        public String title;
+        public NdefTag tag;
+
+        public TagDescription(String title, byte[] bytes) {
+            this.title = title;
+            try {
+                NdefMessage[] msgs = new NdefMessage[] { new NdefMessage(bytes) };
+                this.tag = new NdefTag(NdefTag.TARGET_TYPE_4, UID, 0, msgs);
+            } catch (Exception e) {
+                throw new RuntimeException("Failed to create tag description", e);
+            }
+        }
+
+        public TagDescription(String title, NdefMessage[] msgs) {
+            this.title = title;
+            try {
+                this.tag = new NdefTag(NdefTag.TARGET_TYPE_4, UID, 0, msgs);
+            } catch (Exception e) {
+                throw new RuntimeException("Failed to create tag description", e);
+            }
+        }
+
+        @Override
+        public String toString() {
+            return title;
+        }
+    }
+
+    @Override
+    public void onCreate(Bundle savedState) {
+        super.onCreate(savedState);
+        ArrayAdapter<TagDescription> adapter = new ArrayAdapter<TagDescription>(this,
+                android.R.layout.simple_list_item_1, android.R.id.text1);
+        adapter.add(new TagDescription("Image", buildImageMessages()));
+        adapter.add(new TagDescription("Real NFC message", MockNdefMessages.REAL_NFC_MSG));
+        adapter.add(new TagDescription("Call Google", MockNdefMessages.CALL_GOOGLE));
+        adapter.add(new TagDescription("English text", MockNdefMessages.ENGLISH_PLAIN_TEXT));
+        adapter.add(new TagDescription("Send text message", MockNdefMessages.SEND_TEXT_MESSAGE));
+        adapter.add(new TagDescription("SmartPoster URL & text", MockNdefMessages.SMART_POSTER_URL_AND_TEXT));
+        adapter.add(new TagDescription("SmartPoster URL", MockNdefMessages.SMART_POSTER_URL_NO_TEXT));
+        adapter.add(new TagDescription("VCARD", MockNdefMessages.VCARD));
+        adapter.add(new TagDescription("URI", MockNdefMessages.URI));
+        setListAdapter(adapter);
+        mAdapter = adapter;
+    }
+
+    @Override
+    public void onListItemClick(ListView l, View v, int position, long id) {
+        TagDescription description = mAdapter.getItem(position);
+        Intent intent = new Intent(NfcAdapter.ACTION_NDEF_TAG_DISCOVERED);
+        intent.putExtra(NfcAdapter.EXTRA_TAG, description.tag);
+        startActivity(intent);
+    }
+}