Android NFC读和写踩坑版

环境  android studio 2022   sdk 33

 刚刚开始我的代码是这样的,结果给我的 提示 接收到的Intent不是由NFC触发的  我很蒙圈为什么然后我见过我调试 我发现 我改 里面的那个 

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "NfcWriteActivity";
    private NfcAdapter nfcAdapter;
    private TextView mTvName;
    public static IntentFilter[] mIntentFilter = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTvName = findViewById(R.id.textView);
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (nfcAdapter == null) {
            Toast.makeText(this, "不支持NFC功能", Toast.LENGTH_SHORT).show();
            return;
        }

        if (!nfcAdapter.isEnabled()) {
            Toast.makeText(this, "请打开NFC功能", Toast.LENGTH_SHORT).show();
            Intent inten = new Intent(Settings.ACTION_NFC_SETTINGS);
            // 根据包名打开对应的设置界面
            startActivity(inten);
            return;
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        try {
            IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
            IntentFilter filter3 = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
            IntentFilter filter2 = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
            String[][] techList = new String[][]{new String[]{NfcA.class.getName()}, {Ndef.class.getName()}, {MifareUltralight.class.getName()}};
            mIntentFilter = new IntentFilter[]{filter, filter2, filter3};
            PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 10, new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
            nfcAdapter.enableForegroundDispatch(this, pendingIntent, mIntentFilter, techList);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        try {
            nfcAdapter.disableForegroundDispatch(MainActivity.this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);

        String action = intent.getAction();
        if (!NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) &&
                !NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) &&
                !NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
            Log.e(TAG, "");
            Toast.makeText(this, "接收到的Intent不是由NFC触发的", Toast.LENGTH_SHORT).show();
            return;
        }

        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
            Parcelable[] rawMessages =
                    intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            if (rawMessages != null) {
                NdefMessage[] messages = new NdefMessage[rawMessages.length];
                for (int i = 0; i < rawMessages.length; i++) {
                    messages[i] = (NdefMessage) rawMessages[i];
                }
                // 处理 messages 数组。

                Toast.makeText(this, "识别出是 Ndef类型", Toast.LENGTH_SHORT).show();
            }else {
                Toast.makeText(this, "识别出不是 Ndef类型", Toast.LENGTH_SHORT).show();
            }
        }

        Log.e(TAG, "去未" + intent);
        Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        MifareUltralight mifareUltralight = MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
        if (mifareUltralight != null) {
            Toast.makeText(this, "识别出是 MifareUltralight类型", Toast.LENGTH_SHORT).show();
        }
        if (detectedTag == null) {
            Toast.makeText(this, "未检测到NFC", Toast.LENGTH_SHORT).show();
            return;
        }

        // Check if the tag supports NDEF
        Ndef ndef = Ndef.get(detectedTag);
        if (ndef == null) {
            Toast.makeText(this, "不支持 NDEF", Toast.LENGTH_SHORT).show();
            Log.e(TAG, "去不支持 NDEF");
            return;
        }
        
        try {
            ndef.connect();
            NdefMessage message = createNdefMessage();
            ndef.writeNdefMessage(message);
            ndef.close();
            Toast.makeText(this, "已成功写入 NFC 消息", Toast.LENGTH_SHORT).show();
            Log.i(TAG, "去已成功写入 NFC 消息");
        } catch (IOException | IllegalStateException | FormatException e) {
            Log.e(TAG, "Failed to write NDEF message", e);
        }


    }

    private NdefMessage createNdefMessage() {
        byte[] payload = "Hello NFC".getBytes(StandardCharsets.UTF_8);
        NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload);
        return new NdefMessage(new NdefRecord[]{record});
    }
}
            PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 10, new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

里面的  requestCode 也就是第二个参数 我改成0他就闪屏就是 屏幕来回切换  我就继续还原为10 

