安卓 NFC 主机卡模拟

安卓 NFC 卡模拟

StackOverFlow:Android HCE: are there rules for AID?

主机卡模拟Demo

第一步

新建类CardEmulatorService 继承 HostApduService,实现方法
public byte[] processCommandApdu(byte[] commandApdu, Bundle extras)

@Override
public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
    byte[] ret = null;
    Log.d("cyb", "processCommandApdu commandApdu=" + Hex.toHexString(commandApdu));
    Toast.makeText(getApplicationContext(), Hex.toHexString(commandApdu), Toast.LENGTH_SHORT).show();
    String MF_NAME = "1PAY.SYS.DDF01";
    byte[] selectMF = Hex.hexToBytes("00A404000E" + Hex.toHexString(PbocCmd.MF_Name) + "00");
    Log.d("cyb", "processCommandApdu selectMF=" + Hex.toHexString(selectMF));
    if(Arrays.equals(commandApdu, selectMF)){ // 选择MF
        ret = Hex.hexToBytes("6F15840E315041592E5359532E4444463031A5038801019000");
    }else if(Arrays.equals(commandApdu, Hex.hexToBytes("00A40000023F0100"))){ // 选择应用
        ret = Hex.hexToBytes("6F088400A5049F0801029000");
    }else if(Arrays.equals(commandApdu, Hex.hexToBytes("00A4000002000400"))){ // 选择文件
        ret = Hex.hexToBytes("9000");
    }else if(Arrays.equals(commandApdu, Hex.hexToBytes("00B0000000"))){ // 读文件
        ret = Hex.hexToBytes("4F545142475535394352555245304D369000");
    }
    Log.d("cyb", "processCommandApdu ret=" + Hex.toHexString(ret));
    return ret;
}

第二步

在res/xml 文件夹新建aid_list.xml

<?xml version="1.0" encoding="utf-8"?>
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/service_name"
    android:requireDeviceUnlock="false">

    <aid-group android:description="@string/card_title" android:category="other">
        <!--应用名称 1PAY.SYS.DDF01 对应的二进制-->
        <aid-filter android:name="315041592E5359532E4444463031"/>
    </aid-group>

</host-apdu-service>

第三步

在AndroidManifest.xml中配置Service

<uses-permission android:name="android.permission.NFC" />

<uses-feature
    android:name="android.hardware.nfc"
    android:required="true" />
<uses-feature
    android:name="android.hardware.nfc.hce"
    android:required="true" />
    
    
    <!-- Service for handling communication with NFC terminal. -->
    <service
        android:name=".CardEmulatorService"
        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>

读卡器代码

println("++++++++++++++ start ++++++++++++++++");
println("开始读文件...");
isoDep.connect();
Log.d("cyb", "Hex.toHexString(PbocCmd.MF_Name)=" + Hex.toHexString(PbocCmd.MF_Name));
//                byte[] select_mf = PbocCmd.selectByName(isoDep, PbocCmd.MF_Name);
byte[] select_mf = PbocCmd.selectByName(isoDep, PbocCmd.MF_Name);
println("选择MF返回值=" + Hex.toHexString(select_mf));
if (IsoDepUtils.isNoError(select_mf)) {
    // 选择应用
    byte[] appId = {0x3F, 0x01};
    byte[] response = PbocCmd.selectById(isoDep, appId);
    if (IsoDepUtils.isNoError(response)) {
        println("选择文件=" + Hex.toHexString(appId));
        println("选择文件返回值=" + Hex.toHexString(response));
        println("卡文件名称=" + new SelectResult(response).getName());

        byte[] fileId = {0x00, 0x04};
        // 选择文件
        byte[] response_f = PbocCmd.selectById(isoDep, fileId);
        if (IsoDepUtils.isNoError(response_f)) {
            println("选择文件=" + Hex.toHexString(fileId));
            println("选择文件返回值=" + Hex.toHexString(response_f));
            println("卡文件名称=" + new SelectResult(response_f).getName());

            byte[] read = PbocCmd.readBinary(isoDep);
            if(IsoDepUtils.isNoError(read)){
                println(Hex.toHexString(read));
                println(new String(read, "utf-8"));
            }
        }
    }
}
println("++++++++++++++ end ++++++++++++++++\n\n\n\n\n");
isoDep.close();
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值