NFC 读取不工作
我是开发 Android 应用程序的新手。目前我正在尝试开发自己的标签阅读器,可以读取 MiFare Ultralight 标签。
但我无法读取标签,因为 NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) 总是返回 false。有人可以帮我吗?
NfcReader.java
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mText = (TextView) findViewById(R.id.text);
mText.setText("Scan a tag");
mAdapter = NfcAdapter.getDefaultAdapter();
// Create a generic PendingIntent that will be deliver to this activity. The NFC stack
// will fill in the intent with the details of the discovered tag before delivering to
// this activity.
mPendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
// Setup an intent filter for all MIME based dispatches
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
try {
ndef.addDataType("*/*");
} catch (MalformedMimeTypeException e) {
throw new RuntimeException("fail", e);
}
mFilters = new IntentFilter[] {
ndef,
};
// Setup a tech list for all NfcF tags
mTechLists = new String[][] { new String[] { NfcF.class.getName() } };
Intent intent = getIntent();
getNdefMessages(intent);
}
public void getNdefMessages(Intent intent) {
// Parse the intent
NdefMessage[] msgs = null;
String action = intent.getAction();
if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs != null) {
msgs = new NdefMessage[rawMsgs.length];
for (int i = 0; i < rawMsgs.length; i++) {
msgs[i] = (NdefMessage) rawMsgs[i];
}
}
else {
// Unknown tag type
byte[] empty = new byte[] {};
NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
NdefMessage msg = new NdefMessage(new NdefRecord[] {record});
msgs = new NdefMessage[] {msg};
}
}
else {
//Log.e(TAG, "Unknown intent " + intent);
finish();
}
}
@Override
public void onResume() {
super.onResume();
mAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters, mTechLists);
}
@Override
public void onNewIntent(Intent intent) {
Log.i("Foreground dispatch", "Discovered tag with intent: " + intent);
getNdefMessages(intent);
}
@Override
public void onPause() {
super.onPause();
//mAdapter.disableForegroundDispatch(this);
throw new RuntimeException("onPause not implemented to fix build");
}
Manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nfc.reader"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.NFC" />
<uses-sdk android:minSdkVersion="10"/>
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name="NfcReader"
android:theme="@android:style/Theme.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
<data android:mimeType="text/plain" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfctech" />
</activity>
</application>
</manifest>
I am newbie in developing android application. Currently I am trying to develop my own tag reader which can read MiFare Ultralight tag.
BUt I failed to read the tag as NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) always return false. Could somebody help me out?
NfcReader.java
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mText = (TextView) findViewById(R.id.text);
mText.setText("Scan a tag");
mAdapter = NfcAdapter.getDefaultAdapter();
// Create a generic PendingIntent that will be deliver to this activity. The NFC stack
// will fill in the intent with the details of the discovered tag before delivering to
// this activity.
mPendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
// Setup an intent filter for all MIME based dispatches
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
try {
ndef.addDataType("*/*");
} catch (MalformedMimeTypeException e) {
throw new RuntimeException("fail", e);
}
mFilters = new IntentFilter[] {
ndef,
};
// Setup a tech list for all NfcF tags
mTechLists = new String[][] { new String[] { NfcF.class.getName() } };
Intent intent = getIntent();
getNdefMessages(intent);
}
public void getNdefMessages(Intent intent) {
// Parse the intent
NdefMessage[] msgs = null;
String action = intent.getAction();
if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs != null) {
msgs = new NdefMessage[rawMsgs.length];
for (int i = 0; i < rawMsgs.length; i++) {
msgs[i] = (NdefMessage) rawMsgs[i];
}
}
else {
// Unknown tag type
byte[] empty = new byte[] {};
NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
NdefMessage msg = new NdefMessage(new NdefRecord[] {record});
msgs = new NdefMessage[] {msg};
}
}
else {
//Log.e(TAG, "Unknown intent " + intent);
finish();
}
}
@Override
public void onResume() {
super.onResume();
mAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters, mTechLists);
}
@Override
public void onNewIntent(Intent intent) {
Log.i("Foreground dispatch", "Discovered tag with intent: " + intent);
getNdefMessages(intent);
}
@Override
public void onPause() {
super.onPause();
//mAdapter.disableForegroundDispatch(this);
throw new RuntimeException("onPause not implemented to fix build");
}
Manifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.nfc.reader"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.NFC" />
<uses-sdk android:minSdkVersion="10"/>
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name="NfcReader"
android:theme="@android:style/Theme.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
<data android:mimeType="text/plain" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfctech" />
</activity>
</application>
</manifest>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
当检测到带有 NDEF 消息的标签时,android 会查找任何具有带有意图过滤器的 Activity 的应用程序,以执行操作“android.nfc.action.NDEF_DISCOVERED”。如果两个或多个应用程序可以处理此操作,则具有最精确过滤器的应用程序会接收意图。当找到具有相同过滤器的应用程序时,用户会选择其中一个。因此,在 AndroidManifest.xml 中,您必须使用此操作来检测 NDEF 格式的标签。
如果您想阅读 NDEF 消息,不必担心您正在阅读的标签类型(Ultralight、Felica、Topaz...)。 Android 使用 android.nfc.tech.Ndef 来调度 NDEF 格式的标签。因此,当您的 Activity 位于前台时,要获取所有 NdefMessage,您可以使用以下代码片段:
如果您想读取 Ultralight 标签(或其他技术),那应该是因为您需要来自该标签的原始数据。它不能从主应用程序线程执行。例如:
When a tag with an NDEF message is detected, android looks for any Application with an Activity with intent-filter for action "android.nfc.action.NDEF_DISCOVERED". If two or more applications can handle this action, the one with the most precise filter receives the intent. When applications with the same filter are found, is the user who chooses one. So in your AndroidManifest.xml you have to use this action for detecting NDEF formatted tags.
If you want to read NDEF messages don't worry about which type of tag you are reading (Ultralight, Felica, Topaz,...). Android uses android.nfc.tech.Ndef for dispatch NDEF formatted tags. So for getting all NdefMessages when you activity is on foreground, you can use this snippet:
If you want to read an Ultralight tag ( or another technology), it should be because you need the raw data from the tag. It must not be executed from the main application thread. For example:
在代码中,您根据 ACTION_TECH_DISCOVERED 设置意图过滤器,但随后尝试 ndef.addDataType(/),这是为 ACTION_NDEF_DISCOVERED 设置意图过滤器的方法。相反,您可以简单地执行以下操作:
确保您已正确设置 nfc_tech_list.xml:
In your code you are setting your intent filter based on ACTION_TECH_DISCOVERED, but then you try ndef.addDataType(/), which is the way you would go about setting up an intent filter for ACTION_NDEF_DISCOVERED. Instead you could simply do something like this:
make sure you have nfc_tech_list.xml set up properly: