Android NFC的相關資源,需求和設置
你可以在Android的NFC支援頁面找到相關的API文檔和NFC的示例代碼:
HTTP://developer.android.com/reference/android/nfc/package-summary.html
接下來該怎麼做呢?通常需要硬體的支援(手機支援NFC)和添加你的應用的許可權。
這需要你修改你的AndroidManifest.xml檔,將最低的SDK版本更改為10,也就是Android2.3.3及以上版本:
[mw_shl_code=xhtml,true]<uses-sdk android:minSdkVersion="10"/>[/mw_shl_code]
還有就是你的手機需要支援NFC,應用必須獲取與硬體交互的許可權:
[mw_shl_code=xhtml,true]<uses-feature android:name="android.hardware.nfc" android:required="true"/>
< uses-permission android:name="android.permission.NFC"/>[/mw_shl_code]
你也可以通過定義Intent來對NFC掃描獲取的資料進行過濾處理。這裡僅僅是使用ACTION_NDEF_DISCOVERED處理字元資料。當然也有其他的NFC規格的資料類型的定義。
[mw_shl_code=xhtml,true]<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain"/>
< /intent-filter>[/mw_shl_code]
NFC資料交換格式
NdefMessage包含傳輸在NDEF中的資料,每個NdefMessage由定義在NdefRecord的多個記錄組成。每個NdefRecord根據它指明的3-bit的TNF進行解釋。查看完整的TNF清單及其映射,最常用的TNF是TNF_WELL_KNOWN 和 TNF_MIME_MEDIA。標籤調度系統通過三個Intent處理解包的NFC資料(通過Intent傳遞資料)。根據優先順序的先後,它們是ACTION_NDEF_DISCOVERED,ACTION_TECH_DISCOVERED,和ACTION_TAG_DISCOVERED。
這裡是官方的描述:「只要可能,盡可能的使用NDEF消息和ACTION_NDEF_DISCOVERED,因為三個Intent中最詳細的。這個Intent可以比其他兩個Intent在更加合適的時間啟動你的應用,給使用者更好的體驗」。
在Android中讀取NFC標籤和貼紙
<ignore_js_op>
正如我們在前一節提到,NdefMessage 是交換NFC資料最常用的方式。當然,你仍然可以定義你自己的non-NDEF 資料,但是這超出了本教程的範圍。為了說明資料是如何被標籤調度系統解析和處理的,我們僅在我們的實例中使用簡單的純文字。對於其他類型,看一下官方網站。
NfcAdapter用來監測設備對NFC的支援。前臺調度系統允許一個活動攔截一個意圖並允許這個活動比其他處理相同意圖的活動擁有更高的優先順序。
在onNewIntent(),我們試圖解析所有的NDEF消息和它們的記錄。因為有幾個不同的資料類型,這個例子僅僅試圖解析由inNdefRecord.RTD_TEXT定義的文本類型。
[mw_shl_code=java,true]package com.songsoft.NFC;
import java.util.Arrays;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.NfcF;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.widget.TextView;
public class TagDispatch extends Activity {
private TextView mTextView;
private NfcAdapter mNfcAdapter;
private PendingIntent mPendingIntent;
private IntentFilter[] mIntentFilters;
private String[][] mNFCTechLists;
@Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.main);
mTextView = (TextView)findViewById(R.id.tv);
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter != null) {
mTextView.setText("读取一个NFC标签");
} else {
mTextView.setText("不支持NFC。");
}
mPendingIntent = PendingIntent.getActivity(this, 0,new Intent(this,getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter ndefIntent = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
ndefIntent.addDataType("*/*");
mIntentFilters = new IntentFilter[] { ndefIntent };
} catch (Exception e) {
Log.e("TagDispatch", e.toString());
}
mNFCTechLists = new String[][] { new String[] { NfcF.class.getName() } };
}
@Override
public void onNewIntent(Intent intent) {
String action = intent.getAction();
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String s = action + "\n\n" + tag.toString();
Parcelable[] data = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (data != null) {
try {
for (int i = 0; i < data.length; i++) {
NdefRecord [] recs = ((NdefMessage)data).getRecords();
for (int j = 0; j < recs.length; j++) {
if (recs[j].getTnf() == NdefRecord.TNF_WELL_KNOWN &&
Arrays.equals(recs[j].getType(), NdefRecord.RTD_TEXT)) {
byte[] payload = recs[j].getPayload();
String textEncoding = ((payload[0] & 0200) == 0) ? "UTF-8" : "UTF-16";
int langCodeLen = payload[0] & 0077;
s += ("\n\nNdefMessage[" + i + "], NdefRecord[" + j + "]:\n\"" +
new String(payload, langCodeLen + 1,
payload.length - langCodeLen - 1, textEncoding) +
"\"");
}
}
}
} catch (Exception e) {
Log.e("TagDispatch", e.toString());
}
}
mTextView.setText(s);
}
@Override
public void onResume() {
super.onResume();
if (mNfcAdapter != null)
mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, mIntentFilters, mNFCTechLists);
}
@Override
public void onPause() {
super.onPause();
if (mNfcAdapter != null)
mNfcAdapter.disableForegroundDispatch(this);
}
}[/mw_shl_code]
import java.util.Arrays;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.NfcF;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.widget.TextView;
public class TagDispatch extends Activity {
private TextView mTextView;
private NfcAdapter mNfcAdapter;
private PendingIntent mPendingIntent;
private IntentFilter[] mIntentFilters;
private String[][] mNFCTechLists;
@Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.main);
mTextView = (TextView)findViewById(R.id.tv);
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter != null) {
mTextView.setText("读取一个NFC标签");
} else {
mTextView.setText("不支持NFC。");
}
mPendingIntent = PendingIntent.getActivity(this, 0,new Intent(this,getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter ndefIntent = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
ndefIntent.addDataType("*/*");
mIntentFilters = new IntentFilter[] { ndefIntent };
} catch (Exception e) {
Log.e("TagDispatch", e.toString());
}
mNFCTechLists = new String[][] { new String[] { NfcF.class.getName() } };
}
@Override
public void onNewIntent(Intent intent) {
String action = intent.getAction();
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String s = action + "\n\n" + tag.toString();
Parcelable[] data = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (data != null) {
try {
for (int i = 0; i < data.length; i++) {
NdefRecord [] recs = ((NdefMessage)data).getRecords();
for (int j = 0; j < recs.length; j++) {
if (recs[j].getTnf() == NdefRecord.TNF_WELL_KNOWN &&
Arrays.equals(recs[j].getType(), NdefRecord.RTD_TEXT)) {
byte[] payload = recs[j].getPayload();
String textEncoding = ((payload[0] & 0200) == 0) ? "UTF-8" : "UTF-16";
int langCodeLen = payload[0] & 0077;
s += ("\n\nNdefMessage[" + i + "], NdefRecord[" + j + "]:\n\"" +
new String(payload, langCodeLen + 1,
payload.length - langCodeLen - 1, textEncoding) +
"\"");
}
}
}
} catch (Exception e) {
Log.e("TagDispatch", e.toString());
}
}
mTextView.setText(s);
}
@Override
public void onResume() {
super.onResume();
if (mNfcAdapter != null)
mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, mIntentFilters, mNFCTechLists);
}
@Override
public void onPause() {
super.onPause();
if (mNfcAdapter != null)
mNfcAdapter.disableForegroundDispatch(this);
}
}[/mw_shl_code]
通过AndroidBeam将NFC数据传到其他设备
通过Android Beam的支持发送NFC数据,所以这个活动通常被成为“beaming”。许多NDEF数据可以被传递,当然可以定义你自己的格式。这个实例演示了如何创建一个纯文本类型的记录。大部分代码看起来很熟悉。
[mw_shl_code=java,true]package com.songsoft.NFC;
import java.nio.charset.Charset;
import java.util.Locale;
import android.app.Activity;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.widget.TextView;
public class BeamData extends Activity {
private NfcAdapter mNfcAdapter;
private TextView mTextView;
private NdefMessage mNdefMessage;
@Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.main);
mTextView = (TextView)findViewById(R.id.tv);
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter != null) {
mTextView.setText("到另外一个设备");
} else {
mTextView.setText("不支持NFC");
}
mNdefMessage = new NdefMessage(
new NdefRecord[] {
createNewTextRecord("NDEF文本记录的第一个实例", Locale.ENGLISH, true),
createNewTextRecord("NDEF文本记录的第二个实例", Locale.ENGLISH, true) });
}
public static NdefRecord createNewTextRecord(String text, Locale locale, boolean encodeInUtf8) {
byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");
byte[] textBytes = text.getBytes(utfEncoding);
int utfBit = encodeInUtf8 ? 0 : (1 << 7);
char status = (char)(utfBit + langBytes.length);
byte[] data = new byte[1 + langBytes.length + textBytes.length];
data[0] = (byte)status;
System.arraycopy(langBytes, 0, data, 1, langBytes.length);
System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length);
return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data);
}
@Override
public void onResume() {
super.onResume();
if (mNfcAdapter != null)
mNfcAdapter.enableForegroundNdefPush(this, mNdefMessage);
}
@Override
public void onPause() {
super.onPause();
if (mNfcAdapter != null)
mNfcAdapter.disableForegroundNdefPush(this);
}
}[/mw_shl_code]
import java.nio.charset.Charset;
import java.util.Locale;
import android.app.Activity;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.widget.TextView;
public class BeamData extends Activity {
private NfcAdapter mNfcAdapter;
private TextView mTextView;
private NdefMessage mNdefMessage;
@Override
public void onCreate(Bundle savedState) {
super.onCreate(savedState);
setContentView(R.layout.main);
mTextView = (TextView)findViewById(R.id.tv);
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (mNfcAdapter != null) {
mTextView.setText("到另外一个设备");
} else {
mTextView.setText("不支持NFC");
}
mNdefMessage = new NdefMessage(
new NdefRecord[] {
createNewTextRecord("NDEF文本记录的第一个实例", Locale.ENGLISH, true),
createNewTextRecord("NDEF文本记录的第二个实例", Locale.ENGLISH, true) });
}
public static NdefRecord createNewTextRecord(String text, Locale locale, boolean encodeInUtf8) {
byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");
byte[] textBytes = text.getBytes(utfEncoding);
int utfBit = encodeInUtf8 ? 0 : (1 << 7);
char status = (char)(utfBit + langBytes.length);
byte[] data = new byte[1 + langBytes.length + textBytes.length];
data[0] = (byte)status;
System.arraycopy(langBytes, 0, data, 1, langBytes.length);
System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length);
return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], data);
}
@Override
public void onResume() {
super.onResume();
if (mNfcAdapter != null)
mNfcAdapter.enableForegroundNdefPush(this, mNdefMessage);
}
@Override
public void onPause() {
super.onPause();
if (mNfcAdapter != null)
mNfcAdapter.disableForegroundNdefPush(this);
}
}[/mw_shl_code]
总结
全站熱搜
留言列表