为什么Android NFC阅读器在消息前添加“en”?

l7wslrjt  于 2022-12-25  发布在  Android
关注(0)|答案(3)|浏览(272)

嘿,伙计们,我正在测试NFC,我有一个问题,我认为它是格式化。
我在要编写应用程序的标记中添加了一个字符串值。
当我用那个商店的应用程序扫描它的时候,它显示ok...
当我用我的应用程序扫描时,它会在应用程序中显示正确的名称,但在消息前添加一个“en”。
和一白色。。所以如果我在标记中添加一个名称,然后扫描并获得一个API,它显示404,因为有一个en和空格。
http://myapisite.com/API/getdevice.php?id=输入标记字符串
在=空格之前,然后在ID或甚至名称之前输入en。
我试了几种方法。

public class MainActivity extends Activity {
    // 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 ()
            }
    };
    private TextView mTextView;
    private ImageView mImageView;
    private String ID, machineName, MachineImg, MachinePart, level;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate (savedInstanceState);
        setContentView (R.layout.activity_main);
        mImageView = findViewById (R.id.imageView);
        mTextView = findViewById (R.id.textView_explanation);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater ().inflate (R.menu.menu, menu);
        return true;
    }

    @Override
    protected void onResume() {
        super.onResume ();
        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 ();
        NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter (this);
        nfcAdapter.disableForegroundDispatch (this);
    }

    void parseNdefMessage(Intent intent) {
        Parcelable[] ndefMessageArray = intent.getParcelableArrayExtra (
                NfcAdapter.EXTRA_NDEF_MESSAGES);
        NdefMessage ndefMessage = (NdefMessage) ndefMessageArray[0];
        String text = new String (ndefMessage.getRecords ()[0].getPayload ());
        Log.d (TAG, "PAYLOAD MESS" + text);
        ID = text;
        getApiInfos ();
    }

    @Override
    protected void onNewIntent(Intent intent) {
        parseNdefMessage (intent);
        if (intent.getAction ().equals (NfcAdapter.ACTION_TAG_DISCOVERED)) {
            mTextView.setText ("NFC Tag\n" + ByteArrayToHexString (intent.getByteArrayExtra (NfcAdapter.EXTRA_ID)));

            Parcelable tagN = intent.getParcelableExtra (NfcAdapter.EXTRA_TAG);
            if (tagN != null) {
                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");
                for (int i = 0; i < messages1.length; ++i) {
                    Log.d (TAG, "Found M " + messages1[i].toString ());
                }
            } else {
                Log.d (TAG, "Not EXTRA_NDEF_MESSAGES");
            }

            Tag tag = intent.getParcelableExtra (NfcAdapter.EXTRA_TAG);
            Ndef ndef = Ndef.get (tag);
            if (ndef != null) {
                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");
            }
        }
    }

    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");
        sb.append ("ID (reversed): ").append (getReversed (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);
            }
        }

        DateFormat TIME_FORMAT = SimpleDateFormat.getDateTimeInstance ();
        Date now = new Date ();

        mTextView.setText (TIME_FORMAT.format (now) + '\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 long getReversed(byte[] bytes) {
        long result = 0;
        long factor = 1;
        for (int i = bytes.length - 1; i >= 0; --i) {
            long value = bytes[i] & 0xffl;
            result += value * factor;
            factor *= 256l;
        }
        return result;
    }

    private 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];
        }
        Log.d ("ByteArrayToHexString", String.format ("%0" + (inarray.length * 2) + "X", new BigInteger (1, inarray)));
        return out;
    }
enter code here
epfja78i

epfja78i1#

这很可能是因为应用程序编写将其存储为“WELL_KNOWN”类型的文本/纯文本
NFC文本格式的规格可以在NFCForum-TS-RTD_Text_1.0.pdf上找到。
有效负载中的额外字符如下所示:

  • 语言长度(1字节)+语言(n字节)+文本

所以空格实际上是语言不可打印的大小。
“en”表示文本为英语。
返回一个字节数组。
因此,下面应该工作,以修剪它(测试),因为似乎没有很好的助手方法来解码它,只有创建这种格式。

