我目前正在为Android编写几个支持NFC的应用程序,并希望了解如何阻止我的应用程序进入“选择应用程序”列表,只要从启动器或非NFC扫描标签时该列表就会打开应用程序。我只希望我的应用能够在打开时阅读标签。
我目前的意图过滤器:
<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.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<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_tech_filter" />
nfc_tech_filter.xml:
<tech-list>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.Ndef</tech>
</tech-list>
答案 0 :(得分:2)
您目前在应用的清单中有几个与NFC相关的意图过滤器:
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
通过将此类意图过滤器添加到应用的清单中,您可以指示某些活动应该启动(或者如果在同一意图中注册了多个活动,则在意图选择器中显示为选项)这些NFC标签发现事件。
因此,如果您不希望您的应用可以通过这些意图启动,则需要从 AndroidManifest.xml 中删除这些意图过滤器。
然而,当你的应用程序的活动在前台时,你也会失去监听这些意图的能力。由于NFC意图是活动意图,因此您无法通过动态注册的广播接收器接收它们(参见RubbelDieKatz的回答)。相反,Android API提供了另外的方法来捕获NFC相关事件,同时您的应用程序的活动显示在前台(这也允许您的应用程序优先于其他应用程序,这是基于清单的NFC意图过滤器无法实现的):
自API级别10(基本上自Android NFC开始以来),Android具有前台调度系统。您可以在NfcAdapter.enableForegroundDispatch()
上使用onResume()
方法注册前台活动以接收NFC事件(当您的活动失去焦点onPause()
时,不要忘记取消注册):
public void onResume() {
super.onResume();
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
adapter.enableForegroundDispatch(this, pendingIntent, null, null);
}
public void onPause() {
super.onPause();
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
adapter.disableForegroundDispatch(this);
}
您甚至可以通过向enableForegroundDispatch()
提供可选的技术列表和intent-filters参数来注册以仅接收特定的NFC发现事件子集。
使用前台调度系统注册活动后,您将通过onNewIntent()
回调接收NFC事件:
public void onNewIntent(Intent intent) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
...
}
从API级别19开始,有新的NFC阅读器模式API。您现在可以注册接收常规回调(而不是通过意图调度,有时会导致soome hickup)。您可以使用方法NfcAdpater.enableReaderMode()
:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
adapter.enableReaderMode(this, this, NfcAdapter.FLAG_READER_NFC_A, null);
}
除了(或代替)NfcAdapter.FLAG_READER_NFC_A
之外,通过使用其他标志,您可以设置为阅读器模式以收听其他标签技术。
然后,您将在标记发现时收到回调(接收方需要实现回调接口NfcAdapter.ReaderCallback
):
public void onTagDiscovered(Tag tag) {
...
}
另请参阅What's the difference between enableReaderMode and enableForegroundDispatch?以了解两个选项之间的更详细比较。
答案 1 :(得分:1)
您正在使用NFC and Tech Discovered intent-filters
。您可以删除它们并在您的应用程序中以编程方式注册目标侦听器。
<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.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
关于注册意图:Here's a very good answer。
在
onCreate
方法中,您可以注册这样的接收器:private BroadcastReceiver receiver; @Override public void onCreate(Bundle savedInstanceState){ // your oncreate code should be IntentFilter filter = new IntentFilter(); filter.addAction("SOME_ACTION"); filter.addAction("SOME_OTHER_ACTION"); receiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { //do something based on the intent's action } }; registerReceiver(receiver, filter); }
请记住在
onDestroy
方法中运行:@Override protected void onDestroy() { if (receiver != null) { unregisterReceiver(receiver); receiver = null; } super.onDestroy(); }
下面的答案另一个有趣的引用:
人们忘记提到的一个重点是生命的时间
Broadcast Receiver
。程序上的差异 通过 AndroidManifest.xml 注册来注册它就是这样。 在清单文件中,它不依赖于应用程序的生命周期。 虽然以编程方式注册它确实依赖于 应用寿命。这意味着如果您注册 AndroidManifest.xml ,即使应用程序未运行,您也可以捕获广播的意图。修改:Android 3.1中提到的注释不再适用,Android系统默认情况下排除所有接收方接收意图 如果用户从未启动相应的应用程序或 如果用户通过Android菜单明确停止了应用程序 (在管理→应用程序中)。 https://developer.android.com/about/versions/android-3.1.html
这是一个额外的安全功能,因为用户可以确定 只有他开始的应用程序才会收到广播意图。
因此可以理解为以编程方式注册的接收器 应用程序的
onCreate()
与声明的效果相同 在Android 3.1上面的 AndroidManifest.xml 中。
如果您在活动被杀时取消注册您的接收器,您的应用程序将不再接收这些广播。