我已经写了一个包含外部记录类型的NFC标签。
使用SmartQ读取标记说明如下:
NDEF内容
Record Type:External
Type:/com.domainname:link-uuid
xyzxyz-xyzxyz
支持的技术
android.nfc.NfcA
android.nfc.tech.MifareUltralight
android.nfc.tech.Ndef
所以我非常确定我的标签写得正确。
我尝试在手机注意到某个标记时启动某个活动,并且只有当该类型为外部/com.domainname:link-uuid时才会过滤运行?
我的manifest.xml如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.domainname.android.interlink.nfc" >
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<uses-permission android:name="android.permission.NFC" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".NFCWrite"
android:configChanges="orientation|keyboardHidden"
android:label="@string/title_activity_nfcread"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name=".NFCRead"
android:configChanges="orientation|keyboardHidden"
android:label="@string/title_activity_nfcread"
android:launchMode="singleTask" >
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:host="ext"
android:pathPrefix="/com.domainname-uuid"
android:scheme="vnd.android.nfc" />
</intent-filter>
</activity>
</application>
</manifest>
阅读活动是:
package com.domainname.android.interlink.nfc;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcManager;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.widget.Toast;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
public class NFCRead extends Activity {
private static final int PENDING_INTENT_TECH_DISCOVERED = 1;
private static final int PENDING_INTENT_NDEF_DISCOVERED = 1;
private NfcAdapter mNfcAdapter;
/**
* Called when the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i("NFCRead.onCreate","Running...");
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nfcread);
// Resolve the intent that started us:
try {
resolveIntent(this.getIntent());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
/**
* Called when the activity gets focus.
*/
@Override
public void onResume() {
Log.i("NFCRead.onResume","Running...");
super.onResume();
// Retrieve an instance of the NfcAdapter ("connection" to the NFC system service):
NfcManager nfcManager = (NfcManager) this.getSystemService(Context.NFC_SERVICE);
if (nfcManager != null) {
mNfcAdapter = nfcManager.getDefaultAdapter();
}
if (mNfcAdapter != null) {
// The isEnabled() method, if invoked directly after the NFC service
// crashed, returns false regardless of the real setting (Android 2.3.3+).
// As a nice side-effect it re-establishes the link to the correct instance
// of NfcAdapter. Therefore, just execute this method twice whenever we
// re-request the NfcAdapter, so we can be sure to have a valid handle.
try {
mNfcAdapter.isEnabled();
} catch (NullPointerException e) {
// Drop NullPointerException that is sometimes thrown
// when NFC service crashed
}
try {
mNfcAdapter.isEnabled();
} catch (NullPointerException e) {
// Drop NullPointerException that is sometimes thrown
// when NFC service crashed
}
// Create a PendingIntent to handle discovery of Ndef and NdefFormatable tags:
PendingIntent pi = createPendingResult(
PENDING_INTENT_NDEF_DISCOVERED,
new Intent(),
0);
if (pi != null) {
try {
// Enable foreground dispatch for Ndef and NdefFormatable tags:
mNfcAdapter.enableForegroundDispatch(
this,
pi,
new IntentFilter[]{
new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)
},
new String[][]{
new String[]{"android.nfc.tech.Ndef"}
});
} catch (NullPointerException e) {
// Drop NullPointerException that is sometimes thrown
// when NFC service crashed
}
}
}
}
/**
* Called when the activity loses focus.
*/
@Override
public void onPause() {
Log.i("NFCRead.onPause","Running...");
super.onPause();
if (mNfcAdapter != null) {
try {
// Disable foreground dispatch:
mNfcAdapter.disableForegroundDispatch(this);
} catch (NullPointerException e) {
// Drop NullPointerException that is sometimes thrown
// when NFC service crashed
}
}
}
/**
* Called when activity receives a new intent.
*/
@Override
public void onNewIntent(Intent data) {
Log.i("NFCRead.onNewIntent","Running...");
// Resolve the intent that re-invoked us:
try {
resolveIntent(data);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
/**
* Called when a pending intent returns (e.g. our foreground dispatch).
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.i("NFCRead.onActivityResult","Running...");
switch (requestCode) {
case PENDING_INTENT_TECH_DISCOVERED:
// Resolve the foreground dispatch intent:
try {
resolveIntent(data);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
break;
}
}
/**
* Method to handle any intents that triggered our activity.
* @param data The intent we received and want to process.
*
*/
private void resolveIntent(Intent data) throws UnsupportedEncodingException {
Log.i("resolveIntent","Running...");
this.setIntent(data);
String action = data.getAction();
// We were started from the recent applications history: just show our main activity
// (otherwise, the last intent that invoked us will be re-processed)
if ((data.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) { return; }
// Intent is a tag technology (we are sensitive to Ndef, NdefFormatable) or
// an NDEF message (we are sensitive to URI records with the URI http://www.mroland.at/)
if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
Log.i("TECH_DISCOVERED", "TECH_DISCOVERED");
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
// The reference to the tag that invoked us is passed as a parameter (intent extra EXTRA_TAG)
Tag tag = data.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Log.i("NDEF Discovered:", tag.toString());
// Let's read the tag whenever we are not in write mode
// Retrieve information from tag and display it
StringBuilder tagInfo = new StringBuilder();
// Get tag's UID:
byte[] uid = tag.getId();
tagInfo.append("UID: ").append(new String(uid, "UTF-8")).append("\n\n");
// Get tag's NDEF messages: The NDEF messages are passed as parameters (intent
// extra EXTRA_NDEF_MESSAGES) and have to be casted into an NdefMessage array.
Parcelable[] ndefRaw = data.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage[] ndefMsgs = null;
if (ndefRaw != null) {
ndefMsgs = new NdefMessage[ndefRaw.length];
for (int i = 0; i < ndefMsgs.length; ++i) {
// Cast each NDEF message from Parcelable to NdefMessage:
ndefMsgs[i] = (NdefMessage) ndefRaw[i];
}
}
// Find External records:
if (ndefMsgs != null) {
// Iterate through all NDEF messages on the tag:
for (NdefMessage ndefMsg : ndefMsgs) {
// Get NDEF message's records:
NdefRecord[] records = ndefMsg.getRecords();
if (records != null) {
// Iterate through all NDEF records:
for (NdefRecord record : records) {
// Test if this record is a URI record:
if ((record.getTnf() == NdefRecord.TNF_EXTERNAL_TYPE)
&& Arrays.equals(record.getType(), NdefRecord.RTD_TEXT)) {
// Get record payload:
// // Drop prefix identifier byte and convert remaining URL to string (UTF-8):
// String uri = new String(Arrays.copyOfRange(payload, 1, payload.length), Charset.forName("UTF-8"));
// Use UriRecordHelper to decode URI record payload:
String uuid = new String(record.getPayload(), "UTF-8");
tagInfo.append("UUID: ");
tagInfo.append(uuid);
tagInfo.append("\n");
}
}
}
}
}
// Show our tag detected dialog (with the tag information passed as parameter):
Toast toast = Toast.makeText(getApplicationContext(), tagInfo.toString(), Toast.LENGTH_SHORT);
toast.show();
}
}
}
}
我做错了,因为即使应用程序正在运行,也从未调用此活动。因此,我的应用程序永远不会读取标记。
我使用了教程中的大部分代码,由我修改,因此我可以学习它。我设法让它在编写标签时工作,但我无法阅读它们。
请有人指出我哪里出错了。感谢。
答案 0 :(得分:1)
我已经解决了这个问题。
问题在于我在编写标签时将/放在域名前面。
所以我改变了:
NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_EXTERNAL_TYPE,"/com.domainname:link1-uuid".getBytes(),new byte[]{},msgBytes);
为:
NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_EXTERNAL_TYPE,"com.domainname:link1-uuid".getBytes(),new byte[]{},msgBytes);
活动现在开始完美。