// Create Test Record
NdefRecord record = NdefRecord.createTextRecord("en", "Hello");

//Get Bytes of payload
// byte[] payload = ndefMessage.getRecords ()[0].getPayload ();
// Get Bytes of test NDEF Record
byte[] payload = record.getPayload ();
// Read First Byte and then trim off the right length
byte[] textArray = Arrays.copyOfRange(payload, (int) payload[0] + 1 , payload.length);
// Convert to Text
String text = new String(textArray);

**更新:**由于问题中给出的代码有点混乱,您做了一些不需要做的事情,也没有做一些需要做的事情(例如,您要求从没有NDef数据的卡发送数据,然后您解析Ndef数据,而没有检查是否有一些数据要解析)

我已经简化了代码,只是为了读取一个文本NDEF记录(注:未测试,但基于我过去读取NDEF数据的方式,我现在使用一种更好的方法来读取更可靠的卡,特别是如果你想写入卡以及)

public class MainActivity extends Activity {
    private TextView mTextView;
    private ImageView mImageView;
    private String ID, machineName, MachineImg, MachinePart, level;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mImageView = findViewById(R.id.imageView);
        mTextView = findViewById(R.id.textView_explanation);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu, menu);
        return true;
    }

    @Override
    protected void onResume() {
        super.onResume();
        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(NfcAdapter.ACTION_NDEF_DISCOVERED);
        // enabling foreground dispatch for getting intent from NFC event:
        NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        nfcAdapter.enableForegroundDispatch(this, pendingIntent, new IntentFilter[]{filter}, null);
    }

    @Override
    protected void onPause() {
        super.onPause();
        NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        nfcAdapter.disableForegroundDispatch(this);
    }

    void parseNdefMessage(Intent intent) {
        Parcelable[] ndefMessageArray = intent.getParcelableArrayExtra(
                NfcAdapter.EXTRA_NDEF_MESSAGES);
        // Test if there is actually a NDef message passed via the Intent
        if (ndefMessageArray != null) {
            NdefMessage ndefMessage = (NdefMessage) ndefMessageArray[0];
            //Get Bytes of payload
            byte[] payload = ndefMessage.getRecords()[0].getPayload();
            // Read First Byte and then trim off the right length
            byte[] textArray = Arrays.copyOfRange(payload, (int) payload[0] + 1, payload.length);
            // Convert to Text
            String text = new String(textArray);
            ID = text;
            getApiInfos();
        }
    }

    @Override
    protected void onNewIntent(Intent intent) {

        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
            parseNdefMessage(intent);
        }
    }
}
bxgwgixi

bxgwgixi2#

好的,谢谢@Andrew,我使用了你的部分代码,并根据我的测试进行了调整。它工作得很好,现在我可以清理它,删除不使用或不需要的内容。谢谢节日快乐!:)

void parseNdefMessage(Intent intent) {
    Parcelable[] ndefMessageArray = intent.getParcelableArrayExtra(
            NfcAdapter.EXTRA_NDEF_MESSAGES);
    // Test if there is actually a NDef message passed via the Intent
    if (ndefMessageArray != null) {
        NdefMessage ndefMessage = (NdefMessage) ndefMessageArray[0];
        //Get Bytes of payload
        byte[] payload = ndefMessage.getRecords()[0].getPayload();
        // Read First Byte and then trim off the right length
        byte[] textArray = Arrays.copyOfRange(payload, (int) payload[0] + 1, payload.length);
        // Convert to Text
        String text = new String(textArray);
        ID = text;
        getApiInfos();
    }
}
uelo1irk

uelo1irk3#

如果有人在ReactNative中遇到同样的问题,我的解决方案是react-native-nfc-manager

// register for the NFC tag with NDEF in it
      await NfcManager.requestTechnology(NfcTech.Ndef);
      // the resolved tag object will contain `ndefMessage` property
      const tag = await NfcManager.getTag();
      // access the payload
      const payload = tag?.ndefMessage[0].payload;
      //remove the language code from payload
      const subPayload = payload?.slice(3, payload.length);
      const decoded = Ndef.util.bytesToString(subPayload);

相关问题