如何在安卓系统上使用QtNfc获取Mifare 1k卡片的SAK值
解决方案
1 修复现有JNI代码的编译报错
你遇到的未定义引用问题由两个常见原因导致:
- 未在项目
.pro配置文件中添加androidextras模块依赖,需要新增一行配置:
QT += androidextras
- Qt 5.12的
QAndroidJniObject模板版callMethod<>对短整型的特化支持不完善,不要使用模板写法,直接调用封装好的callShortMethod方法即可。
修改SAK读取逻辑,同时补充NfcA对象的连接、释放操作避免读取失败:
#define NFCATECHNOLOGY QStringLiteral("android.nfc.tech.NfcA") void myfunction::nfcManager{ QAndroidJniObject nfca = getAndroidTech(NFCATECHNOLOGY); if(nfca.isValid()){ // 先连接卡片 nfca.callMethod<void>("connect"); if(nfca.callMethod<jboolean>("isConnected")){ // 读取SAK jshort sakS = nfca.callShortMethod("getSak"); quint16 sak = (quint16)sakS; qDebug() << "读取到的SAK值:" << Qt::hex << sak; } // 释放连接 nfca.callMethod<void>("close"); } } QAndroidJniObject nfcManager::getAndroidTech(const QString &tech) { QString techClass(tech); techClass.replace(QLatin1Char('.'), QLatin1Char('/')); QAndroidJniObject ret = QAndroidJniObject::callStaticObjectMethod("QtNfc","getStartIntent", "()Landroid/content/Intent;"); QAndroidJniObject m_intent = ret; QAndroidJniObject extraTag = QAndroidJniObject::getStaticObjectField("android/nfc/NfcAdapter", "EXTRA_TAG", "Ljava/lang/String;"); QAndroidJniObject tag = m_intent.callObjectMethod("getParcelableExtra", "(Ljava/lang/String;)Landroid/os/Parcelable;", extraTag.object<jstring>()); Q_ASSERT_X(tag.isValid(), "getTagTechnology", "could not get Tag object"); const QString sig = QString::fromUtf8("(Landroid/nfc/Tag;)L%1;"); QAndroidJniObject tagTech = QAndroidJniObject::callStaticObjectMethod(techClass.toUtf8().constData(), "get", sig.arg(techClass).toUtf8().constData(), tag.object<jobject>()); return tagTech; }
2 额外注意事项
- 只有符合NfcA技术标准的Mifare卡才会返回SAK,其他类型NFC卡没有该参数,读取前可以先判断卡片支持的技术列表
- Android 6.0及以上版本需要动态申请位置权限才能正常读取NFC卡参数,需要提前完成权限申请逻辑
内容的提问来源于stack exchange,提问作者Cristian Negru
相关产品推荐
相关产品推荐

