如何通过NFC在两台设备间传输字符串?技术求助
Android NFC 字符串传输实现方案
核心原理
Android NFC传输小字符串无需依赖蓝牙,直接使用**NDEF(NFC Data Exchange Format)**标准即可,这是NFC论坛定义的通用数据格式,Android原生支持。
1. 配置权限
在AndroidManifest.xml中添加NFC相关权限和硬件声明:
<uses-permission android:name="android.permission.NFC" /> <uses-feature android:name="android.hardware.nfc" android:required="true" />
2. 发送端实现
通过NfcAdapter的回调创建并推送NDEF消息:
public class SenderActivity extends AppCompatActivity implements NfcAdapter.CreateNdefMessageCallback, NfcAdapter.OnNdefPushCompleteCallback { private NfcAdapter mNfcAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sender); mNfcAdapter = NfcAdapter.getDefaultAdapter(this); } @Override protected void onResume() { super.onResume(); if (mNfcAdapter != null) { // 设置NDEF消息创建回调 mNfcAdapter.setNdefPushMessageCallback(this, this); // 设置推送完成回调(可选) mNfcAdapter.setOnNdefPushCompleteCallback(this, this); } } // 生成要发送的NDEF消息 @Override public NdefMessage createNdefMessage(NfcEvent event) { // 替换为你要传输的字符串 String content = "Hello NFC!"; // 创建文本类型的NDEF记录 NdefRecord textRecord = NdefRecord.createTextRecord("zh", content); return new NdefMessage(new NdefRecord[]{textRecord}); } // 推送完成后的UI提示(可选) @Override public void onNdefPushComplete(NfcEvent event) { runOnUiThread(() -> { Toast.makeText(this, "字符串已发送", Toast.LENGTH_SHORT).show(); }); } }
3. 接收端实现
通过前台调度拦截NFC意图,解析NDEF消息获取字符串:
public class ReceiverActivity extends AppCompatActivity { private NfcAdapter mNfcAdapter; private PendingIntent mPendingIntent; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_receiver); mNfcAdapter = NfcAdapter.getDefaultAdapter(this); // 创建用于接收NFC事件的PendingIntent mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE); } @Override protected void onResume() { super.onResume(); if (mNfcAdapter != null) { // 拦截text/plain类型的NDEF消息 IntentFilter ndefFilter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED); try { ndefFilter.addDataType("text/plain"); } catch (IntentFilter.MalformedMimeTypeException e) { throw new RuntimeException("Invalid MIME type", e); } IntentFilter[] filters = new IntentFilter[]{ndefFilter}; // 启用前台调度,确保当前Activity优先处理NFC事件 mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, filters, null); } } @Override protected void onPause() { super.onPause(); if (mNfcAdapter != null) { mNfcAdapter.disableForegroundDispatch(this); } } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); handleNfcIntent(intent); } private void handleNfcIntent(Intent intent) { if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) { Parcelable[] rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); if (rawMessages != null && rawMessages.length > 0) { NdefMessage ndefMessage = (NdefMessage) rawMessages[0]; NdefRecord record = ndefMessage.getRecords()[0]; try { // 解析文本记录:第一个字节是语言编码长度,跳过之后取UTF-8内容 String receivedText = new String(record.getPayload(), 1, record.getPayload().length - 1, StandardCharsets.UTF_8); // 处理接收到的字符串,比如显示在UI上 Toast.makeText(this, "收到内容: " + receivedText, Toast.LENGTH_LONG).show(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } } } }
关键注意事项
- 两台设备必须开启NFC并处于屏幕解锁状态
- 传输时需将设备NFC感应区域贴近(通常在背部,距离不超过5厘米)
- 单条NDEF消息容量有限(约1KB),过长字符串需拆分记录
- 官方文档提及的蓝牙文件传输是针对大文件场景,小字符串用NFC NDEF完全独立实现,无需蓝牙
内容的提问来源于stack exchange,提问作者RR_Pradhan
相关产品推荐
相关产品推荐

