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

NFC写标签APP优化:实现点击按钮后等待NFC标签并写入

解决方案:实现点击按钮后等待NFC标签并自动写入

核心思路

不要用循环轮询检测标签,这会持续占用CPU资源导致APP卡顿。正确的做法是利用Android的前台NFC调度系统,让APP在点击按钮后成为NFC事件的优先接收者,同时配合超时定时器,超时后自动恢复正常状态。

具体实现步骤

  1. 初始化NFC调度所需的PendingIntent、IntentFilter和标签技术类型,以及超时控制的定时器。
  2. 点击按钮时标记APP进入「等待写入」状态,启动前台NFC调度和超时定时器。
  3. 系统检测到NFC标签时,在onNewIntent回调中捕获标签,执行写入操作后关闭调度并重置状态。
  4. 超时后自动关闭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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 05:22:34