TextRecord.java revision f34e4d5ec99fd7883bbfcdc0f644d9d6e4df6c97
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 17package com.android.apps.tag.record; 18 19import com.android.apps.tag.R; 20import com.google.common.annotations.VisibleForTesting; 21import com.google.common.base.Preconditions; 22import com.google.common.primitives.Bytes; 23 24import android.app.Activity; 25import android.nfc.NdefRecord; 26import android.view.LayoutInflater; 27import android.view.View; 28import android.view.ViewGroup; 29import android.widget.TextView; 30 31import java.io.UnsupportedEncodingException; 32import java.nio.charset.Charset; 33import java.util.Arrays; 34import java.util.Locale; 35 36/** 37 * An NFC Text Record 38 */ 39public class TextRecord implements ParsedNdefRecord { 40 41 /** ISO/IANA language code */ 42 private final String mLanguageCode; 43 private final String mText; 44 45 private TextRecord(String languageCode, String text) { 46 mLanguageCode = Preconditions.checkNotNull(languageCode); 47 mText = Preconditions.checkNotNull(text); 48 } 49 50 @Override 51 public View getView(Activity activity, LayoutInflater inflater, ViewGroup parent) { 52 TextView text = (TextView) inflater.inflate(R.layout.tag_text, parent, false); 53 text.setText(mText); 54 return text; 55 } 56 57 public String getText() { 58 return mText; 59 } 60 61 /** 62 * Returns the ISO/IANA language code associated with this text element. 63 * 64 * TODO: this should return a {@link java.util.Locale} 65 */ 66 @VisibleForTesting 67 public String getLanguageCode() { 68 return mLanguageCode; 69 } 70 71 // TODO: deal with text fields which span multiple NdefRecords 72 public static TextRecord parse(NdefRecord record) { 73 Preconditions.checkArgument(record.getTnf() == NdefRecord.TNF_WELL_KNOWN); 74 Preconditions.checkArgument(Arrays.equals(record.getType(), NdefRecord.RTD_TEXT)); 75 try { 76 77 byte[] payload = record.getPayload(); 78 79 /* 80 * payload[0] contains the "Status Byte Encodings" field, per 81 * the NFC Forum "Text Record Type Definition" section 3.2.1. 82 * 83 * bit7 is the Text Encoding Field. 84 * 85 * if (Bit_7 == 0): The text is encoded in UTF-8 86 * if (Bit_7 == 1): The text is encoded in UTF16 87 * 88 * Bit_6 is reserved for future use and must be set to zero. 89 * 90 * Bits 5 to 0 are the length of the IANA language code. 91 */ 92 93 String textEncoding = ((payload[0] & 0200) == 0) ? "UTF-8" : "UTF-16"; 94 int languageCodeLength = payload[0] & 0077; 95 96 String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII"); 97 String text = new String(payload, 98 languageCodeLength + 1, 99 payload.length - languageCodeLength - 1, 100 textEncoding); 101 return new TextRecord(languageCode, text); 102 103 } catch (UnsupportedEncodingException e) { 104 // should never happen unless we get a malformed tag. 105 throw new IllegalArgumentException(e); 106 } 107 } 108 109 public static boolean isText(NdefRecord record) { 110 try { 111 parse(record); 112 return true; 113 } catch (IllegalArgumentException e) { 114 return false; 115 } 116 } 117 118 @VisibleForTesting 119 public static NdefRecord newTextRecord(String text, Locale locale) { 120 return newTextRecord(text, locale, true); 121 } 122 123 public static NdefRecord newTextRecord(String text, Locale locale, boolean encodeInUtf8) { 124 Preconditions.checkNotNull(text); 125 Preconditions.checkNotNull(locale); 126 127 byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII")); 128 129 Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16"); 130 byte[] textBytes = text.getBytes(utfEncoding); 131 132 int utfBit = encodeInUtf8 ? 0 : (1 << 7); 133 char status = (char) (utfBit + langBytes.length); 134 135 byte[] data = Bytes.concat( 136 new byte[] { (byte) status }, 137 langBytes, 138 textBytes 139 ); 140 141 return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data); 142 } 143} 144