当前位置: 首页 > 知识库问答 >
问题:

我有一个问题写NFC标签在Android

常光明
2023-03-14

我正在开发一个应用程序,在Android Studio中编写NFC标签。我的代码:

    public class MainActivity extends AppCompatActivity {

    public static final String Error_dected = "No NFC Tag Detected";
    public static final String Write_Success = "Text Written Succesfully";
    public static final String Write_Error = "Error during writtin, Try again";
    NfcAdapter nfcAdapter;
    PendingIntent pendingIntent;
    IntentFilter writingTagFilters[];
    boolean writeMode;
    Tag myTag;
    Context context;


    EditText edit_message;
    TextView nfc_contents;
    Button ActivateButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        edit_message = (EditText) findViewById(R.id.edit_message);
        nfc_contents = (TextView) findViewById(R.id.nfc_content);
        ActivateButton = (Button) findViewById(R.id.ActivateButton);
        context = this;
        ActivateButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                String mensaje=edit_message.getText().toString();


               try {

                    if (myTag == null) {
                        Toast.makeText(context, Error_dected, Toast.LENGTH_LONG).show();
                    } else {

                        write("PlainText|" + edit_message.getText().toString(), myTag);
                        Toast.makeText(context, Write_Success, Toast.LENGTH_LONG).show();
                    }


                } catch (IOException e) {

                    Toast.makeText(context, Write_Error, Toast.LENGTH_LONG).show();
                    e.printStackTrace();
                } catch (FormatException e) {
                    Toast.makeText(context, Write_Error, Toast.LENGTH_LONG).show();
                    e.printStackTrace();
                }


            }

        });



        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (nfcAdapter == null) {
            Toast.makeText(this, "this device does not support NFC", Toast.LENGTH_LONG).show();

        }

        readfromIntent(getIntent());
        pendingIntent = pendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
        tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
        writingTagFilters = new IntentFilter[]{tagDetected};

    }



    public void readfromIntent(Intent intent) {
        String action = intent.getAction();
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
                || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
                || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
            Parcelable[] rawMsg = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            NdefMessage[] msgs = null;
            if (rawMsg != null) {
                msgs = new NdefMessage[rawMsg.length];
                for (int i = 0; i < rawMsg.length; i++) {
                    msgs[i] = (NdefMessage) rawMsg[i];
                }

                buildTagView(msgs);
            }
        }

    }

    private void buildTagView(NdefMessage[] msgs) {
        if (msgs == null || msgs.length == 0) return;

        String text = "";
        byte[] payload = msgs[0].getRecords()[0].getPayload();
        String textEncodgin = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16"; //Get the text encoding
        int languageCodeLength = payload[0] & 0063;
        try {
            text = new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncodgin);

        } catch (UnsupportedEncodingException e) {
            Log.e("UnsupportedEncoding", e.toString());
        }
        nfc_contents.setText("NFC Content: " + text);

    }

    private void write(String text, Tag tag) throws IOException, FormatException {
        NdefRecord[] records = {createRecord(text)};
        NdefMessage message = new NdefMessage(records);
        //Get an instance os Ndef for the tag
        Ndef ndef = Ndef.get(tag);

        //Enable I/0
        ndef.connect();
        //Write the message
        ndef.writeNdefMessage(message);
        //Clase de connection
        ndef.close();


    }

    private NdefRecord createRecord(String text) throws UnsupportedEncodingException {

    String lang ="en";
    byte[] textBytes=text.getBytes();
    byte[] langBytes=lang.getBytes("US-ASCII");
    int langLength=langBytes.length;
    int textLength=textBytes.length;
    byte[] payload =new byte[1+langLength+textLength];
    //set status byte (see NDEF spec for actual bits

        payload[0]= (byte) langLength;
        //copy langbytes and textbytes into payload

        System.arraycopy(langBytes,0,payload,1,langLength);
        System.arraycopy(textBytes,0,payload,1+langLength,textLength);

        NdefRecord recordNFC =new NdefRecord(NdefRecord.TNF_WELL_KNOWN,NdefRecord.RTD_TEXT,new byte[0],payload);

        return recordNFC;



    }

    @Override
    protected void onNewIntent(Intent intent)
    {
        super.onNewIntent(intent);
        setIntent(intent);
        readfromIntent(intent);
        if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()))
        {
            myTag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        }
    }
    @Override
    public void onPause()
    {
        super.onPause();
        WriteModeOff();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        WriteModeOn();
    }

    /********ENABLE WRITE*****/
    private void WriteModeOn()
    {
        writeMode=true;
        nfcAdapter.enableForegroundDispatch(this,pendingIntent,writingTagFilters,null);

    }

    /*******DISABLE WRITE*****/
    private void WriteModeOff()
    {
        writeMode=false;
        nfcAdapter.disableForegroundDispatch(this);
    }
}

