You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android 6+设备HCE服务BIND_NFC_SERVICE权限授权失败求助

解决Android 6.0+ HCE应用权限被拒(返回6999)的问题

兄弟,我一看你的问题就知道踩了Android权限管控的坑——BIND_NFC_SERVICE这个权限根本不是给普通第三方HCE应用用的!先给你拆解清楚问题根源,再给你一步步的解决方案:

问题核心:你误解了HCE所需的权限

Android 6.0+对系统特权权限的管控变得极严,BIND_NFC_SERVICE属于signature|privileged级别的权限:

  • 要么你的应用用系统签名打包,
  • 要么得把应用放到/system/priv-app目录下,
    普通第三方应用哪怕Root后手动授予,重启后系统也会自动收回这个权限,因为它本来就不是给咱们普通开发者用的。

更关键的是:开发HCE应用根本不需要这个权限!你大概率是误加了这个权限,反而导致系统拒绝你的NFC请求,返回6999状态码。

正确的HCE应用配置步骤

1. 修正AndroidManifest.xml配置

把错误的BIND_NFC_SERVICE权限删掉,换成HCE应用真正需要的配置:

<!-- 基础NFC权限 -->
<uses-permission android:name="android.permission.NFC" />
<!-- 声明设备必须支持HCE -->
<uses-feature android:name="android.hardware.nfc.hce" android:required="true" />

<application ...>
    <!-- HCE服务核心配置 -->
    <service
        android:name=".YourHostApduService" <!-- 替换成你的HCE服务类名 -->
        android:exported="true"
        <!-- 这里用HOST_APDU_SERVICE权限,而不是BIND_NFC_SERVICE -->
        android:permission="android.permission.HOST_APDU_SERVICE">
        <intent-filter>
            <!-- HCE服务的标准Action -->
            <action android:name="android.nfc.cardemulation.action.HOST_APDU_SERVICE" />
        </intent-filter>
        <!-- 指向HCE服务的AID配置文件 -->
        <meta-data
            android:name="android.nfc.cardemulation.host_apdu_service"
            android:resource="@xml/apduservice" />
    </service>
</application>

2. 配置AID列表(res/xml/apduservice.xml)

这个文件用来定义你的HCE应用响应的AID,必须和外部设备发送的SELECT AID命令匹配:

<?xml version="1.0" encoding="utf-8"?>
<host-apdu-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/hce_service_desc"
    android:requireDeviceUnlock="false"> <!-- 是否需要解锁设备才能响应 -->
    <aid-group android:description="@string/aid_group_desc"
        android:category="other"> <!-- category根据你的场景选,比如"payment"是支付类 -->
        <!-- 替换成你实际使用的AID,多个AID可以加多个<aid-filter> -->
        <aid-filter android:name="F0010203040506" />
    </aid-group>
</host-apdu-service>

3. 检查你的HCE服务类实现

确保你的服务类继承自HostApduService,并且正确重写核心方法:

public class YourHostApduService extends HostApduService {
    private static final String SELECT_AID_APDU = "00A4040007F001020304050600";

    @Override
    public byte[] processCommandApdu(byte[] apdu, Bundle extras) {
        String apduHex = Hex.encodeHexString(apdu);
        if (SELECT_AID_APDU.equals(apduHex)) {
            // 返回成功响应,比如9000
            return Hex.decodeHex("9000".toCharArray());
        } else {
            // 其他命令的处理逻辑,这里示例返回"文件未找到"
            return Hex.decodeHex("6A82".toCharArray());
        }
    }

    @Override
    public void onDeactivated(int reason) {
        // 服务被停用的回调,比如NFC连接断开时的清理逻辑
    }
}

调试与验证步骤

  1. 检查系统设置:确保设备NFC已开启,并且你的HCE应用在系统NFC设置中被选中(部分设备需要在“默认付款应用”里切换到你的应用)。
  2. Logcat排查:过滤关键词HostApduServiceNFC,查看有没有服务注册失败、AID不匹配的日志。
  3. 验证APDU命令:确保外部设备发送的SELECT AID命令和你配置的AID完全一致(注意大小写、长度)。

关于Root设备的额外说明

如果你的场景确实需要系统级NFC权限(99%的普通HCE应用不需要),那必须:

  1. 把应用安装到/system/priv-app目录下,
  2. 用对应设备的系统签名打包应用,
    否则重启后权限一定会被系统回收,这是Android 6.0+的安全机制决定的。

内容的提问来源于stack exchange,提问作者engineer0815

火山引擎 最新活动