我在android中写nfc标签有问题

jucafojl  于 2021-06-29  发布在  Java
关注(0)|答案(1)|浏览(490)

我正在开发一个在androidstudio中编写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==null,所以我总是在这里:
if(mytag==null){toast.maketext(context,error_dected,toast.length_long).show();
我已经修改了“android.manifest”中的用户权限知道发生了什么吗?谢谢您

iih3973s

iih3973s1#

任何nfc操作的唯一起点是当系统nfc应用程序为您提供 Tag 对象作为与它检测到的nfc标记交互的起点。
有很多方法可以做到这一点 enableForgroundDispatch 是您已经在使用的一种方法,但在实际使用中,这是一种非常不可靠的使用nfc的方法,并且会导致nfc标记上的大量写入错误和损坏的数据。
更好的方法是使用更新的api enableReaderMode 这方面的一个例子是https://stackoverflow.com/a/64921434/2373819 这也解释了为什么它更好。
但是对于这两个api,当检测到一个标记并通知您一个标记已进入范围时,您需要完成与标记的所有交互(对于您正在使用的当前api,该标记已进入范围) onNewIntent )
所以当用户点击 ActivateButton 是设置一个全局布尔值来指示 Tag 如果检测到,则应向其写入,而不是尝试从中读取(并且还应将要写入的字符串存储在全局字符串中)
下面是一些代码更改,让你的想法,但这是一个赤裸裸的例子,因为它没有显示任何用户界面的变化,以提示用户把一个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 检测到写入标记以实际创建一个新的活动,只是为了处理ui并重试逻辑和 Tag 这样可以保持逻辑更清晰,并且可以在应用程序的其他部分重复使用。
然后你的 ActivateButton.setOnClickListener 只需启动新活动,并通过intent将字符串传递给write。
注意,我可以告诉你,你一直在复制和粘贴的代码,从穷人的例子在网上,因为你使用 WriteModeOn 以及 WriteModeOff 方法:-)

相关问题