Mono for Android 之NFC

現在很多國外的手機都支持NFC功能,包括google、三星、HTC等。但中國的手機基本不支持,可能是考慮價格因素,而且NFC應用在中國還很少。NFC功能應該會成爲以後的標配吧,這幾年NFC應用應該會多起來,包括手機支付、手機刷公交等等。

NFC即near filed communication(近場通信),在RFID技術上發展而來。是由飛利浦公司發起,由諾基亞、索尼等著名廠商聯合主推的一項無線技術。

現在市場出現了很多NFC卡,主要包括Mifare卡、felica卡。NFC卡主要是指符合ISO/IEC 14443標準的卡,類型有TypeA、TypeB、TypeF,TypeA和TypeB主要指Mifare卡,TypeF主要是指Felica卡。Mifare卡在歐洲很流行,Felica卡在日本很流行。TypeA卡和TypeB卡主要是在字符編碼等方面有些不同

NFC卡又分爲邏輯加密和CPU卡。CPU卡是非常安全的,現在的金融卡用的就是這種卡。邏輯加密卡相對來也是安全的,但是國外有人已經把它破解了。邏輯加密可以參考Mifare相關文檔,看是怎麼進行密鑰驗證以及權限控制。

在CPU卡中有一種卡叫java卡,java卡的出現,讓程序員編寫的程序可以在不同廠商生產的java卡上運行。因爲每個廠商生成的NFC卡中的cos都可能不一樣,所以如果直接在CPU卡上進行編程,移植性就會很差。CPU卡相當與一臺微型計算機沒有輸入設備,也沒有輸出設備,但可以進行加解密,把信息加密後進行傳輸,所以CPU卡是很安全的。

好,說了那麼多,我們看一下Android是怎麼支持的。如果我們是在Android手機進行簡單的NFC開發,那是非常簡單的,上面的知識可以一點都不瞭解,也可以開發一個簡單的NFC程序。

在AndroidManifest.xml配置如下

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" android:versionCode="100000" android:versionName="Release_V1.0.0" package="NFCTR.Android">
  <uses-sdk android:targetSdkVersion="10" />
  <application android:label="@string/ApplicationName" android:icon="@drawable/icon">
		<activity
					 android:name="nfctr.app.ActTagReader"
					 android:label="@string/ApplicationName"
					 android:noHistory="true"
            >
			<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.NDEF_DISCOVERED"/>
				<data android:mimeType="*/*" />
				<category android:name="android.intent.category.DEFAULT"/>
			</intent-filter>
			<intent-filter>
				<action android:name="android.nfc.action.ACTION_TECH_DISCOVERED"/>
				<category android:name="android.intent.category.DEFAULT"/>
			</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" />
			<intent-filter>
				<action android:name="android.nfc.action.TAG_DISCOVERED"/>
				<category android:name="android.intent.category.DEFAULT"/>
			</intent-filter>
			<intent-filter>
				<action android:name="android.nfc.action.TAG_DISCOVERED"/>
			</intent-filter>
		</activity>
  </application>
  	<uses-feature android:name="android.hardware.nfc" android:required="true" />
	<uses-permission android:name="android.permission.NFC" />
</manifest>

nfc_tech_filter.xml文件內容如下(放在Resources目錄下的Xml目錄下,記着Xml目錄的X一定要大寫,這是Mono)

 

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <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.MifareClassic</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.MifareClassic</tech>
        <tech>android.nfc.tech.NdefFormatable</tech>
    </tech-list>
</resources>


 

intent-filter用來過濾該Activity多哪些NFC Tag感興趣。該配置基本上是對所有的NFC Tag感興趣

Activity ActTagReader界面代碼如下:

protected override void OnCreate(Bundle bundle)
		{
			base.OnCreate(bundle);
			m_NFCAdapter = NfcAdapter.GetDefaultAdapter(this);
			string intentType = Intent.Type ?? String.Empty;

			//if (intentType != String.Empty) // 發現新的NFC卡
			{
				// 獲取卡ID
				byte[] id = Intent.GetByteArrayExtra(NfcAdapter.ExtraId);
			}
		}


當手機發現NFC卡後就會看哪些程序對NFC卡感興趣,如果你手機只有這麼一個對NFC感興趣的APP的話,那麼手機會直接打開該程序,在OnCreate中,我們可以獲取卡的ID。

上面這樣執行,每次都會打開一個新的界面。如果有多個對NFC感興趣的APP,每次都還讓你選擇一下。如果我們想在打開ActTagReader界面的情況下,就使用該界面來處理NFC Tag,且不打開一個新的ActTagReader界面,那就要添加以下代碼

在OnResume方法中啓動前端分派系統,在OnPause方法中停止前端分派系統

/// <summary>
		/// 當應用程序恢復運行時,創建一個IntentFilter,當有NFC標籤被掃描時,調用OnNewIntent方法
		/// </summary>
		protected override void OnResume()
		{
			base.OnResume();

			var ndefDetected = new IntentFilter(NfcAdapter.ActionNdefDiscovered);
			ndefDetected.AddCategory(Intent.CategoryDefault);
			ndefDetected.AddDataType("*/*");
			var techDetected = new IntentFilter(NfcAdapter.ActionTechDiscovered);
			techDetected.AddCategory(Intent.CategoryDefault);
			techDetected.AddDataType("*/*");
			var tagDetected = new IntentFilter(NfcAdapter.ActionTagDiscovered);
			tagDetected.AddCategory(Intent.CategoryDefault);
			tagDetected.AddDataType("*/*");
			var filters = new[] {  techDetected };
			var intent = new Intent(this, GetType()).AddFlags(ActivityFlags.SingleTop);
			var pendingIntent = PendingIntent.GetActivity(this, 0, intent, 0);

			String[][] techListsArray = new String[][] {
				new String[]{"android.nfc.tech.IsoDep"},
			    new String[]{"android.nfc.tech.NfcA"},
			    new String[]{"android.nfc.tech.NfcB"},
			    new String[]{"android.nfc.tech.NfcF"},
			    new String[]{"android.nfc.tech.NfcV"},
			    new String[]{"android.nfc.tech.Ndef"},
			    new String[]{"android.nfc.tech.NdefFormatable"},
			    new String[]{"android.nfc.tech.MifareClassic"},
			    new String[]{"android.nfc.tech.MifareUltralight"},
			new String[] {"android.nfc.tech.NfcA", "android.nfc.tech.MifareClassic", "android.nfc.tech.NdefFormatable"}};

			m_NFCAdapter.EnableForegroundDispatch(this, pendingIntent, filters, techListsArray);
		}

		protected override void OnPause()
		{
			base.OnPause();
			// 應用程序暫停,所以需要移除對NFC標籤的監聽
			m_NFCAdapter.DisableForegroundDispatch(this);
		}

OK,填加了以上代碼後,在打開ActTagReader界面時,NFC手機發現NFC Tag就會丟給給當前Activity去處理,並執行OnNewIntent方法,所以我們需要覆寫OnNewIntent方法

/// <summary>
		/// 當應用程序發現NFC標籤時會執行該方法
		/// </summary>
		/// <param name="intent"></param>
		protected override void OnNewIntent(Intent intent)
		{
			string intentType = intent.Type ?? String.Empty;

			//if (intentType != String.Empty) // 發現新的NFC卡
			{
				byte[] id = intent.GetByteArrayExtra(NfcAdapter.ExtraId);
			}
		}

在OnNewIntent中就可以獲取NFC卡的ID以及對NFC進行讀寫


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章