我正在开发一个在androidstudio中编写nfc标签的应用程序。我的代码:
public class MainActivity extends AppCompatActivity {
public static final String Error_dected = "No NFC Tag Detected";
public static final String Write_Success = "Text Written Succesfully";
public static final String Write_Error = "Error during writtin, Try again";
NfcAdapter nfcAdapter;
PendingIntent pendingIntent;
IntentFilter writingTagFilters[];
boolean writeMode;
Tag myTag;
Context context;
EditText edit_message;
TextView nfc_contents;
Button ActivateButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
edit_message = (EditText) findViewById(R.id.edit_message);
nfc_contents = (TextView) findViewById(R.id.nfc_content);
ActivateButton = (Button) findViewById(R.id.ActivateButton);
context = this;
ActivateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String mensaje=edit_message.getText().toString();
try {
if (myTag == null) {
Toast.makeText(context, Error_dected, Toast.LENGTH_LONG).show();
} else {
write("PlainText|" + edit_message.getText().toString(), myTag);
Toast.makeText(context, Write_Success, Toast.LENGTH_LONG).show();
}
} catch (IOException e) {
Toast.makeText(context, Write_Error, Toast.LENGTH_LONG).show();
e.printStackTrace();
} catch (FormatException e) {
Toast.makeText(context, Write_Error, Toast.LENGTH_LONG).show();
e.printStackTrace();
}
}
});
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcAdapter == null) {
Toast.makeText(this, "this device does not support NFC", Toast.LENGTH_LONG).show();
}
readfromIntent(getIntent());
pendingIntent = pendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
writingTagFilters = new IntentFilter[]{tagDetected};
}
public void readfromIntent(Intent intent) {
String action = intent.getAction();
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
Parcelable[] rawMsg = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage[] msgs = null;
if (rawMsg != null) {
msgs = new NdefMessage[rawMsg.length];
for (int i = 0; i < rawMsg.length; i++) {
msgs[i] = (NdefMessage) rawMsg[i];
}
buildTagView(msgs);
}
}
}
private void buildTagView(NdefMessage[] msgs) {
if (msgs == null || msgs.length == 0) return;
String text = "";
byte[] payload = msgs[0].getRecords()[0].getPayload();
String textEncodgin = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16"; //Get the text encoding
int languageCodeLength = payload[0] & 0063;
try {
text = new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncodgin);
} catch (UnsupportedEncodingException e) {
Log.e("UnsupportedEncoding", e.toString());
}
nfc_contents.setText("NFC Content: " + text);
}
private void write(String text, Tag tag) throws IOException, FormatException {
NdefRecord[] records = {createRecord(text)};
NdefMessage message = new NdefMessage(records);
//Get an instance os Ndef for the tag
Ndef ndef = Ndef.get(tag);
//Enable I/0
ndef.connect();
//Write the message
ndef.writeNdefMessage(message);
//Clase de connection
ndef.close();
}
private NdefRecord createRecord(String text) throws UnsupportedEncodingException {
String lang ="en";
byte[] textBytes=text.getBytes();
byte[] langBytes=lang.getBytes("US-ASCII");
int langLength=langBytes.length;
int textLength=textBytes.length;
byte[] payload =new byte[1+langLength+textLength];
//set status byte (see NDEF spec for actual bits
payload[0]= (byte) langLength;
//copy langbytes and textbytes into payload
System.arraycopy(langBytes,0,payload,1,langLength);
System.arraycopy(textBytes,0,payload,1+langLength,textLength);
NdefRecord recordNFC =new NdefRecord(NdefRecord.TNF_WELL_KNOWN,NdefRecord.RTD_TEXT,new byte[0],payload);
return recordNFC;
}
@Override
protected void onNewIntent(Intent intent)
{
super.onNewIntent(intent);
setIntent(intent);
readfromIntent(intent);
if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()))
{
myTag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
}
}
@Override
public void onPause()
{
super.onPause();
WriteModeOff();
}
@Override
public void onResume()
{
super.onResume();
WriteModeOn();
}
/********ENABLE WRITE*****/
private void WriteModeOn()
{
writeMode=true;
nfcAdapter.enableForegroundDispatch(this,pendingIntent,writingTagFilters,null);
}
/*******DISABLE WRITE*****/
private void WriteModeOff()
{
writeMode=false;
nfcAdapter.disableForegroundDispatch(this);
}
}
当我运行它并尝试写入nfc标记时,我总是得到mytag==null,所以我总是在这里:
if(mytag==null){toast.maketext(context,error_dected,toast.length_long).show();
我已经修改了“android.manifest”中的用户权限知道发生了什么吗?谢谢您
1条答案
按热度按时间iih3973s1#
任何nfc操作的唯一起点是当系统nfc应用程序为您提供
Tag
对象作为与它检测到的nfc标记交互的起点。有很多方法可以做到这一点
enableForgroundDispatch
是您已经在使用的一种方法,但在实际使用中,这是一种非常不可靠的使用nfc的方法,并且会导致nfc标记上的大量写入错误和损坏的数据。更好的方法是使用更新的api
enableReaderMode
这方面的一个例子是https://stackoverflow.com/a/64921434/2373819 这也解释了为什么它更好。但是对于这两个api,当检测到一个标记并通知您一个标记已进入范围时,您需要完成与标记的所有交互(对于您正在使用的当前api,该标记已进入范围)
onNewIntent
)所以当用户点击
ActivateButton
是设置一个全局布尔值来指示Tag
如果检测到,则应向其写入,而不是尝试从中读取(并且还应将要写入的字符串存储在全局字符串中)下面是一些代码更改,让你的想法,但这是一个赤裸裸的例子,因为它没有显示任何用户界面的变化,以提示用户把一个nfc卡在范围内,它不包括任何重试,你可能需要成功地写入一个nfc卡。
我很喜欢下一个节目而不是挂个旗子
Tag
检测到写入标记以实际创建一个新的活动,只是为了处理ui并重试逻辑和Tag
这样可以保持逻辑更清晰,并且可以在应用程序的其他部分重复使用。然后你的
ActivateButton.setOnClickListener
只需启动新活动,并通过intent将字符串传递给write。注意,我可以告诉你,你一直在复制和粘贴的代码,从穷人的例子在网上,因为你使用
WriteModeOn
以及WriteModeOff
方法:-)