当我运行它并试图写在一个NFC标签我总是得到myTag==空,所以我总是在这里:

if(myTag==null){Toast.makeText(context,Error_dected,Toast.LENGTH_LONG).show();

我在“android.Manifest”中修改了用户权限,知道发生了什么吗?非常感谢。

共有1个答案

楚骞尧
2023-03-14

任何NFC操作的唯一起点是当系统NFC应用程序给你一个Tag对象作为与它检测到的NFC Tag交互的起点。

有很多方法可以做到这一点,并且enableForground Dispatch是您已经在使用的一种方法,但是在现实生活中使用这种方法来处理NFC是非常不可靠的,并且会导致NFC标签上的大量写入错误和损坏的数据。

更好的方法是使用较新的APIenableReaderMode,在https://stackoverflow.com/a/64921434/2373819这也解释了为什么它更好。

但对于这两种API,当检测到标记并通知您标记已进入范围时,您需要完成与标记的所有交互(对于您正在使用的onNewIntent中的当前API)

因此,当用户单击ActivateButton时,处理此问题的一个简单方法是设置一个全局布尔值,以指示下次检测到标记时,您应该向其写入,而不是尝试从中读取(并且您还可以将要写入的字符串存储在全局字符串中)

下面是一些代码更改,让您有这样的想法,但这是一个简单的例子,因为它没有显示任何用户界面更改来提示用户将NFC卡带入范围,也没有涵盖您可能需要成功进行的任何重试写入NFC卡。

public class MainActivity extends AppCompatActivity {

    public static final String Error_dected = "No NFC Tag Detected";
    public static final String Write_Success = "Text Written Succesfully";
    public static final String Write_Error = "Error during writtin, Try again";
    NfcAdapter nfcAdapter;
    PendingIntent pendingIntent;
    IntentFilter writingTagFilters[];
    boolean writeMode;
    Tag myTag;
    Context context;


    EditText edit_message;
    TextView nfc_contents;
    Button ActivateButton;

    //New code below
    boolean someThingToWrite;
    String stringToWrite;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        edit_message = (EditText) findViewById(R.id.edit_message);
        nfc_contents = (TextView) findViewById(R.id.nfc_content);
        ActivateButton = (Button) findViewById(R.id.ActivateButton);
        context = this;
        ActivateButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                //Changed Code
                stringToWrite = edit_message.getText().toString();
                someThingToWrite = true;
        });



        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (nfcAdapter == null) {
            Toast.makeText(this, "this device does not support NFC", Toast.LENGTH_LONG).show();

        }

        readfromIntent(getIntent());
        pendingIntent = pendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
        tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
        writingTagFilters = new IntentFilter[]{tagDetected};

    }



    public void readfromIntent(Intent intent) {
        String action = intent.getAction();
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
                || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
                || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
            Parcelable[] rawMsg = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            NdefMessage[] msgs = null;
            if (rawMsg != null) {
                msgs = new NdefMessage[rawMsg.length];
                for (int i = 0; i < rawMsg.length; i++) {
                    msgs[i] = (NdefMessage) rawMsg[i];
                }

                buildTagView(msgs);
            }
        }

    }

    private void buildTagView(NdefMessage[] msgs) {
        if (msgs == null || msgs.length == 0) return;

        String text = "";
        byte[] payload = msgs[0].getRecords()[0].getPayload();
        String textEncodgin = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16"; //Get the text encoding
        int languageCodeLength = payload[0] & 0063;
        try {
            text = new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncodgin);

        } catch (UnsupportedEncodingException e) {
            Log.e("UnsupportedEncoding", e.toString());
        }
        nfc_contents.setText("NFC Content: " + text);

    }

    private void write(String text, Tag tag) throws IOException, FormatException {
        NdefRecord[] records = {createRecord(text)};
        NdefMessage message = new NdefMessage(records);
        //Get an instance os Ndef for the tag
        Ndef ndef = Ndef.get(tag);

        //Enable I/0
        ndef.connect();
        //Write the message
        ndef.writeNdefMessage(message);
        //Clase de connection
        ndef.close();


    }

    private NdefRecord createRecord(String text) throws UnsupportedEncodingException {

    String lang ="en";
    byte[] textBytes=text.getBytes();
    byte[] langBytes=lang.getBytes("US-ASCII");
    int langLength=langBytes.length;
    int textLength=textBytes.length;
    byte[] payload =new byte[1+langLength+textLength];
    //set status byte (see NDEF spec for actual bits

        payload[0]= (byte) langLength;
        //copy langbytes and textbytes into payload

        System.arraycopy(langBytes,0,payload,1,langLength);
        System.arraycopy(textBytes,0,payload,1+langLength,textLength);

        NdefRecord recordNFC =new NdefRecord(NdefRecord.TNF_WELL_KNOWN,NdefRecord.RTD_TEXT,new byte[0],payload);

        return recordNFC;



    }

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

        //New code
        if(someThingToWrite) {
          // Is it an NDEF tag
          if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()))
          {
            myTag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            write("PlainText|" + stringToWrite, myTag);
            // Don't want to continue with reading so return
            return;
          }
          // Really should handle NDEF formatable tags as well
          // Just in case it's a blank unformatted tag
          // but that is relevant for this example.

        }

        setIntent(intent);
        readfromIntent(intent);
        if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()))
        {
            myTag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        }
    }
    @Override
    public void onPause()
    {
        super.onPause();
        WriteModeOff();
    }

    @Override
    public void onResume()
    {
        super.onResume();
        WriteModeOn();
    }

    /********ENABLE WRITE*****/
    private void WriteModeOn()
    {
        writeMode=true;
        nfcAdapter.enableForegroundDispatch(this,pendingIntent,writingTagFilters,null);

    }

    /*******DISABLE WRITE*****/
    private void WriteModeOff()
    {
        writeMode=false;
        nfcAdapter.disableForegroundDispatch(this);
    }
}

