为什么Android NFC阅读器添加了"zh"消息之前? [英] Why Android NFC reader add's "en" before the message?

查看:183
本文介绍了为什么Android NFC阅读器添加了"zh"消息之前?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

嘿,我正在测试NFC,我认为它正在格式化..

Hey guys im testing NFC and i have an issue with i think it is formating..

我在标签中添加了一个字符串值,并带有一个要编写的应用程序.

I added a string value in the tag with an app to write.

当我使用相同的商店应用程序扫描它时,显示正常...

when i scan it with that same store app it shows ok...

当我使用我的应用程序扫描时,它会在应用程序中显示正确的名称,但在消息前添加一个"en".

when i scan with my app it shows the correct name in the app but adds a "en" before the message..

和一个空格..因此,如果我在标签中添加一个名称,然后扫描并获取一个API,它将显示404,因为存在一个en和空格.

and a white space.. so if i add a name in the tag then scan and get a API it shows 404 cause there is an en and white space..

http://myapisite.com/API/getdevice.php?id= enTagString

http://myapisite.com/API/getdevice.php?id= enTagString

在=空格之前,然后在我放置的ID甚至名字之前添加en ..

before the = space and then en before the id or even name i put..

我尝试了几种方法.

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

推荐答案

最可能的原因是,应用编写将其存储为"WELL_KNOWN"类型的文本/纯文本

Most likely this is because the App writing is storing it as a "WELL_KNOWN" type of text/plain

有关NFC文本格式的规范,请参见

The specs for NFC Text format can be found at NFCForum-TS-RTD_Text_1.0.pdf.

有效负载中的多余字符如下:

The extra characters in the payload are as below:

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

因此,空格实际上是该语言不可打印的大小.

So the space is the actually a non printable size of the language.

"en"用于定义文本为英语.

The "en" is defining that the text is English.

https://developer.android.com/reference/android/nfc/NdefRecord#getPayload()返回一个字节数组.

所以下面应该对它进行修剪(测试),因为似乎没有很好的辅助方法来解码它,只能创建这种格式.

So below should work to trim it (tested) as there don't seem to be nice helper methods to decode it, only create this format.

// 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数据而不检查是否有一些数据要解析)

UPDATE: As the code given in the question is a bit of a mess and you do things you don't need to do and don't do things you do need to do (e.g. you have asked to be sent data from cards that won't have NDef data in them and then you parse for Ndef data without checking there is some data to parse)

我已经简化了代码,只是为了读取文本NDEF记录(注意,未经测试,但是基于我以前读取NDEF数据的方式,我现在使用一种更好的方法来读取卡,该方法更可靠,尤其是如果您想要还要写卡)

I've simplified the code just to read a text NDEF record (Note not tested, but based on how I used to read NDEF data, I now use a better method to read cards that is more reliable especially if you want to write to cards as well)

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);
        }
    }
}

这篇关于为什么Android NFC阅读器添加了"zh"消息之前?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