为什么AndroidNFCreader在消息前加"en"?
Why Android NFC reader add's "en" before the message?
大家好,我正在测试 NFC,我有一个问题,我认为它正在格式化..
我在要写的应用程序标签中添加了一个字符串值。
当我用同一个商店应用程序扫描它时,它显示正常...
当我用我的应用程序扫描时,它在应用程序中显示了正确的名称,但在消息前添加了一个 "en"..
和一个白色 space.. 所以如果我在标签中添加一个名字然后扫描并得到一个 API 它显示 404 因为有一个 en 和白色 space。 .
http://myapisite.com/API/getdevice.php?id= enTagString
在 = space 之前,然后在我输入的 id 或什至名字之前..
我尝试了几种方法..
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
这很可能是因为应用程序编写将其存储为 text/plain
的 "WELL_KNOWN" 类型可在 NFCForum-TS-RTD_Text_1.0.pdf 找到 NFC 文本格式的规范。
有效载荷中的额外字符如下:
- 语言长度(1字节)+语言(n字节)+文本
所以 space 实际上是该语言的不可打印尺寸。
"en"定义文本为英文。
https://developer.android.com/reference/android/nfc/NdefRecord#getPayload() returns 字节数组。
所以下面应该 trim 它(已测试)因为似乎没有很好的辅助方法来解码它,只能创建这种格式。
// 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);
}
}
}
好的,感谢@Andrew,我使用了你的部分代码并将其改编为我的测试..它工作得很好,现在我可以清理它并删除不使用的东西或者needed.Thx节日快乐!:)
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();
}
}