Jeff Hamilton | 22c803a | 2010-10-19 14:53:34 -0500 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2010 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License |
| 15 | */ |
| 16 | |
| 17 | package com.android.apps.tagcanon; |
| 18 | |
| 19 | import com.android.apps.tag.MockNdefMessages; |
| 20 | import com.google.common.base.Preconditions; |
| 21 | import com.google.common.primitives.Bytes; |
| 22 | |
| 23 | import android.app.ListActivity; |
| 24 | import android.content.Intent; |
| 25 | import android.content.res.Resources; |
| 26 | import android.graphics.Bitmap; |
| 27 | import android.graphics.drawable.BitmapDrawable; |
| 28 | import android.graphics.drawable.Drawable; |
| 29 | import android.nfc.NdefMessage; |
| 30 | import android.nfc.NdefRecord; |
Jeff Hamilton | 22c803a | 2010-10-19 14:53:34 -0500 | [diff] [blame] | 31 | import android.nfc.NfcAdapter; |
| 32 | import android.os.Bundle; |
| 33 | import android.view.View; |
| 34 | import android.widget.ArrayAdapter; |
| 35 | import android.widget.ListView; |
| 36 | |
| 37 | import java.io.ByteArrayOutputStream; |
| 38 | import java.io.IOException; |
| 39 | import java.nio.charset.Charset; |
Elliott Hughes | 5b1190b | 2013-06-28 16:29:47 -0700 | [diff] [blame] | 40 | import java.nio.charset.StandardCharsets; |
Jeff Hamilton | 22c803a | 2010-10-19 14:53:34 -0500 | [diff] [blame] | 41 | import java.util.Locale; |
| 42 | |
| 43 | /** |
| 44 | * A test activity that launches tags as if they had been scanned. |
| 45 | */ |
| 46 | public class TagCanon extends ListActivity { |
| 47 | static final String TAG = "TagCanon"; |
| 48 | static final byte[] UID = new byte[] { 0x05, 0x00, 0x03, 0x08 }; |
| 49 | |
| 50 | ArrayAdapter<TagDescription> mAdapter; |
| 51 | |
| 52 | public static NdefRecord newTextRecord(String text, Locale locale, boolean encodeInUtf8) { |
| 53 | Preconditions.checkNotNull(text); |
| 54 | Preconditions.checkNotNull(locale); |
| 55 | |
Elliott Hughes | 5b1190b | 2013-06-28 16:29:47 -0700 | [diff] [blame] | 56 | byte[] langBytes = locale.getLanguage().getBytes(StandardCharsets.US_ASCII); |
Jeff Hamilton | 22c803a | 2010-10-19 14:53:34 -0500 | [diff] [blame] | 57 | |
Elliott Hughes | 5b1190b | 2013-06-28 16:29:47 -0700 | [diff] [blame] | 58 | Charset utfEncoding = encodeInUtf8 ? StandardCharsets.UTF_8 : StandardCharsets.UTF_16; |
Jeff Hamilton | 22c803a | 2010-10-19 14:53:34 -0500 | [diff] [blame] | 59 | byte[] textBytes = text.getBytes(utfEncoding); |
| 60 | |
| 61 | int utfBit = encodeInUtf8 ? 0 : (1 << 7); |
| 62 | char status = (char) (utfBit + langBytes.length); |
| 63 | |
| 64 | byte[] data = Bytes.concat( |
| 65 | new byte[] { (byte) status }, |
| 66 | langBytes, |
| 67 | textBytes |
| 68 | ); |
| 69 | |
| 70 | return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data); |
| 71 | } |
| 72 | |
| 73 | public static NdefRecord newMimeRecord(String type, byte[] data) { |
| 74 | Preconditions.checkNotNull(type); |
| 75 | Preconditions.checkNotNull(data); |
| 76 | |
Elliott Hughes | 5b1190b | 2013-06-28 16:29:47 -0700 | [diff] [blame] | 77 | byte[] typeBytes = type.getBytes(StandardCharsets.US_ASCII); |
Jeff Hamilton | 22c803a | 2010-10-19 14:53:34 -0500 | [diff] [blame] | 78 | |
| 79 | return new NdefRecord(NdefRecord.TNF_MIME_MEDIA, typeBytes, new byte[0], data); |
| 80 | } |
| 81 | |
| 82 | final NdefMessage[] buildImageMessages() { |
| 83 | Resources res = getResources(); |
| 84 | Drawable drawable = res.getDrawable(R.drawable.ic_launcher_nfc); |
| 85 | Bitmap photo = ((BitmapDrawable) drawable).getBitmap(); |
| 86 | final int size = photo.getWidth() * photo.getHeight() * 4; |
| 87 | final ByteArrayOutputStream out = new ByteArrayOutputStream(size); |
| 88 | |
| 89 | try { |
| 90 | photo.compress(Bitmap.CompressFormat.PNG, 100, out); |
| 91 | out.flush(); |
| 92 | byte[] payload = out.toByteArray(); |
| 93 | out.close(); |
| 94 | |
| 95 | NdefRecord text = newTextRecord("There's an image below this text!", Locale.US, true); |
| 96 | NdefRecord image = newMimeRecord("image/png", payload); |
| 97 | NdefMessage[] msgs = new NdefMessage[] { |
| 98 | new NdefMessage(new NdefRecord[] { text, image }) }; |
| 99 | |
| 100 | return msgs; |
| 101 | } catch (IOException e) { |
| 102 | throw new RuntimeException("Failed to compress image", e); |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | static final class TagDescription { |
| 107 | public String title; |
Jeff Hamilton | 8714f95 | 2010-11-12 12:30:18 -0600 | [diff] [blame] | 108 | NdefMessage[] msgs; |
Jeff Hamilton | 22c803a | 2010-10-19 14:53:34 -0500 | [diff] [blame] | 109 | |
| 110 | public TagDescription(String title, byte[] bytes) { |
| 111 | this.title = title; |
| 112 | try { |
Jeff Hamilton | 8714f95 | 2010-11-12 12:30:18 -0600 | [diff] [blame] | 113 | msgs = new NdefMessage[] { new NdefMessage(bytes) }; |
Jeff Hamilton | 22c803a | 2010-10-19 14:53:34 -0500 | [diff] [blame] | 114 | } catch (Exception e) { |
| 115 | throw new RuntimeException("Failed to create tag description", e); |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | public TagDescription(String title, NdefMessage[] msgs) { |
| 120 | this.title = title; |
Jeff Hamilton | 8714f95 | 2010-11-12 12:30:18 -0600 | [diff] [blame] | 121 | this.msgs = msgs; |
Jeff Hamilton | 22c803a | 2010-10-19 14:53:34 -0500 | [diff] [blame] | 122 | } |
| 123 | |
| 124 | @Override |
| 125 | public String toString() { |
| 126 | return title; |
| 127 | } |
| 128 | } |
| 129 | |
| 130 | @Override |
| 131 | public void onCreate(Bundle savedState) { |
| 132 | super.onCreate(savedState); |
| 133 | ArrayAdapter<TagDescription> adapter = new ArrayAdapter<TagDescription>(this, |
| 134 | android.R.layout.simple_list_item_1, android.R.id.text1); |
| 135 | adapter.add(new TagDescription("Image", buildImageMessages())); |
| 136 | adapter.add(new TagDescription("Real NFC message", MockNdefMessages.REAL_NFC_MSG)); |
| 137 | adapter.add(new TagDescription("Call Google", MockNdefMessages.CALL_GOOGLE)); |
| 138 | adapter.add(new TagDescription("English text", MockNdefMessages.ENGLISH_PLAIN_TEXT)); |
| 139 | adapter.add(new TagDescription("Send text message", MockNdefMessages.SEND_TEXT_MESSAGE)); |
| 140 | adapter.add(new TagDescription("SmartPoster URL & text", MockNdefMessages.SMART_POSTER_URL_AND_TEXT)); |
| 141 | adapter.add(new TagDescription("SmartPoster URL", MockNdefMessages.SMART_POSTER_URL_NO_TEXT)); |
| 142 | adapter.add(new TagDescription("VCARD", MockNdefMessages.VCARD)); |
| 143 | adapter.add(new TagDescription("URI", MockNdefMessages.URI)); |
| 144 | setListAdapter(adapter); |
| 145 | mAdapter = adapter; |
| 146 | } |
| 147 | |
| 148 | @Override |
| 149 | public void onListItemClick(ListView l, View v, int position, long id) { |
| 150 | TagDescription description = mAdapter.getItem(position); |
Jeff Hamilton | a29dc1b | 2010-10-28 17:44:37 -0500 | [diff] [blame] | 151 | Intent intent = new Intent(NfcAdapter.ACTION_TAG_DISCOVERED); |
Jeff Hamilton | 8714f95 | 2010-11-12 12:30:18 -0600 | [diff] [blame] | 152 | intent.putExtra(NfcAdapter.EXTRA_NDEF_MESSAGES, description.msgs); |
Jeff Hamilton | 22c803a | 2010-10-19 14:53:34 -0500 | [diff] [blame] | 153 | startActivity(intent); |
| 154 | } |
| 155 | } |