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 }

 

posted @ 2015-09-05 23:01  f9q  阅读(799)  评论(0编辑  收藏  举报