Android NFC开发(一)
???????前段時(shí)間由于工作需要,對(duì)NFC做了一些學(xué)習(xí)以及項(xiàng)目上的應(yīng)用,最近工作不是很忙,給大家更新一下NFC連載篇,大家可以共同學(xué)習(xí)進(jìn)步!
NFC開(kāi)發(fā) —————實(shí)現(xiàn)NFC手機(jī)做門(mén)禁卡的方法(二)
NFC開(kāi)發(fā) —————ID卡、IC卡(M1卡、CPU卡)的區(qū)別(三)
NFC開(kāi)發(fā) —————實(shí)用工具以及開(kāi)發(fā)文檔(四)
NFC(Near field communication)
???????簡(jiǎn)介:即近距離無(wú)線通訊技術(shù)。這個(gè)技術(shù)由免接觸式射頻識(shí)別(RFID)演變而來(lái),由飛利浦半導(dǎo)體(現(xiàn)恩智浦半導(dǎo)體)、諾基亞和索尼共同研制開(kāi)發(fā),其基礎(chǔ)是RFID及互連技術(shù)。近場(chǎng)通信是一種短距高頻的無(wú)線電技術(shù),在13.56MHz頻率運(yùn)行于20厘米距離內(nèi)。其傳輸速度有106 Kbit/秒、212 Kbit/秒或者424 Kbit/秒三種。目前近場(chǎng)通信已通過(guò)成為ISO/IEC IS 18092國(guó)際標(biāo)準(zhǔn)、EMCA-340標(biāo)準(zhǔn)與ETSI TS 102 190標(biāo)準(zhǔn)。
NFC三種設(shè)計(jì)模式
數(shù)據(jù)在NFC芯片中,可以簡(jiǎn)單理解成“刷標(biāo)簽”。本質(zhì)上就是通過(guò)支持NFC的手機(jī)或其它電子設(shè)備從帶有NFC芯片的標(biāo)簽、貼紙、名片等媒介中讀寫(xiě)信息。通常NFC標(biāo)簽是不需要外部供電的。當(dāng)支持NFC的外設(shè)向NFC讀寫(xiě)數(shù)據(jù)時(shí),它會(huì)發(fā)送某種磁場(chǎng),而這個(gè)磁場(chǎng)會(huì)自動(dòng)的向NFC標(biāo)簽供電。
數(shù)據(jù)在支持NFC的手機(jī)或其它電子設(shè)備中,可以簡(jiǎn)單理解成“刷手機(jī)”。本質(zhì)上就是將支持NFC的手機(jī)或其它電子設(shè)備當(dāng)成借記卡、公交卡、門(mén)禁卡等IC卡使用。基本原理是將相應(yīng)IC卡中的信息憑證封裝成數(shù)據(jù)包存儲(chǔ)在支持NFC的外設(shè)中 。
在使用時(shí)還需要一個(gè)NFC射頻器(相當(dāng)于刷卡器)。將手機(jī)靠近NFC射頻器,手機(jī)就會(huì)接收到NFC射頻器發(fā)過(guò)來(lái)的信號(hào),在通過(guò)一系列復(fù)雜的驗(yàn)證后,將IC卡的相應(yīng)信息傳入NFC射頻器,最后這些IC卡數(shù)據(jù)會(huì)傳入NFC射頻器連接的電腦,并進(jìn)行相應(yīng)的處理(如電子轉(zhuǎn)帳、開(kāi)門(mén)等操作)。
該模式與藍(lán)牙、紅外差不多,用于不同NFC設(shè)備之間進(jìn)行數(shù)據(jù)交換,不過(guò)這個(gè)模式已經(jīng)沒(méi)有有“刷”的感覺(jué)了。其有效距離一般不能超過(guò)4厘米,但傳輸建立速度要比紅外和藍(lán)牙技術(shù)快很多,傳輸速度比紅外塊得多,如過(guò)雙方都使用Android4.2,NFC會(huì)直接利用藍(lán)牙傳輸。這種技術(shù)被稱為Android Beam。所以使用Android Beam傳輸數(shù)據(jù)的兩部設(shè)備不再限于4厘米之內(nèi)。
點(diǎn)對(duì)點(diǎn)模式的典型應(yīng)用是兩部支持NFC的手機(jī)或平板電腦實(shí)現(xiàn)數(shù)據(jù)的點(diǎn)對(duì)點(diǎn)傳輸,例如,交換圖片或同步設(shè)備聯(lián)系人。因此,通過(guò)NFC,多個(gè)設(shè)備如數(shù)字相機(jī),計(jì)算機(jī),手機(jī)之間,都可以快速連接,并交換資料或者服務(wù)。
NFC、藍(lán)牙和紅外之間的差異:
卡片的分類
后期會(huì)專門(mén)出一篇文章對(duì)卡片分類做一些講解(ID卡、IC卡(M1卡、CPU卡)的區(qū)別)
卡模擬模式可實(shí)現(xiàn)的應(yīng)用
1、基于HCE應(yīng)用
1、)公交卡(虛擬卡)
軟件廠家與交通部等聯(lián)合推出的交通聯(lián)合標(biāo)準(zhǔn)的公交云卡。如:福建出行助手。
2、)銀行卡(虛擬卡)
各銀行APP開(kāi)通的云閃付,聯(lián)機(jī)閃付。如:銀行APP的云閃付。
2、基于NFC-SWP應(yīng)用(電信錢(qián)包/移動(dòng)和包/聯(lián)通沃錢(qián)包)
1、)公交卡(實(shí)體異形卡)
當(dāng)?shù)剡\(yùn)營(yíng)商與各城市一卡通公司合作開(kāi)通的NFC公交應(yīng)用。如:成都電信的手機(jī)天府通。
2、)銀行卡(實(shí)體異形卡,已沒(méi)落。)
運(yùn)營(yíng)商與各銀行或銀聯(lián)開(kāi)通的銀行卡應(yīng)用。如:電子借記卡/貸記卡,聯(lián)機(jī)閃付;電子現(xiàn)金卡,脫機(jī)閃付。
3、)門(mén)禁卡/消費(fèi)卡(實(shí)體異形卡)
運(yùn)營(yíng)商與各學(xué)校或企業(yè)合作開(kāi)通的手機(jī)一卡通,直接用NFC手機(jī)代替校園卡或企業(yè)卡等。如:電信的校園翼機(jī)通。
3、基于eSE應(yīng)用
1、)公交卡(實(shí)體異形卡)
手機(jī)廠家與部分城市一卡通合作開(kāi)通的公交卡。如:Mi Pay、Huawei Pay等支持開(kāi)通部分城市公交卡。
2、)銀行卡(虛擬卡)
手機(jī)廠家與銀聯(lián)及銀行合作開(kāi)通的銀行卡。如:Apple Pay、Sumsung Pay、huawei Pay、Mi Pay等綁定銀行卡開(kāi)通的虛擬卡,聯(lián)機(jī)閃付。
讀寫(xiě)模式可實(shí)現(xiàn)的應(yīng)用(常用)
1、)都都寶手機(jī)客戶端
天府通卡的電子錢(qián)包充值。
2、)卡卡聯(lián)手機(jī)客戶端
可為銀行閃付卡(金融IC卡)的電子現(xiàn)金賬戶充值(圈存)。
3、)銀聯(lián)錢(qián)包的‘生活’中‘拍拍卡’
可為銀行閃付卡(金融IC卡)的電子現(xiàn)金賬戶充值(圈存)。
非主流卡模擬應(yīng)用(基于NFC-SD應(yīng)用)
1、)公交手環(huán)或手表,如刷刷手環(huán)、怡康(Walker)手環(huán)等。
2、)銀行手環(huán)或手表,如興動(dòng)力手環(huán)等。
3、)公交及銀行手環(huán)或手表,如拉卡拉手環(huán)或手表。
Android的NFC標(biāo)簽調(diào)度系統(tǒng)
當(dāng)手機(jī)發(fā)現(xiàn)外部NFC的標(biāo)簽(指含有NFC功能的設(shè)備)時(shí),Android系統(tǒng)會(huì)尋找可以處理這個(gè)標(biāo)簽的Activity,那怎么知道哪個(gè)Activity能處理這條NFC消息呢?答案是清單文件,我們需要在清單文件中設(shè)置intent-filter。系統(tǒng)會(huì)分發(fā)NFC消息到設(shè)置intent-filter的Activity中,當(dāng)然,接收NFC消息也有優(yōu)先級(jí)之分,也是通過(guò)設(shè)置intent-filter來(lái)設(shè)置接收NFC消息的優(yōu)先級(jí)的。
NFC的標(biāo)簽調(diào)度系統(tǒng)綁定了3中intent,按優(yōu)先級(jí)的高低列出,如下
啟動(dòng) Activity。這是優(yōu)先級(jí)最高的 Intent,NFC標(biāo)簽調(diào)度系統(tǒng)會(huì)盡可能嘗試使用此 Intent 啟動(dòng)
Activity,在找不到這個(gè)Intent時(shí)才會(huì)嘗試使用其他 Intent。
Activity,則標(biāo)簽調(diào)度系統(tǒng)會(huì)嘗試使用此 Intent 來(lái)啟動(dòng)應(yīng)用。此外,如果掃描到的標(biāo)簽包含無(wú)法映射到 MIME 類型或 URI
的 NDEF 數(shù)據(jù),或者該標(biāo)簽不包含 NDEF 數(shù)據(jù),但它使用了已知的標(biāo)簽技術(shù),那么也會(huì)直接啟動(dòng)此 Intent(無(wú)需先啟動(dòng)
ACTION_NDEF_DISCOVERED)。
ACTION_TECH_DISCOVERED Intent 的 Activity,則使用此 Intent 啟動(dòng) Activity。
Tag支持的技術(shù)標(biāo)準(zhǔn)
卡片常用的數(shù)據(jù)格式:
MifareClassic數(shù)據(jù)格式就是NfcA。
IsoDep:各種公交卡。
NfcB:二代身份證。
NfcF:Felica。
NfcV:德州儀器的VicinityCard
Ndef:安卓主流的傳輸數(shù)據(jù)格式。
跟NFC有關(guān)的常見(jiàn)的ISO標(biāo)準(zhǔn)有:
最后這里簡(jiǎn)單的教大家如何使用NFC
NFC集成以及配置
清單文件里面的配置:
<uses-permission android:name="android.permission.NFC" /> <!-- 當(dāng)前設(shè)備必須要有NFC芯片 --><uses-featureandroid:name="android.hardware.nfc"android:required="true" />對(duì)執(zhí)行讀取設(shè)備數(shù)據(jù)的activity配置:
<intent-filter><action android:name="android.nfc.action.NDEF_DISCOVERED" /></intent-filter><intent-filter><action android:name="android.nfc.action.TECH_DISCOVERED" /></intent-filter><meta-dataandroid:name="android.nfc.action.TECH_DISCOVERED"android:resource="@xml/nfc_tech_filter" /><intent-filter><action android:name="android.nfc.action.TAG_DISCOVERED" /></intent-filter>nfc_tech_filter:
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"><!-- Android支持的NFC類型 --><tech-list><tech>android.nfc.tech.IsoDep</tech></tech-list><tech-list><tech>android.nfc.tech.NfcA</tech></tech-list><tech-list><tech>android.nfc.tech.NfcB</tech></tech-list><tech-list><tech>android.nfc.tech.NfcF</tech></tech-list><tech-list><tech>android.nfc.tech.NfcV</tech></tech-list><tech-list><tech>android.nfc.tech.Ndef</tech></tech-list><tech-list><tech>android.nfc.tech.NdefFormatable</tech></tech-list><tech-list><tech>android.nfc.tech.MifareUltralight</tech></tech-list><tech-list><tech>android.nfc.tech.MifareClassic</tech></tech-list> </resources>我在做NFC的時(shí)候,對(duì)其抽了一個(gè)基類:
/*** @author Martin-harry* @date 2021/11/11* @address* @Desc 子類在onNewIntent方法中進(jìn)行NFC標(biāo)簽相關(guān)操作。* 在onNewIntent方法中執(zhí)行intent傳遞過(guò)來(lái)的Tag數(shù)據(jù)*/ public abstract class BaseNfcActivity extends FragmentActivity {protected NfcAdapter mNfcAdapter;private PendingIntent mPendingIntent;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(createViews());//初始化視圖initView();//初始化控件initData();//初始化數(shù)據(jù)}protected abstract void initView();protected abstract void initData();protected abstract int createViews();/*** onCreat->onStart->onResume->onPause->onStop->onDestroy* 啟動(dòng)Activity,界面可見(jiàn)時(shí).*/@Overrideprotected void onStart() {super.onStart();//此處adapter需要重新獲取,否則無(wú)法獲取messagemNfcAdapter = NfcAdapter.getDefaultAdapter(this);//一旦截獲NFC消息,就會(huì)通過(guò)PendingIntent調(diào)用窗口mPendingIntent = PendingIntent.getActivity(this, 0,new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);}/*** 獲得焦點(diǎn),按鈕可以點(diǎn)擊*/@Overridepublic void onResume() {super.onResume();//設(shè)置處理優(yōu)于所有其他NFC的處理if (mNfcAdapter != null)mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null);}/*** 暫停Activity,界面獲取焦點(diǎn),按鈕可以點(diǎn)擊*/@Overridepublic void onPause() {super.onPause();//恢復(fù)默認(rèn)狀態(tài)if (mNfcAdapter != null)mNfcAdapter.disableForegroundDispatch(this);} }對(duì)用戶是否已經(jīng)開(kāi)啟NFC權(quán)限處理
/*** @author Martin-harry* @date 2021/11/11* @address* @Desc WelcomeActivity*/ public class WelcomeActivity extends BaseActivity implements View.OnClickListener {private ImageView nfc;private NfcAdapter mNfcAdapter;@Overrideprotected void initView() {nfc = findViewById(R.id.nfc);nfc.setOnClickListener(this);}@Overrideprotected void initData() {mNfcAdapter = NfcAdapter.getDefaultAdapter(this);}@Overrideprotected int createViews() {return R.layout.activity_welcome;}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.nfc:if (!ifNFCUse()) {Intent setNfc = new Intent(Settings.ACTION_NFC_SETTINGS);startActivity(setNfc);} else {startActivity(new Intent(this, ReadNfcActivity.class));}break;}}/*** 檢測(cè)工作,判斷設(shè)備的NFC支持情況** @return*/protected Boolean ifNFCUse() {if (mNfcAdapter == null) {Toast.makeText(this, "當(dāng)前設(shè)備不支持NFC!", Toast.LENGTH_SHORT).show();return false;}if (mNfcAdapter != null && !mNfcAdapter.isEnabled()) {Toast.makeText(this, "請(qǐng)?jiān)谙到y(tǒng)設(shè)置中先啟用NFC功能!", Toast.LENGTH_SHORT).show();return false;}return true;} }下面就是讀取NFC設(shè)備數(shù)據(jù)的操作:
/*** @author Martin-harry* @date 2021/11/11* @address* @Desc NFC讀取*/ public class ReadNfcActivity extends BaseNfcActivity implements View.OnClickListener {private TextView mNfcText;private ImageView back;private LinearLayout linTxt;private ImageView readPic;private TextView systemTime;private Button bt;private LinearLayout linBt;private String currentTime;private Tag mTag;@Overrideprotected void initView() {back = findViewById(R.id.back);readPic = findViewById(R.id.readPic);linTxt = findViewById(R.id.linTxt);mNfcText = findViewById(R.id.nfcTxt); systemTime = findViewById(R.id.systemTime);linBt = findViewById(R.id.linBt);bt = findViewById(R.id.bt);back.setOnClickListener(this);bt.setOnClickListener(this);resolveIntent(getIntent());}@Overridepublic void onNewIntent(Intent intent) {if (mNfcAdapter != null) {if (mNfcAdapter.isEnabled()) {resolveIntent(getIntent());}}}/*** 初次判斷卡片的類型** @param intent*/private void resolveIntent(Intent intent) {NdefMessage[] msgs = NfcUtil.getNdefMsg(intent); //解析nfc標(biāo)簽中的數(shù)據(jù)if (msgs == null) {Toast.makeText(ReadNfcActivity.this, "非NFC啟動(dòng)", Toast.LENGTH_SHORT).show();} else {String id = NfcUtil.readNFCId(NfcUtil.getNFCTag(intent));Log.e("讀取數(shù)據(jù) >>>", "nfcID:" + id);setNFCMsgView(id, msgs);}}/*** 顯示掃描后的信息** @param ndefMessages ndef數(shù)據(jù)*/@SuppressLint("SetTextI18n")private void setNFCMsgView(String tag, NdefMessage[] ndefMessages) {if (ndefMessages == null || ndefMessages.length == 0) {return;}// mNfcText.setText("Payload:" + new String(ndefMessages[0].getRecords()[0].getPayload()) + "\n");Log.e("ndef數(shù)據(jù) >>>>", "setNFCMsgView ndefMessages: " + ndefMessages.length );Log.e("ndef數(shù)據(jù) >>>>", "setNFCMsgView Payload: " + new String(ndefMessages[0].getRecords()[0].getPayload()) );readPic.setVisibility(View.GONE);linTxt.setVisibility(View.VISIBLE);linBt.setVisibility(View.VISIBLE);//將數(shù)據(jù)信息存儲(chǔ)到本地try {FileOutputStream fos = new FileOutputStream(getExternalFilesDir(null) + "/NFC讀取.txt", true);OutputStreamWriter ost = new OutputStreamWriter(fos);NdefMessage msg = ndefMessages[0];List<ParsedNdefRecord> records = NdefMessageParser.parse(msg);final int size = records.size();Log.e("ndef數(shù)據(jù) >>>>", "setNFCMsgView records: " + size );for (int i = 0; i < size; i++) {ParsedNdefRecord record = records.get(i);String math = record.toString();Log.e("ndef數(shù)據(jù) >>>>", "setNFCMsgView: math" + math );String viewText = record.getViewText();String TagStr = "55AA" + viewText;mNfcText.setText("Tag ID (hex): " + tag + "\n"+ "message:" + TagStr);currentTime = TimeFormatUtils.getCurrentTime();systemTime.setText("當(dāng)前系統(tǒng)時(shí)間:" + currentTime);Log.e("掃描后的數(shù)據(jù)信息 >>>>", "setNFCMsgView: " + record.getViewText());ost.write("Tag ID(hex):" + record.getViewText());ost.write("當(dāng)前系統(tǒng)時(shí)間:" + currentTime);ost.write("\n");ost.close();}} catch (FileNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}//字符序列轉(zhuǎn)換為16進(jìn)制字符串private static String bytesToHexString(byte[] src) {StringBuilder stringBuilder = new StringBuilder("0x");if (src == null || src.length <= 0) {return null;}char[] buffer = new char[2];for (int i = 0; i < src.length; i++) {buffer[0] = Character.forDigit((src[i] >>> 4) & 0x0F, 16);buffer[1] = Character.forDigit(src[i] & 0x0F, 16);stringBuilder.append(buffer);}return stringBuilder.toString();}@Overrideprotected void initData() {}@Overrideprotected int createViews() {return R.layout.activity_read_nfc;}@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.back:finish();break;case R.id.bt:mNfcText.setText("");systemTime.setText("");finish();break;}} }總結(jié)
以上是生活随笔為你收集整理的Android NFC开发(一)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【转载】ESFramewor使用技巧(2
- 下一篇: 初学Android之飞机大战——飞机大战