每次我想在里面写字时,我都应该点击 NFC 标签吗?
Should I tap NFC tag every time I want to write in it?
我是 android 开发者
我想开发一个写入 NFC 标签数据的应用程序。 (只写)
我有一个编辑文本和一个按钮,当我点击按钮时,我在 NFC 上写入了字段中写入的数据
我搜索了很多并尝试了几个代码
唯一的问题是我的 NFC 标签贴在 phone 的后面,我使用的代码告诉我必须 tap/tag NFC 标签才能写入其中
单击按钮时,是否有其他方法检测贴在 phone 背面的 NFC 标签?
我有两个主要活动 activity 将从我的 NFCManager 调用方法
我将在 NFCManager 下面分享 class
NFCManager class:
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.Ndef;
import android.nfc.tech.NdefFormatable;
import java.io.ByteArrayOutputStream;
import java.util.Locale;
public class NFCManager {
private Activity activity;
private NfcAdapter nfcAdpt;
public NFCManager(Activity activity) {
this.activity = activity;
}
public void verifyNFC() throws NFCNotSupported, NFCNotEnabled {
nfcAdpt = NfcAdapter.getDefaultAdapter(activity);
if (nfcAdpt == null)
throw new NFCNotSupported();
if (!nfcAdpt.isEnabled())
throw new NFCNotEnabled();
}
public void enableDispatch() {
Intent nfcIntent = new Intent(activity, getClass());
nfcIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(activity, 0, nfcIntent, 0);
IntentFilter[] intentFiltersArray = new IntentFilter[] {};
String[][] techList = new String[][] { { android.nfc.tech.Ndef.class.getName() }, { android.nfc.tech.NdefFormatable.class.getName() } };
nfcAdpt.enableForegroundDispatch(activity, pendingIntent, intentFiltersArray, techList);
}
public void disableDispatch() {
nfcAdpt.disableForegroundDispatch(activity);
}
public static class NFCNotSupported extends Exception {
public NFCNotSupported() {
super();
}
}
public static class NFCNotEnabled extends Exception {
public NFCNotEnabled() {
super();
}
}
public void writeTag(Tag tag, NdefMessage message) {
if (tag != null) {
try {
Ndef ndefTag = Ndef.get(tag);
if (ndefTag == null) {
// Let's try to format the Tag in NDEF
NdefFormatable nForm = NdefFormatable.get(tag);
if (nForm != null) {
nForm.connect();
nForm.format(message);
nForm.close();
}
}
else {
ndefTag.connect();
ndefTag.writeNdefMessage(message);
ndefTag.close();
}
}
catch(Exception e) {
e.printStackTrace();
}
}
}
public NdefMessage createUriMessage(String content, String type) {
NdefRecord record = NdefRecord.createUri(type + content);
NdefMessage msg = new NdefMessage(new NdefRecord[]{record});
return msg;
}
public NdefMessage createTextMessage(String content) {
try {
// Get UTF-8 byte
byte[] lang = Locale.getDefault().getLanguage().getBytes("UTF-8");
byte[] text = content.getBytes("UTF-8"); // Content in UTF-8
int langSize = lang.length;
int textLength = text.length;
ByteArrayOutputStream payload = new ByteArrayOutputStream(1 + langSize + textLength);
payload.write((byte) (langSize & 0x1F));
payload.write(lang, 0, langSize);
payload.write(text, 0, textLength);
NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload.toByteArray());
return new NdefMessage(new NdefRecord[]{record});
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
public NdefMessage createExternalMessage(String content) {
NdefRecord externalRecord = NdefRecord.createExternal("com.survivingwithandroid", "data", content.getBytes());
NdefMessage ndefMessage = new NdefMessage(new NdefRecord[] { externalRecord });
return ndefMessage;
}
}
我的 MainActivity 中的方法:
@Override
protected void onResume() {
super.onResume();
try {
nfcMger.verifyNFC();
//nfcMger.enableDispatch();
Intent nfcIntent = new Intent(this, getClass());
nfcIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, nfcIntent, 0);
IntentFilter[] intentFiltersArray = new IntentFilter[] {};
String[][] techList = new String[][] { { android.nfc.tech.Ndef.class.getName() }, { android.nfc.tech.NdefFormatable.class.getName() } };
NfcAdapter nfcAdpt = NfcAdapter.getDefaultAdapter(this);
nfcAdpt.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techList);
}
catch(NFCManager.NFCNotSupported nfcnsup) {
Snackbar.make(v, "NFC not supported", Snackbar.LENGTH_LONG).show();
}
catch(NFCManager.NFCNotEnabled nfcnEn) {
Snackbar.make(v, "NFC Not enabled", Snackbar.LENGTH_LONG).show();
}
}
@Override
protected void onPause() {
super.onPause();
nfcMger.disableDispatch();
}
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d("Nfc", "New intent");
// It is the time to write the tag
currentTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (message != null) {
nfcMger.writeTag(currentTag, message);
dialog.dismiss();
Snackbar.make(v, "Tag written", Snackbar.LENGTH_LONG).show();
} else {
// Handle intent
}
}
还有另一种更好的方法来通知标签进入范围,尤其是当您正在写入标签时,这称为 enableReaderMode
但您的用例很奇怪。
我不确定为什么你会想要一个 NFC 标签贴在 phone 的背面,因为当文件在 phone ]的记忆力会好很多。
请记住,一旦标签进入范围,您就会通过 enableForegroundDispatch
或 enableReaderMode
收到标签已进入范围的通知,并获得标签对象。只要该 Tag 没有超出范围并且您已将 Tag 对象存储在 activity 的全局范围内,那么您可以根据需要多次写入它。
因此,即使在用户单击按钮时也可以执行您希望和写入(或读取)的操作,即使这很复杂。
你的App放到后台再拉到前台后,Tag对象是否可用,我没有测试过,但我觉得不太可能,因为后台App可能会关闭,关闭肯定无效Tag 对象。
但是你的代码有两个问题。
真正调用 connect
和 write
到你的标签不应该在 UI 线程上完成,因为它是 IO 阻塞并且可以被取消,这会导致将标签带出范围并再次带回范围内。幸运的是,如果您使用 enableReaderMode
,那么您会在单独的线程中收到通知。
你应该只在你不想再写的时候在标签上调用 close
,在你写了一次之后调用 close
.
因此以下内容可能对您有用,但限制是标签必须在应用程序启动后第一次进入范围。
使用 enableReaderMode
获得标签最初进入范围的通知,将标签对象存储在全局 Activity 范围中,并在 enableReaderMode
中将其 connect
一次=]回调线程。
从 UI 按下按钮时,开始一个新的线程 write
到标签。
切勿对标记对象调用关闭。
请注意,我没有对此进行测试,因为这是一个非常奇怪的用例。
我是 android 开发者
我想开发一个写入 NFC 标签数据的应用程序。 (只写) 我有一个编辑文本和一个按钮,当我点击按钮时,我在 NFC 上写入了字段中写入的数据 我搜索了很多并尝试了几个代码 唯一的问题是我的 NFC 标签贴在 phone 的后面,我使用的代码告诉我必须 tap/tag NFC 标签才能写入其中 单击按钮时,是否有其他方法检测贴在 phone 背面的 NFC 标签?
我有两个主要活动 activity 将从我的 NFCManager 调用方法 我将在 NFCManager 下面分享 class NFCManager class:
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.Ndef;
import android.nfc.tech.NdefFormatable;
import java.io.ByteArrayOutputStream;
import java.util.Locale;
public class NFCManager {
private Activity activity;
private NfcAdapter nfcAdpt;
public NFCManager(Activity activity) {
this.activity = activity;
}
public void verifyNFC() throws NFCNotSupported, NFCNotEnabled {
nfcAdpt = NfcAdapter.getDefaultAdapter(activity);
if (nfcAdpt == null)
throw new NFCNotSupported();
if (!nfcAdpt.isEnabled())
throw new NFCNotEnabled();
}
public void enableDispatch() {
Intent nfcIntent = new Intent(activity, getClass());
nfcIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(activity, 0, nfcIntent, 0);
IntentFilter[] intentFiltersArray = new IntentFilter[] {};
String[][] techList = new String[][] { { android.nfc.tech.Ndef.class.getName() }, { android.nfc.tech.NdefFormatable.class.getName() } };
nfcAdpt.enableForegroundDispatch(activity, pendingIntent, intentFiltersArray, techList);
}
public void disableDispatch() {
nfcAdpt.disableForegroundDispatch(activity);
}
public static class NFCNotSupported extends Exception {
public NFCNotSupported() {
super();
}
}
public static class NFCNotEnabled extends Exception {
public NFCNotEnabled() {
super();
}
}
public void writeTag(Tag tag, NdefMessage message) {
if (tag != null) {
try {
Ndef ndefTag = Ndef.get(tag);
if (ndefTag == null) {
// Let's try to format the Tag in NDEF
NdefFormatable nForm = NdefFormatable.get(tag);
if (nForm != null) {
nForm.connect();
nForm.format(message);
nForm.close();
}
}
else {
ndefTag.connect();
ndefTag.writeNdefMessage(message);
ndefTag.close();
}
}
catch(Exception e) {
e.printStackTrace();
}
}
}
public NdefMessage createUriMessage(String content, String type) {
NdefRecord record = NdefRecord.createUri(type + content);
NdefMessage msg = new NdefMessage(new NdefRecord[]{record});
return msg;
}
public NdefMessage createTextMessage(String content) {
try {
// Get UTF-8 byte
byte[] lang = Locale.getDefault().getLanguage().getBytes("UTF-8");
byte[] text = content.getBytes("UTF-8"); // Content in UTF-8
int langSize = lang.length;
int textLength = text.length;
ByteArrayOutputStream payload = new ByteArrayOutputStream(1 + langSize + textLength);
payload.write((byte) (langSize & 0x1F));
payload.write(lang, 0, langSize);
payload.write(text, 0, textLength);
NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload.toByteArray());
return new NdefMessage(new NdefRecord[]{record});
}
catch (Exception e) {
e.printStackTrace();
}
return null;
}
public NdefMessage createExternalMessage(String content) {
NdefRecord externalRecord = NdefRecord.createExternal("com.survivingwithandroid", "data", content.getBytes());
NdefMessage ndefMessage = new NdefMessage(new NdefRecord[] { externalRecord });
return ndefMessage;
}
}
我的 MainActivity 中的方法:
@Override
protected void onResume() {
super.onResume();
try {
nfcMger.verifyNFC();
//nfcMger.enableDispatch();
Intent nfcIntent = new Intent(this, getClass());
nfcIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, nfcIntent, 0);
IntentFilter[] intentFiltersArray = new IntentFilter[] {};
String[][] techList = new String[][] { { android.nfc.tech.Ndef.class.getName() }, { android.nfc.tech.NdefFormatable.class.getName() } };
NfcAdapter nfcAdpt = NfcAdapter.getDefaultAdapter(this);
nfcAdpt.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techList);
}
catch(NFCManager.NFCNotSupported nfcnsup) {
Snackbar.make(v, "NFC not supported", Snackbar.LENGTH_LONG).show();
}
catch(NFCManager.NFCNotEnabled nfcnEn) {
Snackbar.make(v, "NFC Not enabled", Snackbar.LENGTH_LONG).show();
}
}
@Override
protected void onPause() {
super.onPause();
nfcMger.disableDispatch();
}
@Override
public void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.d("Nfc", "New intent");
// It is the time to write the tag
currentTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (message != null) {
nfcMger.writeTag(currentTag, message);
dialog.dismiss();
Snackbar.make(v, "Tag written", Snackbar.LENGTH_LONG).show();
} else {
// Handle intent
}
}
还有另一种更好的方法来通知标签进入范围,尤其是当您正在写入标签时,这称为 enableReaderMode
但您的用例很奇怪。
我不确定为什么你会想要一个 NFC 标签贴在 phone 的背面,因为当文件在 phone ]的记忆力会好很多。
请记住,一旦标签进入范围,您就会通过 enableForegroundDispatch
或 enableReaderMode
收到标签已进入范围的通知,并获得标签对象。只要该 Tag 没有超出范围并且您已将 Tag 对象存储在 activity 的全局范围内,那么您可以根据需要多次写入它。
因此,即使在用户单击按钮时也可以执行您希望和写入(或读取)的操作,即使这很复杂。
你的App放到后台再拉到前台后,Tag对象是否可用,我没有测试过,但我觉得不太可能,因为后台App可能会关闭,关闭肯定无效Tag 对象。
但是你的代码有两个问题。
真正调用
connect
和write
到你的标签不应该在 UI 线程上完成,因为它是 IO 阻塞并且可以被取消,这会导致将标签带出范围并再次带回范围内。幸运的是,如果您使用enableReaderMode
,那么您会在单独的线程中收到通知。你应该只在你不想再写的时候在标签上调用
close
,在你写了一次之后调用close
.
因此以下内容可能对您有用,但限制是标签必须在应用程序启动后第一次进入范围。
使用 enableReaderMode
获得标签最初进入范围的通知,将标签对象存储在全局 Activity 范围中,并在 enableReaderMode
中将其 connect
一次=]回调线程。
从 UI 按下按钮时,开始一个新的线程 write
到标签。
切勿对标记对象调用关闭。
请注意,我没有对此进行测试,因为这是一个非常奇怪的用例。