现在很多国外的手机都支持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进行读写