在安卓開發(fā)中開始應用NFC
NFC (近場通信)。
NFC 科技代表近場通信,你可以在 NFC 論壇上找到 NFC 的詳細信息。在本文中,我們將分析 NFC 的一些基礎知識,并且我們還將描述如何在安卓系統(tǒng)中實現一個利用 NFC 的 APP(應用程序)。
如果你想做 NFC 實驗,那么你在幾個網站上花費幾歐元就能買到 NFC 。
NFC 可以用于不同的情景:在家中時,我們可以使用它來打開 WiFi 或者執(zhí)行一些任務操作等等。
本文中,我們將注意力集中在 NDEF 數據,它是一種特殊類型的 NFC 標記。不過,在使用 NFC 之前,我們必須遵循一些基本步驟。
NFC 過濾器
當我們使用 NFC 標記時,我們要做的第一件事就是,當我們接近一個 NFC 標記的時候,我們的 APP 可以收到通知。為了實現這個目的,我們需要使用一個意圖過濾器。安卓 SDK 中提供了三種不同的過濾器,我們可以以不同的優(yōu)先級來使用它們:
ACTION_NDEF_DISCOVERED
ACTION_TECH_DISCOVERED
ACTION_TAG_DISCOVERED
我們重點關注 ACTION_NDEF_DISCOVERED,它擁有最高的優(yōu)先級。正如前面所說的,我們的目的是,當智能手機接近一個 NFC 標記時能夠收到通知,并且如果我們只安裝了這一個 APP,并且它能夠處理這個 NFC 標記,那么我們希望該 APP 能夠立即開始處理。為了實現這一點,我們在 Manifest.xml 中注冊過濾器:
package="com.survivingwithandroid.nfc">
....
在第 6 行,我們注冊了 APP,以使得它可以收到 ACTION_NDEF_DISCOVERED 通知。我們使用不同類型的過濾器,在這個例子中(第 8 行)我們使用了 mine 類型。換句話說,當發(fā)現一個 NFC 標記 NDEF 并且它的 mine 類型為“text/plain”時,我們的 APP 將會啟動。其實,我們可以使用幾種 mine 類型來過濾,而不僅僅是 text/plain。此外,我們還能以協議或一個字符串模式來使用其他類型的過濾器(如 android:scheme)來過濾。
NFC 前臺調度
如果我們的 APP 沒處于前臺,就會開始意圖過濾。如果我們的應用程序運行在前臺,那么當我們的智能手機移動到一個 NFC 標記時,它將不會收到通知。在這種情況下,我們必須使用一種稱為NFC前臺調度的技術。第一步是,在我們的代碼中定義意圖過濾器(正如我們在 Manifest.xml 中做的那樣):
@Override
protectedvoidonCreate(Bundle savedInstanceState){
...
Intent nfcIntent=newIntent(this,getClass());
nfcIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
nfcPendingIntent=
PendingIntent.getActivity(this,0,nfcIntent,0);
IntentFilter tagIntentFilter=
newIntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try{
tagIntentFilter.addDataType("text/plain");
intentFiltersArray=newIntentFilter[]{tagIntentFilter};
}
catch(Throwablet){
t.printStackTrace();
}
}
現在,我們必須注冊我們的過濾器,在 onResume 方法中以這種方式實現它:
protectedvoidonResume(){
super.onResume();
nfcAdpt.enableForegroundDispatch(
this,
nfcPendingIntent,
intentFiltersArray,
null);
handleIntent(getIntent());
}
此外,也應該記住,只要 APP 退回到后臺,我們就應該關閉前臺調度,而要實現這一點,最好的地方是在 onPause 方法中。
@Override
protectedvoidonPause(){
super.onPause();
nfcAdpt.disableForegroundDispatch(this);
}
其中,nfcAdpt 是 NFC 適配器。
使用 NFCAdapter 處理 NFC
一旦我們創(chuàng)建了過濾器,我們必須與智能手機中的 NFC 組件交互。為此,我們使用安卓 SDK 提供的 NfcAdapter。使用這個類,我們能夠檢測智能手機是否支持 NFC,或者 NFC 功能是否開啟或關閉。
@Override
protectedvoidonCreate(Bundle savedInstanceState){
...
nfcAdpt=NfcAdapter.getDefaultAdapter(this);
// Check if the smartphone has NFC
if(nfcAdpt==null){
Toast.makeText(this,"NFC not supported",Toast.LENGTH_LONG).show();
finish();
}
// Check if NFC is enabled
if(!nfcAdpt.isEnabled()){
Toast.makeText(this,"Enable NFC before using the app",Toast.LENGTH_LONG).show();
}
}
NFC 數據:負載
既然我們知道了如何處理 NFC 標記,接著我們就想讀取標記內容。在 NFC 說明文檔中,定義了幾種類型的內容:
NFC Forum well-known type
Media-type
Absolute URI
NFC Forum external type
每種類型都有它自己的有效負載。一般來說,一個 NFC NDEF 數據由一條信息組成,一條信息可以包含一個或多個記錄,每個記錄由一個頭和一個負載(真正的信息)組成?,F在,如果我們想讀取 NFC NDEF 標記中的數據,我們可以使用下面的代碼:
@Override
publicvoidonNewIntent(Intent intent){
Log.d("Nfc","New intent");
getTag(intent);
}
privatevoidgetTag(Intenti){
if(i==null)
return;
Stringtype=i.getType();
Stringaction=i.getAction();
List dataList=newArrayList();
if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)){
Log.d("Nfc","Action NDEF Found");
Parcelable[]parcs=i.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
for(Parcelablep:parcs){
recNumberTxt.setText(String.valueOf(numRec));
NdefRecord[]records=msg.getRecords();
for(NdefRecord record:records){
shorttnf=record.getTnf();
// Here we handle the payload
}
}
}
}