2015年10月26日 星期一

NFC於Android之應用

NFC基本原理
# 近場通訊NFC(Near Field Communication)無線射頻辨識 (Radio Frequency IDentificationRFID)的一種延伸技術

具有以下特點:
# 非接觸式點對點資料傳輸
# 10 公分 (3.9 英吋)
# RFID演變而來
# 13.56MHz運行於20公分內
# 傳輸速度106 Kbit / 212 Kbit/ 425 Kbit/
# ISO/IEC IS 18092 國際標準
# EMCA-340標準
# ETSI TS 102 190 標準
# 讀取模式 : 主動 / 被動


NFC
Bluetooth
Bluetooth Low Energy
RFID相容
ISO 18000-3
active
active
標準化機構
ISO/IEC
Bluetooth SIG
Bluetooth SIG
網路標準
ISO 13157 etc.
IEEE 802.15.1
IEEE 802.15.1
網路類型
Point-to-point
WPAN
WPAN
加密
not with RFID
available
available
範圍
< 0.2 m
~10 m (class 2)
~1 m (class 3)
頻率
13.56 MHz
2.4-2.5 GHz
2.4-2.5 GHz
Bit rate
424 kbit/s
2.1 Mbit/s
~1.0 Mbit/s
設定程式
< 0.1 s
< 6 s
< 0.006 s
功耗
< 15mA (read)
varies with class
< 15 mA (xmit)


NFC的資料通訊模式分為主動模式與被動模式兩種:
(1) 主動模式 (有源標籤)
在主動模式下,NFC的兩端設備都必須要支援全雙向的資料交換,
接收端需要有電源供應,稱為有源標籤.

(2) 被動模式 (無源標籤)
在被動模式下,NFC的啟動端,將要傳輸的訊息發送到NFC的接收端,接收端本身不需要有電源的供應,就像是我們的悠遊卡一樣,接收端利用發送端所產生的電場回應訊息給NFC的啟動端。

# 在每張NFC卡在出廠時都會配有一組UID,基本上是不可更改的.

使用Android Mobile作為NFC模擬卡:
在一部配備NFC功能的手機實現NFC卡的模擬,目前有兩種方式.
一種是基於硬體的,稱為虛擬卡模式(Virtual Card Mode).
一種是基於軟體的,被稱為主機卡模式(Host Card Mode).
在硬體的虛擬卡實現中,需要有SE模組的支援(Secure Elemen),而SE模組的實施有以下方案:
#內嵌於 SIM
#內嵌於 SD
#內嵌於 NFC 晶片

20131031日,google發布android 4.4系統,其中包含一種叫HCE(Host Card Emulation)的技術.HCE能使用軟體的方式使行動裝置能使用NFC卡模擬的功能.
HCE技術是模擬NFCSE通信的協議和實現。但是HCE並沒有實現SE,只是用NFCSE通信的方式告訴NFC讀卡器後面有SE的支持,從而以虛擬SE的方式完成NFC業務的安全保證.

Android4.4系統使用NFC論壇制定的的ISO-DEP標準協議(基於ISO/IEC14443-4ISO-DEP)標準)進行數據傳輸,傳輸的數據單元被稱為應用協議數據單元(APDUs)

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

服務註冊:
  <!-- Service for handling communication with NFC terminal. -->
        <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>
<!-- END_INCLUDE(CardEmulationManifest) -->

AID註冊:
<!-- BEGIN_INCLUDE(CardEmulationXML) -->
<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="F222222222"/>
    </aid-group>
<!-- END_INCLUDE(CardEmulationXML) -->
</host-apdu-service>

繼承 and 複寫:

public class CardService extends HostApduService
{
...

 // BEGIN_INCLUDE(processCommandApdu)
    @Override
    public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
        Log.i(TAG, "Received APDU: " + ByteArrayToHexString(commandApdu));
        // If the APDU matches the SELECT AID command for this service,
        // send the loyalty card account number, followed by a SELECT_OK status trailer (0x9000).
        if (Arrays.equals(SELECT_APDU, commandApdu)) {
            String account = AccountStorage.GetAccount(this);
            byte[] accountBytes = account.getBytes();
            Log.i(TAG, "Sending account number: " + account);
            return ConcatArrays(accountBytes, SELECT_OK_SW);
        } else {
            return UNKNOWN_CMD_SW;
        }
    }
    // END_INCLUDE(processCommandApdu)

...
}

Android官方範例:

使用Android Mobile 作為NFC讀卡機:
連線至讀卡機後,傳送SELECT AID的指令,
NFC 模擬卡的部分,我們設定AID (Application ID) = F222222222
因此傳送此指令:
00A4040005F222222222


參考資料:

沒有留言:

張貼留言