我很喜欢设置一个标志,而不是在下一个Tag检测写入Tag,实际上创建一个新的活动,只是为了处理用户界面,重新尝试逻辑和Tag写入,这保持了逻辑的清洁
然后,您的ActivateButton.setOnClickListener
只需启动新的活动,并通过Intent将字符串传递给它。

注意我可以你一直在复制和粘贴代码从可怜的例子在web上,因为你使用WriteModeOnWriteModeoff方法:-)

 类似资料:
  • 我正在尝试使用react-native-NFC-Manager在我的react-本机应用程序中添加NFC功能,它工作正常。但问题是我第一次无法读取/写入NFC卡。第一次,我需要使用NFC工具应用程序编写一个新标签,将“NdeFormatable”转换为“Ndef”,否则我无法读取/写入NFC卡 我用这段代码写数据: 这个问题有什么解决办法吗?

  • 我正在尝试创建一个 NFC 标签,该标签将触发两个单独的操作: 打开蓝牙连接 启动应用程序(或前往游戏商店) 我使用 nfc-eclipse-plugin 创建了一个包含两个合适记录的消息,但是,当写入标签时,它总是只触发第一个操作。两者都单独工作,但第二个总是被忽略。 我知道一个NFC标签上的2个NDEF消息/记录的答案-Android说你不能在一个标签上有两条独立的消息,只有一条消息中的多条记

  • 我使用下面的示例代码来读取NFC标签,但它不是多次读取标签(有时读取3次,有时读取6-7次)。在我的应用程序中,我需要连续读取nfc标签。 https://github.com/andijakl/NfcDemo

  • 本文向大家介绍详解Android平台上读写NFC标签,包括了详解Android平台上读写NFC标签的使用技巧和注意事项,需要的朋友参考一下 本文主要谈一谈Android上有关NFC标签的读写问题(NDEF格式)。 硬件环境:android4.0(Sony M35h)+可读可写的NFC标签若干 一、NFC基础知识 1.NFC是什么? NFC,即Near Field Communication,近距离

  • 如何将NDEF消息写入NFC标记?我必须更改清单文件吗?到目前为止,我有生成NDEF消息的代码: 如何发现标签?有人能帮我吗?

  • 我一直在开发一个应用程序,它使用NFC标签做一些魔术。 一切都很好,直到最近,我改变了一些代码,这些代码与之前一直有效的NFC代码无关。 当我通过NFC点击启动我的应用程序时,所有的工作,当我点击应用程序运行时,我将在onNewIntent()中收到未来的NFCTag。 当我通过图标启动应用程序并在应用程序运行时尝试点击时,会调用onNewIntent()方法,但当我试图从intent中获取额外的