NFC(12)使用Android Beam技术传输文本数据及它是什么
Android Beam技术是什么
Android Beam的基本理念就是两部(只能是1对1,不可像蓝牙那样1对多)NFC设备靠近时(一般是背靠背),通过触摸一部NFC设备的屏幕,将数据推向另外一部NFC设备。在传递数据的过程中,两部NFC设备不能离得太远,否则NFC连接将中断。
使用Android Beam技术传输文本数据
目前2015-09-05在android支持的nfc设备上,只要我们提供数据类型就可,不用手动像socket那样手动write(data),由系统完成,
Android SDK提供了如下两个用于传递消息的方法
NfcAdapter.setNdefPushMessage
public void setNdefPushMessage(NdefMessage message, Activity activity, Activity ... activities);
NfcAdapter.setNdefPushMessageCallback ,这是一个回调,直到需要传输数据时才准备数据.
public void setNdefPushMessageCallback(CreateNdefMessageCallback callback, Activity activity, Activity ... activities); public NdefMessage createNdefMessage(NfcEvent event)
使用Android Beam技术传输文本示例
1 import java.nio.charset.Charset; 2 import java.util.Locale; 3 4 import android.app.Activity; 5 import android.app.PendingIntent; 6 import android.content.Intent; 7 import android.nfc.NdefMessage; 8 import android.nfc.NdefRecord; 9 import android.nfc.NfcAdapter; 10 import android.nfc.NfcAdapter.CreateNdefMessageCallback; 11 import android.nfc.NfcAdapter.OnNdefPushCompleteCallback; 12 import android.nfc.NfcEvent; 13 import android.os.Bundle; 14 import android.os.Parcelable; 15 import android.util.Log; 16 import android.widget.EditText; 17 import android.widget.Toast; 18 /* 19 * 两个nfc设备通信示例 20 * 本例中使用第2种方法传递数据,NfcAdapter.setNdefPushMessageCallback 21 */ 22 public class AndroidBeamMainActivity extends Activity 23 implements CreateNdefMessageCallback //传输数据的方法 24 , OnNdefPushCompleteCallback {//OnNdefPushCompleteCallback是传输完毕的事件回调 25 26 private EditText mBeamText; 27 28 private NfcAdapter mNfcAdapter; 29 private PendingIntent mPendingIntent; 30 31 @Override 32 public void onCreate(Bundle savedInstanceState) { 33 super.onCreate(savedInstanceState); 34 35 setContentView(R.layout.activity_android_beam); 36 mBeamText = (EditText) findViewById(R.id.edittext_beam_text); 37 38 //设置当前aty为处理nfc的应用,注意aty为singleTop 39 mNfcAdapter = mNfcAdapter.getDefaultAdapter(this); 40 mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,getClass()), 0); 41 42 //数据传输函数回调 43 mNfcAdapter.setNdefPushMessageCallback(this, this); 44 //传输完毕回调 45 mNfcAdapter.setOnNdefPushCompleteCallback(this, this); 46 47 } 48 /* 49 * from OnNdefPushCompleteCallback 50 * 数据传输完毕的回调. 51 */ 52 @Override 53 public void onNdefPushComplete(NfcEvent event) { 54 Log.d("message", "complete"); 55 } 56 57 /* 58 * 这是CreateNdefMessageCallback的回调, 59 * 创建一个NdefMessage.这里是把EditText中内容封装成NdefMessage 60 * NdefMessage中record的类型可以自己随意,如text,uri,application 61 * 62 */ 63 @Override 64 public NdefMessage createNdefMessage(NfcEvent event) { 65 String text = mBeamText.getText().toString().trim(); 66 if ("".equals(text)) 67 text = "默认文本"; 68 69 /* 70 * 创建一个ApplicationRecord类型的record 71 * 启动计算器. 72 */ 73 /*NdefMessage ndefMessage = new NdefMessage( 74 new NdefRecord[] { NdefRecord.createApplicationRecord("com.android.calculator2") });*/ 75 76 /* 77 * 根据txt创建一个NdefRecord,并把它放入到NdefMessage中. 78 */ 79 NdefMessage ndefMessage = new NdefMessage(new NdefRecord[]{createTextRecord(text)}); 80 81 return ndefMessage; 82 } 83 84 /* 85 *注册当前aty为nfc处理功能 86 */ 87 @Override 88 public void onResume() { 89 super.onResume(); 90 if (mNfcAdapter != null) 91 mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, 92 null); 93 94 } 95 /* 96 *注销当前aty处理nfc的功能 97 */ 98 @Override 99 public void onPause() { 100 super.onPause(); 101 if (mNfcAdapter != null) 102 mNfcAdapter.disableForegroundDispatch(this); 103 } 104 105 @Override 106 public void onNewIntent(Intent intent) { 107 /* 108 * 当本aty启动时,有另个nfc设备通过beam与本机配对并传来数据时, 109 * 本函数接收数据,并用toast提示出来. 110 * 如果要aty未启动,那么系统调用默认的处理程序. 111 */ 112 processIntent(intent); 113 } 114 115 /* 116 * 根据文本创建一个NdefRecord, 117 * 注意ndef文本格式规范 118 * 1,这些数据的第1个字节描述了数据的状态, 119 * 2,然后若干个字节描述文本的语言编码, 120 * 3,最后剩余字节表示文本数据。 121 */ 122 public NdefRecord createTextRecord(String text) { 123 //语言编码 124 byte[] langBytes = Locale.CHINA.getLanguage().getBytes(Charset.forName("US-ASCII")); 125 126 //设置text的字符编码为utf8 127 Charset utfEncoding = Charset.forName("UTF-8"); 128 byte[] textBytes = text.getBytes(utfEncoding); 129 int utfBit = 0; 130 char status = (char) (utfBit + langBytes.length); 131 //申请空间 132 byte[] data = new byte[1 + langBytes.length + textBytes.length]; 133 //第1字节是状态码 134 data[0] = (byte) status; 135 System.arraycopy(langBytes, 0, data, 1, langBytes.length); 136 System.arraycopy(textBytes, 0, data, 1 + langBytes.length,textBytes.length); 137 NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,NdefRecord.RTD_TEXT, new byte[0], data); 138 139 return record; 140 } 141 142 void processIntent(Intent intent) { 143 144 Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); 145 146 NdefMessage msg = (NdefMessage) rawMsgs[0]; 147 String text = TextRecord.parse(msg.getRecords()[0]).getText(); 148 Toast.makeText(this, text, Toast.LENGTH_LONG).show(); 149 } 150 }
解析文本的类
1 import java.io.UnsupportedEncodingException; 2 import java.util.Arrays; 3 import android.nfc.NdefRecord; 4 5 public class TextRecord { 6 private final String mText; 7 8 private TextRecord(String text) { 9 10 mText = text; 11 } 12 13 public String getText() { 14 return mText; 15 } 16 17 public static TextRecord parse(NdefRecord record) { 18 19 if (record.getTnf() != NdefRecord.TNF_WELL_KNOWN) 20 return null; 21 if (!Arrays.equals(record.getType(), NdefRecord.RTD_TEXT)) 22 return null; 23 24 try { 25 byte[] payload = record.getPayload(); 26 /* 27 * payload[0] contains the "Status Byte Encodings" field, per the 28 * NFC Forum "Text Record Type Definition" section 3.2.1. 29 * 30 * bit7 is the Text Encoding Field. 31 * 32 * if (Bit_7 == 0): The text is encoded in UTF-8 if (Bit_7 == 1): 33 * The text is encoded in UTF16 34 * 35 * Bit_6 is reserved for future use and must be set to zero. 36 * 37 * Bits 5 to 0 are the length of the IANA language code. 38 */ 39 String textEncoding = ((payload[0] & 0x80) == 0) ? "UTF-8" 40 : "UTF-16"; 41 int languageCodeLength = payload[0] & 0x3f; 42 String languageCode = new String(payload, 1, languageCodeLength,"US-ASCII"); 43 String text = new String(payload, languageCodeLength + 1, 44 payload.length - languageCodeLength - 1, textEncoding); 45 return new TextRecord(text); 46 } catch (UnsupportedEncodingException e) { 47 // should never happen unless we get a malformed tag. 48 throw new IllegalArgumentException(e); 49 } 50 } 51 }