然后我就去看看我的  AndroidManifest.xml  是不是有问题

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-feature
        android:name="android.hardware.nfc"
        android:required="true" />

    <uses-permission android:name="android.permission.NFC" />



    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyNFC"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <intent-filter>
                <action android:name="android.nfc.action.TAG_DISCOVERED" />
                <action android:name="android.nfc.action.NDEF_DISCOVERED" />
                <action android:name="android.nfc.action.TECH_DISCOVERED" />

                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="*/*" />
            </intent-filter>

            <meta-data
                android:name="android.nfc.action.TECH_DISCOVERED"
                android:resource="@xml/nfc_tech_filter" />
        </activity>

    </application>

</manifest>

发现没问题啊都配了,为什么我一扫上nfc就识别不出来 ,然后就去百度查看都是一些远古的东西

后面发现一大佬的写的

[android nfc] onNewIntent 中 无法获取 tag, 或者 intent.extras 为空, 或者 intent.action 为空_android 12 getintent().getaction()一直为空-CSDN博客


跟我的情况一样 因为我断点调试发现  action 为null

String action = intent.getAction();

我的问题就只修改了 那一句 把原来的 

            PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 10, new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);

换成了

PendingIntent.getActivity(this, 0, 
                new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
                PendingIntent.FLAG_MUTABLE)

具体问题就是

    FLAG_IMMUTABLE表示PendingIntent中的Intent不能被将Intent传递给PendingIntent.send()的其他应用程序修改。应用总是可以使用FLAG_UPDATE_CURRENT来修改它自己的PendingIntent
    在Android 12之前,默认情况下,不带此标志创建的PendingIntent是可变的。
    在Android 6 (API 23) 之前的Android版本上,PendingIntent总是可变的。

    FLAG_MUTABLE:表示PendingIntent中的Intent应允许应用程序通过合并PendingIntent.send()的Intent参数值来更新其内容。
    始终填写任何可变的PendingIntent的包装Intent的ComponentName。不这样做可能会导致安全漏洞!
    此标志是在Android 12中添加的。在Android 12之前,在没有FLAG_IMMUTABLE标志的情况下创建的任何PendingIntent都是隐式可变的

我就说为什么一直识别不出来 我换成这个就可以识别出来了 

完整版  就只有 

MainActivity 有改动其他的没有
package com.go.mynfc;

import android.Manifest;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.MifareUltralight;
import android.nfc.tech.Ndef;
import android.nfc.tech.NfcA;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.Settings;
import android.util.Log;

import android.widget.TextView;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.io.IOException;

