Android NFC开发

来源:互联网 发布:vm虚拟机没网络 编辑:程序博客网 时间:2024/06/05 08:40

由于工作关系,需要做智能卡(JavaCard Applet)和Android NFC方面的开发。

NFC主要有3种模式:读卡器模式, 卡模拟模式, 点到点模式。

本文主要参考了Android官方CardEmulation例子,描述如何实现HCE(主机卡模拟)。

开发前提条件:需要1部支持NFC的手机和一部非接读写器


首先使用AS创建一个工程.

在AndroidManifest.xml文件中添加以下代码

描述所需硬件特性

<uses-feature android:name="android.hardware.nfc.hce" android:required="true" />
描述应用所需的权限<uses-permission android:name="android.permission.NFC" /><uses-permission android:name="android.permission.INTERNET"/>

添加Service

<service android:name=".CardService"    android:exported="true"    android:permission="android.permission.BIND_NFC_SERVICE">    <!-- Intent filter indicating that we support card emulation. -->    <intent-filter>        <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE"/>        <category android:name="android.intent.category.DEFAULT"/>    </intent-filter>    <!-- Required XML configuration file, listing the AIDs that we are emulating cards         for. This defines what protocols our card emulation service supports. -->    <meta-data android:name="android.nfc.cardemulation.host_apdu_service"        android:resource="@xml/aid_list"/></service>

aid_list.xml文件

<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"    android:description="@string/service_name"    android:requireDeviceUnlock="false">    <!--    If category="payment" is used for any aid-groups, you must also add an android:apduServiceBanner    attribute above, like so:    android:apduServiceBanner="@drawable/settings_banner"     apduServiceBanner should be 260x96 dp. In pixels, that works out to...       - drawable-xxhdpi: 780x288 px       - drawable-xhdpi:  520x192 px       - drawable-hdpi:   390x144 px       - drawable-mdpi:   260x96  px    The apduServiceBanner is displayed in the "Tap & Pay" menu in the system Settings app, and    is only displayed for apps which implement the "payment" AID category.    Since this sample is implementing a non-standard card type (a loyalty card, specifically), we    do not need to define a banner.    Important: category="payment" should only be used for industry-standard payment cards. If you are        implementing a closed-loop payment system (e.g. stored value cards for a specific merchant        or transit system), use category="other". This is because only one "payment" card may be        active at a time, whereas all "other" cards are active simultaneously (subject to AID        dispatch).    -->    <aid-group android:description="@string/card_title" android:category="other">        <aid-filter android:name="A00000000386980700"/>    </aid-group></host-apdu-service>
service代码类
public class CardService extends HostApduService {
/** * Called if the connection to the NFC card is lost, in order to let the application know the * cause for the disconnection (either a lost link, or another AID being selected by the * reader). * * @param reason Either DEACTIVATION_LINK_LOSS or DEACTIVATION_DESELECTED */@Overridepublic void onDeactivated(int reason) {    Logger.i("onDeactivated reason:" + reason);}
/** * This method will be called when a command APDU has been received from a remote device. A * response APDU can be provided directly by returning a byte-array in this method. In general * response APDUs must be sent as quickly as possible, given the fact that the user is likely * holding his device over an NFC reader when this method is called. * * <p class="note">If there are multiple services that have registered for the same AIDs in * their meta-data entry, you will only get called if the user has explicitly selected your * service, either as a default or just for the next tap. * * <p class="note">This method is running on the main thread of your application. If you * cannot return a response APDU immediately, return null and use the {@link * #sendResponseApdu(byte[])} method later. * * @param commandApdu The APDU that received from the remote device * @param extras A bundle containing extra data. May be null. * @return a byte-array containing the response APDU, or null if no response APDU can be sent * at this point. */// BEGIN_INCLUDE(processCommandApdu)@Overridepublic byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {    Logger.i("Received APDU: " + ByteArrayToHexString(commandApdu));    byte cla = commandApdu[0];    byte ins = commandApdu[1];    //    switch (ins)    {        case (byte)0xA4:            select(commandApdu);            break;        case (byte)0xCA:            getMessage(commandApdu);            break;        case (byte)0xB0:            readBinary(commandApdu);            break;        case (byte)0x5c:            getBalance(commandApdu);            break;        case (byte)0x50:            purchaseInit(commandApdu);            break;        case (byte)0xDC:            updateRecord(commandApdu);            break;        case (byte)0x54:            purchase(commandApdu);            break;        default:    }    //要么返回GetResponse    Logger.d("processCommandApdu return null");    return null;}

返回apdu使用方法
sendResponseApdu(responseApdu);
由于迁涉到交通卡结构内容、密钥处理等保密协议,无法公开整个工程。但是整个流程还是比较简单的,无法就是接收到请求,然后调用远程或本地服务进行业务处理,最后返回处理结果的APDU.
使用HCE的最大好处就是不需要使用NFC-SIM或者eSE,不会受制于移动运营商和手机厂商。

0 1
原创粉丝点击