为啥我会得到一个反向的 NFC 标签 ID(十六进制)?

Posted

技术标签:

【中文标题】为啥我会得到一个反向的 NFC 标签 ID(十六进制)?【英文标题】:Why am I getting a reversed NFC Tag ID (Hex)?为什么我会得到一个反向的 NFC 标签 ID(十六进制)? 【发布时间】:2020-06-01 13:59:43 【问题描述】:

我希望我的应用程序扫描 NFC 标签并获取其 ID 和标签类型。但不知何故,我的代码读取了一个反向的标签 ID。

例如,我的应用读取以下标签 ID(十六进制):80 65 69 e2 f5 fe 04 而来自 Google Play 商店的其他 4 个类似应用读取以下 ID:4 fe f5 e2 69 65 80(其中第一个零也丢失了)

我希望我的应用在不还原字节的情况下读取标签 ID,我该如何实现?这是我的完整代码:

package com.asetnfc;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.IsoDep;
import android.nfc.tech.MifareClassic;
import android.nfc.tech.MifareUltralight;
import android.nfc.tech.Ndef;
import android.nfc.tech.NfcA;
import android.nfc.tech.NfcB;
import android.nfc.tech.NfcF;
import android.nfc.tech.NfcV;
import android.os.AsyncTask;
import android.os.Parcelable;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.widget.TextView;
import android.widget.Toast;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;


import static android.content.ContentValues.TAG;

//public class MainActivity extends AppCompatActivity 

public class InfoNFC extends Activity 
    private TextView mTextView; //ECP 2017-01-16

    // list of NFC technologies detected:
    private final String[][] techList = new String[][] 
            new String[] 
                    NfcA.class.getName(),
                    NfcB.class.getName(),
                    NfcF.class.getName(),
                    NfcV.class.getName(),
                    IsoDep.class.getName(),
                    MifareClassic.class.getName(),
                    MifareUltralight.class.getName(), Ndef.class.getName()
            
    ;

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

        mTextView = (TextView) findViewById(R.id.infonfctype);
        mTextView.setText("Data Tampil Disini");
    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) 
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    

    @Override
    protected void onResume() 
        super.onResume();
        Log.d("onResume", "1");

        //mTextView.setText("onResume:");
        // creating pending intent:
        PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        // creating intent receiver for NFC events:
        IntentFilter filter = new IntentFilter();
        filter.addAction(NfcAdapter.ACTION_TAG_DISCOVERED);
        filter.addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
        filter.addAction(NfcAdapter.ACTION_TECH_DISCOVERED);
        // enabling foreground dispatch for getting intent from NFC event:
        NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        nfcAdapter.enableForegroundDispatch(this, pendingIntent, new IntentFilter[]filter, this.techList);
    

    @Override
    protected void onPause() 
        super.onPause();

        Log.d("onPause", "1");

        // disabling foreground dispatch:
        NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        nfcAdapter.disableForegroundDispatch(this);
    

    @Override
    protected void onNewIntent(Intent intent) 
        Log.d("onNewIntent", "1");

        if (intent.getAction().equals(NfcAdapter.ACTION_TAG_DISCOVERED)) 
            Log.d("onNewIntent", "2");
            mTextView.setText( "NFC Tag\n" + ByteArrayToHexString(intent.getByteArrayExtra(NfcAdapter.EXTRA_ID)));

            //if(getIntent().hasExtra(NfcAdapter.EXTRA_TAG))

            Parcelable tagN = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            if (tagN != null) 
                Log.d(TAG, "Parcelable OK");
                NdefMessage[] msgs;
                byte[] empty = new byte[0];
                byte[] id = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);
                byte[] payload = dumpTagData(tagN).getBytes();
                NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, id, payload);
                NdefMessage msg = new NdefMessage(new NdefRecord[]  record );
                msgs = new NdefMessage[]  msg ;

                //Log.d(TAG, msgs[0].toString());


            
            else 
                Log.d(TAG, "Parcelable NULL");
            



            Parcelable[] messages1 = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            if (messages1 != null) 
                Log.d(TAG, "Found " + messages1.length + " NDEF messages");
            
            else 
                Log.d(TAG, "Not EXTRA_NDEF_MESSAGES");
            

            Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            Ndef ndef = Ndef.get(tag);
            if(ndef != null) 

                Log.d("onNewIntent:", "NfcAdapter.EXTRA_TAG");

                Parcelable[] messages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
                if (messages != null) 
                    Log.d(TAG, "Found " + messages.length + " NDEF messages");
                
            
            else 
                Log.d(TAG, "Write to an unformatted tag not implemented");
            


            //mTextView.setText( "NFC Tag\n" + ByteArrayToHexString(intent.getByteArrayExtra(NfcAdapter.EXTRA_TAG)));
        
    

    private String dumpTagData(Parcelable p) 
        StringBuilder sb = new StringBuilder();
        Tag tag = (Tag) p;
        byte[] id = tag.getId();
        sb.append("Tag ID (hex): ").append(getHex(id)).append("\n");
        sb.append("Tag ID (dec): ").append(getDec(id)).append("\n");



        String prefix = "android.nfc.tech.";
        sb.append("Technologies: ");
        for (String tech : tag.getTechList()) 
            sb.append(tech.substring(prefix.length()));
            sb.append(", ");
        
        sb.delete(sb.length() - 2, sb.length());
        for (String tech : tag.getTechList()) 
            if (tech.equals(MifareClassic.class.getName())) 
                sb.append('\n');
                MifareClassic mifareTag = MifareClassic.get(tag);
                String type = "Unknown";
                switch (mifareTag.getType()) 
                    case MifareClassic.TYPE_CLASSIC:
                        type = "Classic";
                        break;
                    case MifareClassic.TYPE_PLUS:
                        type = "Plus";
                        break;
                    case MifareClassic.TYPE_PRO:
                        type = "Pro";
                        break;
                
                sb.append("Mifare Classic type: ");
                sb.append(type);
                sb.append('\n');

                sb.append("Mifare size: ");
                sb.append(mifareTag.getSize() + " bytes");
                sb.append('\n');

                sb.append("Mifare sectors: ");
                sb.append(mifareTag.getSectorCount());
                sb.append('\n');

                sb.append("Mifare blocks: ");
                sb.append(mifareTag.getBlockCount());
            

            if (tech.equals(MifareUltralight.class.getName())) 
                sb.append('\n');
                MifareUltralight mifareUlTag = MifareUltralight.get(tag);
                String type = "Unknown";
                switch (mifareUlTag.getType()) 
                    case MifareUltralight.TYPE_ULTRALIGHT:
                        type = "Ultralight";
                        break;
                    case MifareUltralight.TYPE_ULTRALIGHT_C:
                        type = "Ultralight C";
                        break;
                
                sb.append("Mifare Ultralight type: ");
                sb.append(type);
            
        
        Log.d("Datos: ", sb.toString());



        mTextView.setText('\n' + sb.toString());
        return sb.toString();
    


    private String getHex(byte[] bytes) 
        StringBuilder sb = new StringBuilder();
        for (int i = bytes.length - 1; i >= 0; --i) 
            int b = bytes[i] & 0xff;
            if (b < 0x10)
                sb.append('0');
            sb.append(Integer.toHexString(b));
            if (i > 0) 
                sb.append(" ");
            
        
        return sb.toString();
    

    private long getDec(byte[] bytes) 
        long result = 0;
        long factor = 1;
        for (int i = 0; i < bytes.length; ++i) 
            long value = bytes[i] & 0xffl;
            result += value * factor;
            factor *= 256l;
        
        return result;
    



    private String ByteArrayToHexString(byte [] inarray) 

        Log.d("ByteArrayToHexString", inarray.toString());

        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];
        
