NFC 标签被 android 的默认标签查看器而非应用捕获
NFC Tag caught by android's default Tag Viewer instead of app
我已经按照不同的教程阅读了一些与该问题相关的修复程序,但似乎仍然没有任何效果...每当我扫描 NFC 标签时,它都会打开名为 [=25] 的默认 android 应用程序=]Tag Viewer 告诉我“收集了新标签”并且主体是“空标签”,但我的应用程序中没有任何反应.我无法打印任何日志...
这是我的清单:
<activity
android:name=".activityv2.ActivityHome"
android:label="Home"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tag_filter" />
</activity>
这是我的 Activity:
public class ActivityHome extends GenericActivity implements BackHandledFragment.BackHandlerInterface, OnFragmentListener {
private final String TAG = "ActivityHome";
public static final String MIME_TEXT_PLAIN = "text/plain";
@Bind(R.id.drawer_layout)
DrawerLayout mDrawerLayout;
@Bind(R.id.actionToolbar)
Toolbar toolbar;
@Bind(R.id.left_drawer_item)
LinearLayout mDrawerLinear;
@Bind(R.id.left_drawer_child)
ListView mDrawerListChild;
@Bind(R.id.profil_pic)
CircleImageView mProfilPic;
private NfcAdapter mNfcAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_v2_home);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle(getResources().getString(R.string.app_name));
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
// enable ActionBar app icon to behave as action to toggle nav drawer
handleIntent(getIntent());
}
private void handleIntent(Intent intent) {
String action = intent.getAction();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
String type = intent.getType();
if (MIME_TEXT_PLAIN.equals(type)) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
new NdefReaderTask().execute(tag);
} else {
Log.d(TAG, "Wrong mime type: " + type);
}
} else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
// In case we would still use the Tech Discovered Intent
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String[] techList = tag.getTechList();
String searchedTech = Ndef.class.getName();
for (String tech : techList) {
if (searchedTech.equals(tech)) {
new NdefReaderTask().execute(tag);
break;
}
}
}
}
@Override
protected void onNewIntent(Intent intent) {
/**
* This method gets called, when a new Intent gets associated with the current activity instance.
* Instead of creating a new activity, onNewIntent will be called. For more information have a look
* at the documentation.
*
* In our case this method gets called, when the user attaches a Tag to the device.
*/
handleIntent(intent);
}
private class NdefReaderTask extends AsyncTask<Tag, Void, String> {
@Override
protected String doInBackground(Tag... params) {
Tag tag = params[0];
Ndef ndef = Ndef.get(tag);
if (ndef == null) {
// NDEF is not supported by this Tag.
return null;
}
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
NdefRecord[] records = ndefMessage.getRecords();
for (NdefRecord ndefRecord : records) {
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
try {
return readText(ndefRecord);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Unsupported Encoding", e);
}
}
}
return null;
}
private String readText(NdefRecord record) throws UnsupportedEncodingException {
/*
* See NFC forum specification for "Text Record Type Definition" at 3.2.1
*
* http://www.nfc-forum.org/specs/
*
* bit_7 defines encoding
* bit_6 reserved for future use, must be 0
* bit_5..0 length of IANA language code
*/
byte[] payload = record.getPayload();
// Get the Text Encoding
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
// Get the Language Code
int languageCodeLength = payload[0] & 0063;
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
// e.g. "en"
// Get the Text
return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
}
@Override
protected void onPostExecute(String result) {
if (result != null) {
Log.e(TAG, result);
}
}
}
@Override
protected void onPause() {
super.onPause();
if (mNfcAdapter != null)
stopForegroundDispatch(this, mNfcAdapter);
}
@Override
protected void onResume() {
super.onResume();
if (mNfcAdapter != null)
setupForegroundDispatch(this, mNfcAdapter);
}
@Override
protected void onDestroy() {
getSupportFragmentManager().removeOnBackStackChangedListener(mOnBackStackChangedListener);
super.onDestroy();
}
public static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) {
final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);
IntentFilter[] filters = new IntentFilter[1];
String[][] techList = new String[][]{};
// Notice that this is the same filter as in our manifest.
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
filters[0].addCategory(Intent.CATEGORY_DEFAULT);
try {
filters[0].addDataType(MIME_TEXT_PLAIN);
} catch (IntentFilter.MalformedMimeTypeException e) {
throw new RuntimeException("Check your mime type.");
}
adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
}
public static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) {
adapter.disableForegroundDispatch(activity);
}
}
这里是 XML 配置以捕获所有这些:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.Ndef</tech>
<tech>android.nfc.tech.IsoDep</tech>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.NfcB</tech>
<tech>android.nfc.tech.NfcF</tech>
<tech>android.nfc.tech.NfcV</tech>
<tech>android.nfc.tech.Ndef</tech>
<tech>android.nfc.tech.NdefFormatable</tech>
<tech>android.nfc.tech.MifareClassic</tech>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
</resources>
当我靠近标签并且默认标签查看器打开时我收到的消息:
04-20 12:45:26.825 799-2511/? I/ActivityManager: START u0 {flg=0x10008000 cmp=com.android.nfc/.NfcRootActivity (has extras)} from uid 1027 on display 0
04-20 12:45:26.874 1952-24878/? D/NativeNfcTag: Starting background presence check
04-20 12:45:26.913 1952-4642/? W/AudioTrack: AUDIO_OUTPUT_FLAG_FAST denied by client; transfer 4, track 16000 Hz, output 48000 Hz
04-20 12:45:26.917 799-24452/? I/ActivityManager: START u0 {act=android.nfc.action.TECH_DISCOVERED cmp=com.google.android.tag/com.android.apps.tag.TagViewer (has extras)} from uid 1027 on display 0
04-20 12:45:26.947 799-1287/? I/ActivityManager: Start proc 24893:com.google.android.tag/u0a18 for activity com.google.android.tag/com.android.apps.tag.TagViewer
我从@tatianag 那里找到了解决方案:
第一次阅读有关nfc的教程并使用了部分代码。还有一些代码我没有适应你给我的建议。
这是我代码的旧部分
IntentFilter[] filters = new IntentFilter[1];
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_TECH_DISCOVERED);
try {
filters[0].addDataType(MIME_TEXT_PLAIN);
} catch (MalformedMimeTypeException e) {
Log.e("App","Wrong mime")
}
adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
动作错误,哑剧类型。很多错误...我改成
final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);
adapter.enableForegroundDispatch(activity, pendingIntent, null, null);
而且效果很好!我希望它能帮助像你这样的人通过你的解释帮助我。
再次感谢您的宝贵时间!
我已经按照不同的教程阅读了一些与该问题相关的修复程序,但似乎仍然没有任何效果...每当我扫描 NFC 标签时,它都会打开名为 [=25] 的默认 android 应用程序=]Tag Viewer 告诉我“收集了新标签”并且主体是“空标签”,但我的应用程序中没有任何反应.我无法打印任何日志...
这是我的清单:
<activity
android:name=".activityv2.ActivityHome"
android:label="Home"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tag_filter" />
</activity>
这是我的 Activity:
public class ActivityHome extends GenericActivity implements BackHandledFragment.BackHandlerInterface, OnFragmentListener {
private final String TAG = "ActivityHome";
public static final String MIME_TEXT_PLAIN = "text/plain";
@Bind(R.id.drawer_layout)
DrawerLayout mDrawerLayout;
@Bind(R.id.actionToolbar)
Toolbar toolbar;
@Bind(R.id.left_drawer_item)
LinearLayout mDrawerLinear;
@Bind(R.id.left_drawer_child)
ListView mDrawerListChild;
@Bind(R.id.profil_pic)
CircleImageView mProfilPic;
private NfcAdapter mNfcAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_v2_home);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle(getResources().getString(R.string.app_name));
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
// enable ActionBar app icon to behave as action to toggle nav drawer
handleIntent(getIntent());
}
private void handleIntent(Intent intent) {
String action = intent.getAction();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
String type = intent.getType();
if (MIME_TEXT_PLAIN.equals(type)) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
new NdefReaderTask().execute(tag);
} else {
Log.d(TAG, "Wrong mime type: " + type);
}
} else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
// In case we would still use the Tech Discovered Intent
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String[] techList = tag.getTechList();
String searchedTech = Ndef.class.getName();
for (String tech : techList) {
if (searchedTech.equals(tech)) {
new NdefReaderTask().execute(tag);
break;
}
}
}
}
@Override
protected void onNewIntent(Intent intent) {
/**
* This method gets called, when a new Intent gets associated with the current activity instance.
* Instead of creating a new activity, onNewIntent will be called. For more information have a look
* at the documentation.
*
* In our case this method gets called, when the user attaches a Tag to the device.
*/
handleIntent(intent);
}
private class NdefReaderTask extends AsyncTask<Tag, Void, String> {
@Override
protected String doInBackground(Tag... params) {
Tag tag = params[0];
Ndef ndef = Ndef.get(tag);
if (ndef == null) {
// NDEF is not supported by this Tag.
return null;
}
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
NdefRecord[] records = ndefMessage.getRecords();
for (NdefRecord ndefRecord : records) {
if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
try {
return readText(ndefRecord);
} catch (UnsupportedEncodingException e) {
Log.e(TAG, "Unsupported Encoding", e);
}
}
}
return null;
}
private String readText(NdefRecord record) throws UnsupportedEncodingException {
/*
* See NFC forum specification for "Text Record Type Definition" at 3.2.1
*
* http://www.nfc-forum.org/specs/
*
* bit_7 defines encoding
* bit_6 reserved for future use, must be 0
* bit_5..0 length of IANA language code
*/
byte[] payload = record.getPayload();
// Get the Text Encoding
String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
// Get the Language Code
int languageCodeLength = payload[0] & 0063;
// String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
// e.g. "en"
// Get the Text
return new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
}
@Override
protected void onPostExecute(String result) {
if (result != null) {
Log.e(TAG, result);
}
}
}
@Override
protected void onPause() {
super.onPause();
if (mNfcAdapter != null)
stopForegroundDispatch(this, mNfcAdapter);
}
@Override
protected void onResume() {
super.onResume();
if (mNfcAdapter != null)
setupForegroundDispatch(this, mNfcAdapter);
}
@Override
protected void onDestroy() {
getSupportFragmentManager().removeOnBackStackChangedListener(mOnBackStackChangedListener);
super.onDestroy();
}
public static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) {
final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);
IntentFilter[] filters = new IntentFilter[1];
String[][] techList = new String[][]{};
// Notice that this is the same filter as in our manifest.
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
filters[0].addCategory(Intent.CATEGORY_DEFAULT);
try {
filters[0].addDataType(MIME_TEXT_PLAIN);
} catch (IntentFilter.MalformedMimeTypeException e) {
throw new RuntimeException("Check your mime type.");
}
adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
}
public static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) {
adapter.disableForegroundDispatch(activity);
}
}
这里是 XML 配置以捕获所有这些:
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.Ndef</tech>
<tech>android.nfc.tech.IsoDep</tech>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.NfcB</tech>
<tech>android.nfc.tech.NfcF</tech>
<tech>android.nfc.tech.NfcV</tech>
<tech>android.nfc.tech.Ndef</tech>
<tech>android.nfc.tech.NdefFormatable</tech>
<tech>android.nfc.tech.MifareClassic</tech>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
</resources>
当我靠近标签并且默认标签查看器打开时我收到的消息:
04-20 12:45:26.825 799-2511/? I/ActivityManager: START u0 {flg=0x10008000 cmp=com.android.nfc/.NfcRootActivity (has extras)} from uid 1027 on display 0
04-20 12:45:26.874 1952-24878/? D/NativeNfcTag: Starting background presence check
04-20 12:45:26.913 1952-4642/? W/AudioTrack: AUDIO_OUTPUT_FLAG_FAST denied by client; transfer 4, track 16000 Hz, output 48000 Hz
04-20 12:45:26.917 799-24452/? I/ActivityManager: START u0 {act=android.nfc.action.TECH_DISCOVERED cmp=com.google.android.tag/com.android.apps.tag.TagViewer (has extras)} from uid 1027 on display 0
04-20 12:45:26.947 799-1287/? I/ActivityManager: Start proc 24893:com.google.android.tag/u0a18 for activity com.google.android.tag/com.android.apps.tag.TagViewer
我从@tatianag 那里找到了解决方案:
第一次阅读有关nfc的教程并使用了部分代码。还有一些代码我没有适应你给我的建议。
这是我代码的旧部分
IntentFilter[] filters = new IntentFilter[1];
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_TECH_DISCOVERED);
try {
filters[0].addDataType(MIME_TEXT_PLAIN);
} catch (MalformedMimeTypeException e) {
Log.e("App","Wrong mime")
}
adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
动作错误,哑剧类型。很多错误...我改成
final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);
adapter.enableForegroundDispatch(activity, pendingIntent, null, null);
而且效果很好!我希望它能帮助像你这样的人通过你的解释帮助我。
再次感谢您的宝贵时间!