import java.nio.charset.StandardCharsets;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "NfcWriteActivity";
    private NfcAdapter nfcAdapter;
    private TextView mTvName;
    public static IntentFilter[] mIntentFilter = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTvName = findViewById(R.id.textView);
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (nfcAdapter == null) {
            Toast.makeText(this, "不支持NFC功能", Toast.LENGTH_SHORT).show();
            return;
        }

        if (!nfcAdapter.isEnabled()) {
            Toast.makeText(this, "请打开NFC功能", Toast.LENGTH_SHORT).show();
            Intent inten = new Intent(Settings.ACTION_NFC_SETTINGS);
            // 根据包名打开对应的设置界面
            startActivity(inten);
            return;
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        try {

            IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
            IntentFilter filter3 = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
            IntentFilter filter2 = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
            String[][] techList = new String[][]{new String[]{NfcA.class.getName()}, {Ndef.class.getName()}, {MifareUltralight.class.getName()}};
            mIntentFilter = new IntentFilter[]{filter, filter2, filter3};
            PendingIntent pendingIntent = PendingIntent.getActivity(MainActivity.this, 10, new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE);
            nfcAdapter.enableForegroundDispatch(this, pendingIntent, mIntentFilter, techList);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
        try {
            nfcAdapter.disableForegroundDispatch(MainActivity.this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);

        String action = intent.getAction();
        if (!NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) &&
                !NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) &&
                !NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
            Log.e(TAG, "接收到的Intent不是由NFC触发的");
            return;
        }

        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
            Parcelable[] rawMessages =
                    intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            if (rawMessages != null) {
                NdefMessage[] messages = new NdefMessage[rawMessages.length];
                for (int i = 0; i < rawMessages.length; i++) {
                    messages[i] = (NdefMessage) rawMessages[i];
                }
                // 处理 messages 数组。

                Toast.makeText(this, "识别出是 Ndef类型", Toast.LENGTH_SHORT).show();
            }else {
                Toast.makeText(this, "识别出不是 Ndef类型", Toast.LENGTH_SHORT).show();
            }
        }

        Log.e(TAG, "去未" + intent);
        Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        MifareUltralight mifareUltralight = MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
        if (mifareUltralight != null) {
            Toast.makeText(this, "识别出是 MifareUltralight类型", Toast.LENGTH_SHORT).show();
        }
        if (detectedTag == null) {
            Toast.makeText(this, "未检测到NFC", Toast.LENGTH_SHORT).show();
            return;
        }

        // Check if the tag supports NDEF
        Ndef ndef = Ndef.get(detectedTag);
        if (ndef == null) {
            Toast.makeText(this, "不支持 NDEF", Toast.LENGTH_SHORT).show();
            Log.e(TAG, "去不支持 NDEF");
            return;
        }

        try {
            ndef.connect();
            NdefMessage message = createNdefMessage();
            ndef.writeNdefMessage(message);
            ndef.close();
            Toast.makeText(this, "已成功写入 NFC 消息", Toast.LENGTH_SHORT).show();
            Log.i(TAG, "去已成功写入 NFC 消息");
        } catch (IOException | IllegalStateException | FormatException e) {
            Log.e(TAG, "Failed to write NDEF message", e);
        }


    }

    private NdefMessage createNdefMessage() {
        byte[] payload = "Hello NFC".getBytes(StandardCharsets.UTF_8);
        NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload);
        return new NdefMessage(new NdefRecord[]{record});
    }
}

上面是写 读的话

    private static String ByteArrayToHexString(byte[] inarray) {
        int i, j, in;
        String[] hex = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
        String out = "";

        for (j = 0; j < inarray.length; ++j) {
            in = (int) inarray[j] & 0xff;
            i = (in >> 4) & 0x0f;
            out += hex[i];
            i = in & 0x0f;
            out += hex[i];
        }
        return out;
    }

把那个id传进入 转换一个就可以获取到 nfc的id

android.nfc.tech.NfcA: NFC Forum Type A 技术,适用于大多数被动标签和卡片,如ISO 14443A标准的设备。
android.nfc.tech.NfcB: NFC Forum Type B 技术,主要应用于某些非接触式智能卡,符合ISO 14443B标准。
android.nfc.tech.NfcF: NFC Forum FeliCa 技术,主要用于日本及部分亚洲地区,支持高速通信。
android.nfc.tech.NfcV: NFC Forum Type V 技术,专为高带宽要求设计,常用于公交票务和其他需要快速读取的应用场景,基于ISO 15693标准。
android.nfc.tech.IsoDep: ISO/IEC 14443-4 技术,允许设备执行基于ISO 7816-4协议的智能卡交互,常用于SIM卡或电子护照等。
android.nfc.tech.Ndef: NFC Data Exchange Format (NDEF) 技术,这是一种通用的数据交换格式,支持多种类型的数据存储和读取,如文本、URLs等。
android.nfc.tech.NdefFormatable: 表示一个可以被格式化为NDEF兼容标签的NFC标签。这用于创建新的NDEF消息。
android.nfc.tech.MifareClassic: MIFARE Classic 技术,一种广泛应用的存储卡技术,支持扇区和块级别的访问控制。
android.nfc.tech.MifareUltralight: MIFARE Ultralight 系列标签,为低成本、小容量应用设计,常用于一次性使用的票证或标签

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值