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 package com.example.android.nfc.record; 17 18 import android.app.Activity; 19 import android.net.Uri; 20 import android.nfc.NdefRecord; 21 import android.view.LayoutInflater; 22 import android.view.View; 23 import android.view.ViewGroup; 24 import android.widget.TextView; 25 26 import com.google.common.base.Preconditions; 27 import com.google.common.collect.BiMap; 28 import com.google.common.collect.ImmutableBiMap; 29 import com.google.common.primitives.Bytes; 30 31 import com.example.android.nfc.R; 32 33 import java.nio.charset.Charset; 34 import java.util.Arrays; 35 36 /** 37 * A parsed record containing a Uri. 38 */ 39 public class UriRecord implements ParsedNdefRecord { 40 41 private static final String TAG = "UriRecord"; 42 43 public static final String RECORD_TYPE = "UriRecord"; 44 45 /** 46 * NFC Forum "URI Record Type Definition" 47 * 48 * This is a mapping of "URI Identifier Codes" to URI string prefixes, 49 * per section 3.2.2 of the NFC Forum URI Record Type Definition document. 50 */ 51 private static final BiMap<Byte, String> URI_PREFIX_MAP = ImmutableBiMap.<Byte, String>builder() 52 .put((byte) 0x00, "") 53 .put((byte) 0x01, "http://www.") 54 .put((byte) 0x02, "https://www.") 55 .put((byte) 0x03, "http://") 56 .put((byte) 0x04, "https://") 57 .put((byte) 0x05, "tel:") 58 .put((byte) 0x06, "mailto:") 59 .put((byte) 0x07, "ftp://anonymous:anonymous@") 60 .put((byte) 0x08, "ftp://ftp.") 61 .put((byte) 0x09, "ftps://") 62 .put((byte) 0x0A, "sftp://") 63 .put((byte) 0x0B, "smb://") 64 .put((byte) 0x0C, "nfs://") 65 .put((byte) 0x0D, "ftp://") 66 .put((byte) 0x0E, "dav://") 67 .put((byte) 0x0F, "news:") 68 .put((byte) 0x10, "telnet://") 69 .put((byte) 0x11, "imap:") 70 .put((byte) 0x12, "rtsp://") 71 .put((byte) 0x13, "urn:") 72 .put((byte) 0x14, "pop:") 73 .put((byte) 0x15, "sip:") 74 .put((byte) 0x16, "sips:") 75 .put((byte) 0x17, "tftp:") 76 .put((byte) 0x18, "btspp://") 77 .put((byte) 0x19, "btl2cap://") 78 .put((byte) 0x1A, "btgoep://") 79 .put((byte) 0x1B, "tcpobex://") 80 .put((byte) 0x1C, "irdaobex://") 81 .put((byte) 0x1D, "file://") 82 .put((byte) 0x1E, "urn:epc:id:") 83 .put((byte) 0x1F, "urn:epc:tag:") 84 .put((byte) 0x20, "urn:epc:pat:") 85 .put((byte) 0x21, "urn:epc:raw:") 86 .put((byte) 0x22, "urn:epc:") 87 .put((byte) 0x23, "urn:nfc:") 88 .build(); 89 90 private final Uri mUri; 91 UriRecord(Uri uri)92 private UriRecord(Uri uri) { 93 this.mUri = Preconditions.checkNotNull(uri); 94 } 95 getView(Activity activity, LayoutInflater inflater, ViewGroup parent, int offset)96 public View getView(Activity activity, LayoutInflater inflater, ViewGroup parent, int offset) { 97 TextView text = (TextView) inflater.inflate(R.layout.tag_text, parent, false); 98 text.setText(mUri.toString()); 99 return text; 100 } 101 getUri()102 public Uri getUri() { 103 return mUri; 104 } 105 106 /** 107 * Convert {@link android.nfc.NdefRecord} into a {@link android.net.Uri}. 108 * This will handle both TNF_WELL_KNOWN / RTD_URI and TNF_ABSOLUTE_URI. 109 * 110 * @throws IllegalArgumentException if the NdefRecord is not a record 111 * containing a URI. 112 */ parse(NdefRecord record)113 public static UriRecord parse(NdefRecord record) { 114 short tnf = record.getTnf(); 115 if (tnf == NdefRecord.TNF_WELL_KNOWN) { 116 return parseWellKnown(record); 117 } else if (tnf == NdefRecord.TNF_ABSOLUTE_URI) { 118 return parseAbsolute(record); 119 } 120 throw new IllegalArgumentException("Unknown TNF " + tnf); 121 } 122 123 /** Parse and absolute URI record */ parseAbsolute(NdefRecord record)124 private static UriRecord parseAbsolute(NdefRecord record) { 125 byte[] payload = record.getPayload(); 126 Uri uri = Uri.parse(new String(payload, Charset.forName("UTF-8"))); 127 return new UriRecord(uri); 128 } 129 130 /** Parse an well known URI record */ parseWellKnown(NdefRecord record)131 private static UriRecord parseWellKnown(NdefRecord record) { 132 Preconditions.checkArgument(Arrays.equals(record.getType(), NdefRecord.RTD_URI)); 133 byte[] payload = record.getPayload(); 134 /* 135 * payload[0] contains the URI Identifier Code, per the 136 * NFC Forum "URI Record Type Definition" section 3.2.2. 137 * 138 * payload[1]...payload[payload.length - 1] contains the rest of 139 * the URI. 140 */ 141 String prefix = URI_PREFIX_MAP.get(payload[0]); 142 byte[] fullUri = 143 Bytes.concat(prefix.getBytes(Charset.forName("UTF-8")), Arrays.copyOfRange(payload, 1, 144 payload.length)); 145 Uri uri = Uri.parse(new String(fullUri, Charset.forName("UTF-8"))); 146 return new UriRecord(uri); 147 } 148 isUri(NdefRecord record)149 public static boolean isUri(NdefRecord record) { 150 try { 151 parse(record); 152 return true; 153 } catch (IllegalArgumentException e) { 154 return false; 155 } 156 } 157 158 private static final byte[] EMPTY = new byte[0]; 159 } 160