NFC写标签APP优化:实现点击按钮后等待NFC标签并写入
解决方案:实现点击按钮后等待NFC标签并自动写入
核心思路
不要用循环轮询检测标签,这会持续占用CPU资源导致APP卡顿。正确的做法是利用Android的前台NFC调度系统,让APP在点击按钮后成为NFC事件的优先接收者,同时配合超时定时器,超时后自动恢复正常状态。
具体实现步骤
- 初始化NFC调度所需的
PendingIntent、IntentFilter和标签技术类型,以及超时控制的定时器。 - 点击按钮时标记APP进入「等待写入」状态,启动前台NFC调度和超时定时器。
- 系统检测到NFC标签时,在
onNewIntent回调中捕获标签,执行写入操作后关闭调度并重置状态。 - 超时后自动关闭NFC调度,提示用户操作超时并重置状态。
代码示例
首先在Activity中添加成员变量:
private PendingIntent nfcPendingIntent; private IntentFilter[] nfcIntentFilters; private String[][] nfcTechLists; private boolean isWaitingForTag = false; private CountDownTimer writeTimeoutTimer; private static final int WRITE_TIMEOUT_SECONDS = 5; // 设置等待时长为5秒
在onCreate方法中初始化NFC相关配置:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化NFC PendingIntent,确保APP能捕获NFC事件 nfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE); // 配置IntentFilter,过滤NFC标签发现事件 IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED); try { tagDetected.addDataType("*/*"); } catch (IntentFilter.MalformedMimeTypeException e) { e.printStackTrace(); } nfcIntentFilters = new IntentFilter[]{tagDetected}; // 设置支持的NFC标签技术(根据你要写入的标签类型调整,示例为Ndef) nfcTechLists = new String[][]{new String[]{Ndef.class.getName()}}; }
处理写入按钮的点击事件:
yourWriteButton.setOnClickListener(v -> { NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); if (nfcAdapter == null) { Toast.makeText(this, getString(R.string.no_nfc), Toast.LENGTH_LONG).show(); return; } if (!nfcAdapter.isEnabled()) { Toast.makeText(this, getString(R.string.enable_nfc), Toast.LENGTH_LONG).show(); return; } // 标记进入等待标签状态 isWaitingForTag = true; Toast.makeText(this, getString(R.string.place_tag), Toast.LENGTH_LONG).show(); // 启动前台NFC调度,让APP优先接收NFC事件 nfcAdapter.enableForegroundDispatch(this, nfcPendingIntent, nfcIntentFilters, nfcTechLists); // 启动超时定时器 writeTimeoutTimer = new CountDownTimer(WRITE_TIMEOUT_SECONDS * 1000, 1000) { @Override public void onTick(long millisUntilFinished) { // 可选:显示倒计时提示 } @Override public void onFinish() { // 超时后清理状态 isWaitingForTag = false; nfcAdapter.disableForegroundDispatch(MainActivity.this); Toast.makeText(MainActivity.this, getString(R.string.timeout), Toast.LENGTH_LONG).show(); } }.start(); });
重写onNewIntent处理NFC标签检测:
@Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); if (isWaitingForTag && NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) { Tag myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); if (myTag != null) { // 取消超时定时器 writeTimeoutTimer.cancel(); // 执行写入操作 performWriteOperation(myTag); // 关闭前台调度,重置状态 NfcAdapter.getDefaultAdapter(this).disableForegroundDispatch(this); isWaitingForTag = false; } } }
实现写入操作方法(复用原有写入逻辑):
private void performWriteOperation(Tag myTag) { try { String content = title + edit_message.getText().toString(); write(content, myTag); Toast.makeText(this, getString(R.string.saved), Toast.LENGTH_LONG).show(); } catch (IOException e) { Toast.makeText(this, getString(R.string.failed), Toast.LENGTH_LONG).show(); e.printStackTrace(); } catch (FormatException e) { Toast.makeText(this, getString(R.string.failed), Toast.LENGTH_LONG).show(); e.printStackTrace(); } }
Activity销毁时清理资源:
@Override protected void onDestroy() { super.onDestroy(); if (writeTimeoutTimer != null) { writeTimeoutTimer.cancel(); } NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); if (nfcAdapter != null && isWaitingForTag) { nfcAdapter.disableForegroundDispatch(this); } }
注意事项
- 确保Manifest中添加NFC权限:
<uses-permission android:name="android.permission.NFC" /> - Android 10及以上版本需确保APP处于前台状态,才能正常捕获NFC事件
- 根据实际写入的标签类型(如MifareClassic),调整
nfcTechLists中的技术类型
内容的提问来源于stack exchange,提问作者Jakub Osadczuk
相关产品推荐
相关产品推荐

