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