You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Kotlin实现Android与iOS设备间NFC UID互读

Android端(Kotlin)实现NFC UID互读方案

一、权限与配置

首先在AndroidManifest.xml中添加必要权限和NFC相关配置:

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

<!-- 处理NFC事件的Activity配置 -->
<activity android:name=".MainActivity">
    <intent-filter>
        <action android:name="android.nfc.action.NDEF_DISCOVERED" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:mimeType="text/plain" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.nfc.action.TECH_DISCOVERED" />
    </intent-filter>
    <meta-data 
        android:name="android.nfc.action.TECH_DISCOVERED"
        android:resource="@xml/nfc_tech_filter" />
</activity>

在res/xml目录下创建nfc_tech_filter.xml,指定支持的NFC技术类型:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.Ndef</tech>
        <tech>android.nfc.tech.NdefFormatable</tech>
    </tech-list>
</resources>

二、Kotlin代码实现

1. 初始化NFC组件

在Activity中完成NFC适配器初始化,检查设备NFC支持状态:

import android.nfc.NfcAdapter
import android.nfc.NfcManager
import android.nfc.Tag
import android.nfc.tech.Ndef
import android.nfc.tech.NdefFormatable
import android.content.Intent
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    private var nfcAdapter: NfcAdapter? = null
    private lateinit var deviceUidTv: TextView
    private lateinit var receivedUidTv: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        deviceUidTv = findViewById(R.id.tv_device_uid)
        receivedUidTv = findViewById(R.id.tv_received_uid)

        // 检查设备NFC支持情况
        val nfcManager = getSystemService(NFC_SERVICE) as NfcManager
        nfcAdapter = nfcManager.defaultAdapter
        when {
            nfcAdapter == null -> deviceUidTv.text = "设备不支持NFC"
            !nfcAdapter!!.isEnabled -> deviceUidTv.text = "请先开启NFC"
        }
    }
}

2. 前台调度与Intent处理

在Activity的生命周期中管理前台调度,确保App优先捕获NFC事件:

override fun onResume() {
    super.onResume()
    nfcAdapter?.let { adapter ->
        val pendingIntent = PendingIntent.getActivity(
            this,
            0,
            intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
            PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        )
        adapter.enableForegroundDispatch(this, pendingIntent, null, null)
    }
}

override fun onPause() {
    super.onPause()
    nfcAdapter?.disableForegroundDispatch(this)
}

override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    intent?.let { handleNfcIntent(it) }
}

3. 读取对方UID并发送自身UID

实现核心逻辑,处理NFC标签的读取与写入:

private fun handleNfcIntent(intent: Intent) {
    val tag = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG) ?: return

    // 获取并显示当前设备的NFC UID
    val deviceUid = tag.id?.joinToString(separator = ":") { String.format("%02X", it) } ?: "无法获取UID"
    deviceUidTv.text = "当前设备UID: $deviceUid"

    // 读取对方设备发送的UID
    readNdefMessage(tag)?.let { receivedUid ->
        receivedUidTv.text = "收到对方UID: $receivedUid"
    }

    // 将自身UID写入对方设备(支持NDEF的设备)
    writeNdefMessage(tag, deviceUid)
}

private fun readNdefMessage(tag: Tag): String? {
    return try {
        val ndef = Ndef.get(tag)
        ndef.connect()
        val payload = ndef.ndefMessage.records[0].payload
        // 解析UTF-8格式的NDEF数据
        String(payload, 1, payload.size - 1, Charsets.UTF_8)
    } catch (e: Exception) {
        null
    } finally {
        Ndef.get(tag)?.close()
    }
}

private fun writeNdefMessage(tag: Tag, uid: String) {
    try {
        val ndef = Ndef.get(tag)
        if (ndef != null) {
            ndef.connect()
            if (!ndef.isWritable) return
            // 创建文本类型的NDEF记录
            val record = NdefRecord.createTextRecord("en", uid)
            val message = NdefMessage(arrayOf(record))
            ndef.writeNdefMessage(message)
        } else {
            // 对未格式化的标签进行格式化并写入
            val formatable = NdefFormatable.get(tag)
            formatable?.let {
                it.connect()
                it.format(NdefMessage(arrayOf(NdefRecord.createTextRecord("en", uid))))
                it.close()
            }
        }
    } catch (e: Exception) {
        e.printStackTrace()
    } finally {
        Ndef.get(tag)?.close()
        NdefFormatable.get(tag)?.close()
    }
}

三、iOS端配合要点

iOS端需使用CoreNFC框架完成对应逻辑:

  • 在Info.plist中添加NFCReaderUsageDescription权限描述
  • 使用NFCNDEFReaderSession读取Android设备发送的NDEF消息
  • 使用NFCNDEFWriterSession将自身UID写入Android设备

关键注意事项

  • 部分Android机型默认开启NFC UID随机化,需在系统设置中关闭“NFC安全”类选项才能获取固定UID
  • iOS仅在13+版本支持NFC读取,14+版本支持NDEF写入
  • 双方设备需保持近距离接触,且均开启NFC功能
  • 仅App在前台运行时能正常处理NFC事件,后台NFC存在功能限制

内容的提问来源于stack exchange,提问作者Sparx it solutions

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 06:40:20