//CE7AEED4
//EE7BEED4
        Log.d("ByteArrayToHexString", String.format("%0" + (inarray.length * 2) + "X", new BigInteger(1,inarray)));


        return out;
    




【问题讨论】:

【参考方案1】:

在您的函数getHex() 中,您从最后一个字节开始,然后递减i 计数器。 尝试使用此功能:

private final static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHexString(byte[] bytes) 
    if (bytes == null) 
        return null;
    
    char[] hexChars = new char[bytes.length * 2];
    for (int j = 0; j < bytes.length; j++) 
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    
    return new String(hexChars);

【讨论】:

你能给我完整的代码吗?我在“hexArray”中收到错误 对不起,这是我的错误,给你:private final static char[] hexArray = "0123456789ABCDEF".toCharArray(); 我使用Eclipse开发NFC应用,可能有一些差异,但它仍然可以工作。谢谢。 可以使用 StringBuilder 在 "for" 循环中附加一个 String.format("%02X ", bytes[i]) 作为将十六进制转换为字符串的更简单方法

以上是关于为啥我会得到一个反向的 NFC 标签 ID(十六进制)?的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用十六进制常量?

为啥十六进制的 5D 表示为 bytearray(b']')?

为啥十六进制数字以#而不是0x为前缀?

为啥十六进制颜色值中有前导“#FF”?

为啥 chr() 返回一个十六进制值,我怎样才能让它只返回字符 [重复]

为啥.out文件是十六进制而不是二进制