日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android NFC 开发实例

發(fā)布時間:2025/3/20 Android 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android NFC 开发实例 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
http://blog.csdn.net/pku_android/article/details/7430788


類:?Android應(yīng)用開發(fā)系列教程?Android應(yīng)用開發(fā)技巧?51910人閱讀?評論(57)?收藏?舉報 androidtypesactionlayoutstringbuffer

作者:裘德超


使用硬件:Google Nexus S,北京大學(xué)學(xué)生卡。(ps:筆者本想使用公交一卡通進(jìn)行測試,發(fā)現(xiàn)手機(jī)不能正確識別)

手機(jī)操作系統(tǒng):Android ICS 4.04。

開發(fā)時,筆者從Google Play Store上下載了NFC TagInfo軟件進(jìn)行對比學(xué)習(xí)。所以我們可以使用任意一張能被TagInfo軟件正確識別的卡做測試。

在Android NFC 應(yīng)用中,Android手機(jī)通常是作為通信中的發(fā)起者,也就是作為各種NFC卡的讀寫器。Android對NFC的支持主要在 android.nfc 和android.nfc.tech 兩個包中。

android.nfc 包中主要類如下:

NfcManager 可以用來管理Android設(shè)備中指出的所有NFCAdapter,但由于大部分Android設(shè)備只支持一個NFC Adapter,所以一般直接調(diào)用getDefaultAapater來獲取手機(jī)中的Adapter。

NfcAdapter 相當(dāng)于一個NFC適配器,類似于電腦裝了網(wǎng)絡(luò)適配器才能上網(wǎng),手機(jī)裝了NfcAdapter才能發(fā)起NFC通信。

?NDEF: NFC Data Exchange Format,即NFC數(shù)據(jù)交換格式。

NdefMessage 和NdefRecord NDEF 為NFC forum 定義的數(shù)據(jù)格式。

Tag 代表一個被動式Tag對象,可以代表一個標(biāo)簽,卡片等。當(dāng)Android設(shè)備檢測到一個Tag時,會創(chuàng)建一個Tag對象,將其放在Intent對象,然后發(fā)送到相應(yīng)的Activity。

android.nfc.tech 中則定義了可以對Tag進(jìn)行的讀寫操作的類,這些類按照其使用的技術(shù)類型可以分成不同的類如:NfcA, NfcB, NfcF,以及MifareClassic 等。其中MifareClassic比較常見。

在本次實(shí)例中,筆者使用北京大學(xué)學(xué)生卡進(jìn)行數(shù)據(jù)讀取測試,學(xué)生卡的TAG類型為MifareClassic。


AndroidManifest.xml:


