NFC代表近场通讯,其全方位的测量精度可以达到厘米。这项技术也促进了其它一些好玩的技术的成长,如把两个手机碰到一起就可以启动一个多人游戏,把手机贴近NFC读写器就可以进行付款了。


在Android4.4之前,NFC支付过程需要通过借助设备上一个专有的安全部件(Secure Element,可以存在SIM卡中),使用本地存储的方式,关联设备本身的某种支付方式。这样的话其它的APP就很难通过NFC进行支付操作,因为这个过程是依靠部分硬件的,也就是Secure Element,现在的问题就是像Sprint通信公司或者Verizon通信公司的这个载体部件,应该让APP可以使用这个硬件功能。


基于主机的卡仿真技术


基于主机的卡仿真(HCE)是Android4.4的一项新技术,可以让app绕过Secure Element,然后使用云端支付信息或者其它方式存储的支付信息来模拟一个NFC卡。有了HCE,任何APP都可以模拟一个NFC卡,而且任意一台Android设备可以当做NFC读写器。

检测HCE功能就需要看看 FEATURE_NFC_HOST_CARD_EMULATION。


PackageManager pm = context.getPackageManager();
boolean hasNfcHce = pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION);



需要在AndroidManifest.xml中声明应用程序需要使用HCE功能:




<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc.hce" ... />



HCE需要实现为一个服务(service),Android中的服务可以运行在后台,启动后不用和用户进行交互。此服务可以让NFC在使用时不需要用户首先打开APP。在Android4.4中新增了

HostApduService

,继承它然后创建一个服务来处理近场通讯:



public class NfcHceService extends HostApduService {
    @Override
    public byte[] processCommandApdu(byte[] apdu, Bundle extras) { … }
  
    @Override
    public void onDeactivated(int reason) { … }
}



这个NfcHceService需要覆盖两个方法:processCommandApdu()和onDeactivated()。APDU(Application Protocol Data Unit)是NFC读写器发送给NfcHceService的数据单元,然后processCommandApdu()方法回送一个响应APDU。在NFC读写器和另外一个HCE服务通信或者设备不在NFC读写器的范围内时,onDeactivated()方法会被调用。

注意还要在AndroidManifest.xml中声明服务:

<service android:name=".NfcHceService"
    android:exported="true"
    android:permission="android.permission.BIND_NFC_SERVICE">
    <intent-filter>
        <action android:name="android.nfc.cardemulation.HOST_APDU_SERVICE" />
    </intent-filter>
    <meta-data android:name="android.nfc.cardemulation.host_apdu_service"
        android:resource="@xml/hceService" />
</service>



这个hceService.xml资源文件在meta-data标签里声明,告诉Android系统到哪里去寻找Application的ID组。

Application ID

Application ID (AID)可以让NFC读写器识别出设备需要读哪一张模拟卡(在processCommandApdu()方法中需要得到一个响应)。AID是由ISO/IEC 7816-5(International Organization for Standardization and the International Electrotechnical Commission)制定的,Android设备要想作为NFC读写器,必须注册一个AID。

这里在hceService.xml中定义了一个application的AID组,在此场景中,它就是一个用于支付的组(使用CardEmulation.CATEGORY而不是用其它的组CATEGORY_OTHER)。在这个支付组的AID的应用程序还需要有一个260*96dp的资源,为apduServiceBanner服务。

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/my_app_hce_service"
    android:requireDeviceUnlock="false"
    android:apduServiceBanner="@drawable/my_app_service_banner">
    <aid-group android:description="@string/my_app_aid_group"
                android:category="payment">
        <aid-filter android:name="4111111111111111"/>
        <aid-filter android:name="0123456789ABCDEF"/>
    </aid-group>
</host-apdu-service>



HCE简化了开启NFC功能,把它从载体部件中解脱出来(不用依赖Secure Element的载体了),解除了其它的设备等相关的限制。

想要了解更多关于给予主机的卡仿真技术可以看看这里 Host-based Card Emulation