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

Android Java项目实现点击按钮启动NFC扫描功能求助

实现点击按钮触发NFC标签扫描

1. 确认Manifest基础配置

确保AndroidManifest.xml中已添加NFC相关权限与声明:

<!-- NFC权限 -->
<uses-permission android:name="android.permission.NFC" />
<!-- 声明设备依赖NFC硬件 -->
<uses-feature android:name="android.hardware.nfc" android:required="true" />

<!-- 目标Activity添加NFC事件过滤(已配置可忽略) -->
<activity android:name=".YourNfcActivity">
    <intent-filter>
        <action android:name="android.nfc.action.TAG_DISCOVERED" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

2. 布局添加扫描触发按钮

在Activity布局文件(如activity_main.xml)中添加按钮:

<Button
    android:id="@+id/btn_start_nfc_scan"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="启动NFC扫描" />

3. Java核心逻辑实现

通过NfcAdapter的前台调度方法,控制扫描的开启/关闭,仅在按钮点击时激活扫描:

import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.content.IntentFilter;
import android.app.PendingIntent;

public class YourNfcActivity extends AppCompatActivity {
    private NfcAdapter nfcAdapter;
    private Button btnStartScan;
    private boolean isScanning = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnStartScan = findViewById(R.id.btn_start_nfc_scan);
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);

        // 检查设备NFC支持情况
        if (nfcAdapter == null) {
            Toast.makeText(this, "设备不支持NFC", Toast.LENGTH_SHORT).show();
            btnStartScan.setEnabled(false);
            return;
        }

        // 按钮点击切换扫描状态
        btnStartScan.setOnClickListener(v -> {
            if (!isScanning) {
                startNfcScan();
                btnStartScan.setText("停止NFC扫描");
                isScanning = true;
                Toast.makeText(YourNfcActivity.this, "已启动扫描,请靠近NFC标签", Toast.LENGTH_SHORT).show();
            } else {
                stopNfcScan();
                btnStartScan.setText("启动NFC扫描");
                isScanning = false;
                Toast.makeText(YourNfcActivity.this, "已停止扫描", Toast.LENGTH_SHORT).show();
            }
        });
    }

    // 启动NFC前台调度(优先让当前Activity接收NFC事件)
    private void startNfcScan() {
        Intent nfcIntent = new Intent(this, YourNfcActivity.class);
        nfcIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, nfcIntent, PendingIntent.FLAG_MUTABLE);

        // 配置过滤的NFC技术类型,这里以NDEF为例,可按需调整
        IntentFilter[] intentFilters = new IntentFilter[]{};
        String[][] techLists = new String[][]{new String[]{Ndef.class.getName()}};

        nfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFilters, techLists);
    }

    // 停止NFC前台调度
    private void stopNfcScan() {
        if (nfcAdapter != null) {
            nfcAdapter.disableForegroundDispatch(this);
        }
    }

    // 处理扫描到的NFC标签
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (isScanning) {
            String action = intent.getAction();
            if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
                Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
                if (tag != null) {
                    handleNfcTag(tag);
                    // 可选:扫描到标签后自动停止扫描
                    stopNfcScan();
                    btnStartScan.setText("启动NFC扫描");
                    isScanning = false;
                }
            }
        }
    }

    // 自定义标签处理逻辑(示例:读取NDEF内容)
    private void handleNfcTag(Tag tag) {
        Ndef ndef = Ndef.get(tag);
        if (ndef != null) {
            try {
                ndef.connect();
                byte[] payload = ndef.getNdefMessage().getRecords()[0].getPayload();
                String content = new String(payload, 1, payload.length - 1, "UTF-8");
                Toast.makeText(this, "扫描到内容:" + content, Toast.LENGTH_LONG).show();
                ndef.close();
            } catch (Exception e) {
                Toast.makeText(this, "读取标签失败", Toast.LENGTH_SHORT).show();
                e.printStackTrace();
            }
        } else {
            Toast.makeText(this, "不支持的标签类型", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        // 页面暂停时自动停止扫描,避免后台占用资源
        if (isScanning) {
            stopNfcScan();
            isScanning = false;
            btnStartScan.setText("启动NFC扫描");
        }
    }
}

关键说明

  • 前台调度控制:核心通过enableForegroundDispatch和disableForegroundDispatch方法,仅在按钮点击时激活扫描,不用时关闭,避免系统默认的自动扫描行为。
  • 状态标记isScanning:跟踪当前扫描状态,实现按钮文本与逻辑的切换。
  • 生命周期处理:在onPause中关闭扫描,防止Activity后台运行时仍占用NFC资源。

内容的提问来源于stack exchange,提问作者SenjaKids

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 04:45:30