[html]?view plaincopy
  • <span?style="font-size:16px;"><?xml?version="1.0"?encoding="utf-8"?>??
  • <manifest?xmlns:android="http://schemas.android.com/apk/res/android"??
  • ????package="org.reno"??
  • ????android:versionCode="1"??
  • ????android:versionName="1.0"?>??
  • ????<uses-permission?android:name="android.permission.NFC"?/>??
  • ????<uses-sdk?android:minSdkVersion="14"?/>??
  • ????<uses-feature?android:name="android.hardware.nfc"?android:required="true"?/>??
  • ????<application??
  • ????????android:icon="@drawable/ic_launcher"??
  • ????????android:label="@string/app_name"?>??
  • ????????<activity??
  • ????????????android:name="org.reno.Beam"??
  • ????????????android:label="@string/app_name"??
  • ????????????android:launchMode="singleTop"?>??
  • ????????????<intent-filter>??
  • ????????????????<action?android:name="android.intent.action.MAIN"?/>??
  • ??
  • ????????????????<category?android:name="android.intent.category.LAUNCHER"?/>??
  • ????????????</intent-filter>??
  • ????????????<intent-filter>??
  • ????????????????<action?android:name="android.nfc.action.TECH_DISCOVERED"?/>??
  • ????????????</intent-filter>??
  • ????????????<meta-data??
  • ????????????????android:name="android.nfc.action.TECH_DISCOVERED"??
  • ????????????????android:resource="@xml/nfc_tech_filter"?/>??
  • ????????</activity>??
  • ????</application>??
  • </manifest>??
  • </span>??


  • res/xml/nfc_tech_filter.xml:


    <resources?xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">

    ????<tech-list>

    ???????<tech>android.nfc.tech.MifareClassic</tech>

    ????</tech-list>

    </resources>


    <uses-permission?android:name="android.permission.NFC"?/>

    <uses-feature?android:name="android.hardware.nfc"?android:required="true"?/>


    表示會使用到硬件的NFC功能。并且當(dāng)用戶在Google Play Store中搜索時,只有帶有NFC功能的手機(jī)才能夠搜索到本應(yīng)用。

    ?

    當(dāng)手機(jī)開啟了NFC,并且檢測到一個TAG后,TAG分發(fā)系統(tǒng)會自動創(chuàng)建一個封裝了NFC TAG信息的intent。如果多于一個應(yīng)用程序能夠處理這個intent的話,那么手機(jī)就會彈出一個框,讓用戶選擇處理該TAG的Activity。TAG分發(fā)系統(tǒng)定義了3中intent。按優(yōu)先級從高到低排列為:

    NDEF_DISCOVERED, TECH_DISCOVERED, TAG_DISCOVERED

    當(dāng)Android設(shè)備檢測到有NFC Tag靠近時,會根據(jù)Action申明的順序給對應(yīng)的Activity 發(fā)送含NFC消息的 Intent。

    此處我們使用的intent-filter的Action類型為TECH_DISCOVERED從而可以處理所有類型為ACTION_TECH_DISCOVERED并且使用的技術(shù)為nfc_tech_filter.xml文件中定義的類型的TAG。

    ?

    詳情可查看http://developer.android.com/guide/topics/nfc/nfc.html說明。下圖為當(dāng)手機(jī)檢測到一個TAG時,啟用Activity的匹配過程。




    res/layout/main.xml


    [html]?view plaincopy
  • <?xml?version="1.0"?encoding="utf-8"?>??
  • <LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"??
  • ????android:layout_width="fill_parent"??
  • ????android:layout_height="fill_parent"??
  • ????android:orientation="vertical"?>??
  • ??
  • ????<ScrollView??
  • ????????android:id="@+id/scrollView"??
  • ????????android:layout_width="fill_parent"??
  • ????????android:layout_height="fill_parent"??
  • ????????android:background="@android:drawable/edit_text"?>??
  • ??
  • ????????<TextView??
  • ????????????android:id="@+id/promt"??
  • ????????????android:layout_width="fill_parent"??
  • ????????????android:layout_height="wrap_content"??
  • ????????????android:scrollbars="vertical"??
  • ????????????android:singleLine="false"??
  • ????????????android:text="@string/info"?/>??
  • ????</ScrollView>??
  • ??
  • </LinearLayout>??

  • 定義了Activity的布局:只有一個帶有滾動條的TextView用于顯示從TAG中讀取的信息。

    res/values/strings.xml


    [html]?view plaincopy
  • <?xml?version="1.0"?encoding="utf-8"?>??
  • <resources>??
  • ????<string?name="app_name">NFC測試</string>??
  • ????<string?name="info">掃描中。。。</string>??
  • </resources>??

  • src/org/reno/Beam.java

    [java]?view plaincopy
  • package?org.reno;??
  • ??
  • import?android.app.Activity;??
  • import?android.content.Intent;??
  • import?android.nfc.NfcAdapter;??
  • import?android.nfc.Tag;??
  • import?android.nfc.tech.MifareClassic;??
  • import?android.os.Bundle;??
  • import?android.widget.TextView;??
  • ??
  • public?class?Beam?extends?Activity?{??
  • ????NfcAdapter?nfcAdapter;??
  • ????TextView?promt;??
  • ????@Override??
  • ????public?void?onCreate(Bundle?savedInstanceState)?{??
  • ????????super.onCreate(savedInstanceState);??
  • ????????setContentView(R.layout.main);??
  • ????????promt?=?(TextView)?findViewById(R.id.promt);??
  • ????????//?獲取默認(rèn)的NFC控制器??
  • ????????nfcAdapter?=?NfcAdapter.getDefaultAdapter(this);??
  • ????????if?(nfcAdapter?==?null)?{??
  • ????????????promt.setText("設(shè)備不支持NFC!");??
  • ????????????finish();??
  • ????????????return;??
  • ????????}??
  • ????????if?(!nfcAdapter.isEnabled())?{??
  • ????????????promt.setText("請在系統(tǒng)設(shè)置中先啟用NFC功能!");??
  • ????????????finish();??
  • ????????????return;??
  • ????????}??
  • ????}??
  • ??
  • ????@Override??
  • ????protected?void?onResume()?{??
  • ????????super.onResume();??
  • ????????//得到是否檢測到ACTION_TECH_DISCOVERED觸發(fā)??
  • ????????if?(NfcAdapter.ACTION_TECH_DISCOVERED.equals(getIntent().getAction()))?{??
  • ????????????//處理該intent??
  • ????????????processIntent(getIntent());??
  • ????????}??
  • ????}??
  • ????//字符序列轉(zhuǎn)換為16進(jìn)制字符串??
  • ????private?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);??
  • ????????????System.out.println(buffer);??
  • ????????????stringBuilder.append(buffer);??
  • ????????}??
  • ????????return?stringBuilder.toString();??
  • ????}??
  • ??
  • ????/**?
  • ?????*?Parses?the?NDEF?Message?from?the?intent?and?prints?to?the?TextView?
  • ?????*/??
  • ????private?void?processIntent(Intent?intent)?{??
  • ????????//取出封裝在intent中的TAG??
  • ????????Tag?tagFromIntent?=?intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);??
  • ????????for?(String?tech?:?tagFromIntent.getTechList())?{??
  • ????????????System.out.println(tech);??
  • ????????}??
  • ????????boolean?auth?=?false;??
  • ????????//讀取TAG??
  • ????????MifareClassic?mfc?=?MifareClassic.get(tagFromIntent);??
  • ????????try?{??
  • ????????????String?metaInfo?=?"";??
  • ????????????//Enable?I/O?operations?to?the?tag?from?this?TagTechnology?object.??
  • ????????????mfc.connect();??
  • ????????????int?type?=?mfc.getType();//獲取TAG的類型??
  • ????????????int?sectorCount?=?mfc.getSectorCount();//獲取TAG中包含的扇區(qū)數(shù)??
  • ????????????String?typeS?=?"";??
  • ????????????switch?(type)?{??
  • ????????????case?MifareClassic.TYPE_CLASSIC:??
  • ????????????????typeS?=?"TYPE_CLASSIC";??
  • ????????????????break;??
  • ????????????case?MifareClassic.TYPE_PLUS:??
  • ????????????????typeS?=?"TYPE_PLUS";??
  • ????????????????break;??
  • ????????????case?MifareClassic.TYPE_PRO:??
  • ????????????????typeS?=?"TYPE_PRO";??
  • ????????????????break;??
  • ????????????case?MifareClassic.TYPE_UNKNOWN:??
  • ????????????????typeS?=?"TYPE_UNKNOWN";??
  • ????????????????break;??
  • ????????????}??
  • ????????????metaInfo?+=?"卡片類型:"?+?typeS?+?"\n共"?+?sectorCount?+?"個扇區(qū)\n共"??
  • ????????????????????+?mfc.getBlockCount()?+?"個塊\n存儲空間:?"?+?mfc.getSize()?+?"B\n";??
  • ????????????for?(int?j?=?0;?j?<?sectorCount;?j++)?{??
  • ????????????????//Authenticate?a?sector?with?key?A.??
  • ????????????????auth?=?mfc.authenticateSectorWithKeyA(j,??
  • ????????????????????????MifareClassic.KEY_DEFAULT);??
  • ????????????????int?bCount;??
  • ????????????????int?bIndex;??
  • ????????????????if?(auth)?{??
  • ????????????????????metaInfo?+=?"Sector?"?+?j?+?":驗(yàn)證成功\n";??
  • ????????????????????//?讀取扇區(qū)中的塊??
  • ????????????????????bCount?=?mfc.getBlockCountInSector(j);??
  • ????????????????????bIndex?=?mfc.sectorToBlock(j);??
  • ????????????????????for?(int?i?=?0;?i?<?bCount;?i++)?{??
  • ????????????????????????byte[]?data?=?mfc.readBlock(bIndex);??
  • ????????????????????????metaInfo?+=?"Block?"?+?bIndex?+?"?:?"??
  • ????????????????????????????????+?bytesToHexString(data)?+?"\n";??
  • ????????????????????????bIndex++;??
  • ????????????????????}??
  • ????????????????}?else?{??
  • ????????????????????metaInfo?+=?"Sector?"?+?j?+?":驗(yàn)證失敗\n";??
  • ????????????????}??
  • ????????????}??
  • ????????????promt.setText(metaInfo);??
  • ????????}?catch?(Exception?e)?{??
  • ????????????e.printStackTrace();??
  • ????????}??
  • ????}??
  • }??


  • 關(guān)于MifareClassic卡的背景介紹:數(shù)據(jù)分為16個區(qū)(Sector) ,每個區(qū)有4個塊(Block) ,每個塊可以存放16字節(jié)的數(shù)據(jù)。

    每個區(qū)最后一個塊稱為Trailer ,主要用來存放讀寫該區(qū)Block數(shù)據(jù)的Key ,可以有A,B兩個Key,每個Key 長度為6個字節(jié),缺省的Key值一般為全FF或是0. 由 MifareClassic.KEY_DEFAULT 定義。

    因此讀寫Mifare Tag 首先需要有正確的Key值(起到保護(hù)的作用),如果鑒權(quán)成功

    然后才可以讀寫該區(qū)數(shù)據(jù)。

    執(zhí)行效果:








    參考聯(lián)接:

    http://developer.android.com/guide/topics/nfc/nfc.html

    http://developer.android.com/reference/android/nfc/tech/MifareClassic.html

    http://www.imobilebbs.com/wordpress/?p=2822

    總結(jié)

    以上是生活随笔為你收集整理的Android NFC 开发实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。