gpt4 book ai didi

android - 如何在 Kivy + Python 中读取 NFC 标签?

转载 作者:太空宇宙 更新时间:2023-11-03 13:48:38 24 4
gpt4 key购买 nike

我正在尝试读取 NFC 标签,如果标签只有文本,则读取很顺利。但是,如果标签包含 URL 或为空,则它不起作用。我认为问题出在 nfc_filter.xml 文件上。

<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:mimeType="*/*" />
</intent-filter>

Python代码:

def nfc_init(self):
activity.bind(on_new_intent=self.on_new_intent)
self.j_context = context = PythonActivity.mActivity
self.nfc_adapter = NfcAdapter.getDefaultAdapter(context)
self.nfc_pending_intent = PendingIntent.getActivity(context, 0, Intent(context, context.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0)
return True

def on_new_intent(self, intent):
print 'on_new_intent()', intent.getAction()
# get TAG details
tag = cast('android.nfc.Tag', intent.getParcelableExtra(NfcAdapter.EXTRA_TAG))
details = self.get_ndef_details(tag)

def on_pause(self):
print 'paused'
return True

def on_resume(self):
print 'resumed'

我想要的是,当我的应用程序处于 Activity 状态并且您读取了 NFC 标签时,它总是会收到 Intent 。现在我可以在日志中看到它不会从 on_pause 恢​​复,以防标签包含文本以外的内容或为空。

有人可以帮我解决这个问题吗?

最佳答案

由于 list 中的 Intent 过滤器,您的应用当前接收 NFC 事件:

<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/>
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:mimeType="*/*" />
</intent-filter>

这个 Intent 过滤器有几个问题:

  1. 此意向过滤器将匹配具有意向操作 TAG_DISCOVERED 的意向, NDEF_DISCOVERED , 或 TECH_DISCOVERED , and 同时包含类别 DEFAULT 或 BROWSABLE, and 同时包含任何(?) MIME 类型。

    问题是只有 NDEF_DISCOVERED intent 可能包含 MIME 类型。因此,TAG_DISCOVEREDTECH_DISCOVERED永远不会匹配。

  2. MIME 类型 */* (即匹配任何 MIME 类型)不会(不应该?)在 list Intent 过滤器中工作,因为只有子类型部分(即斜杠后的部分)可能包含通配符 (*)。参见 android:mimeType .

  3. 类别 BROWSABLE 是无用的,因为任何 NFC Intent 都不会包含该类别。

  4. NDEF_DISCOVERED包含 URL 的标签的 Intent 不包含 MIME 类型。由于您限制了 NDEF_DISCOVERED Intent 过滤器到包含 MIME 类型的 Intent ,它不会匹配包含 URL 的 Intent 。

  5. TECH_DISCOVERED Intent 过滤器需要声明一个技术列表 XML 文件。

因此,您需要更改 Intent 过滤器以匹配您的标签。如果你想匹配任何 NDEF 格式的标签,你可以简单地使用 intent 过滤器:

<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>

但是,这有一些限制:任何注册了更具体 NDEF_DISCOVERED 的应用程序intent(例如包含 MIME 类型过滤器或 URL 过滤器的)将优先于您的应用程序,您将不会收到该 intent。此外,有报道称 NDEF_DISCOVERED没有 <data ...> 的 Intent 过滤器不适用于某些设备。

因此,为了匹配 MIME 类型和 URL,您可能需要使用更具体的 Intent 过滤器,例如为了匹配所有 text/ , image/ , 和 application/ MIME 类型、所有 HTTP(S) URL 和所有 NFC 论坛外部类型:

<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/*" />
<data android:mimeType="image/*" />
<data android:mimeType="application/*" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" />
<data android:scheme="https" />
<data android:scheme="vnd.android.nfc" android:host="ext" android:pathPrefix="/" />
</intent-filter>

不过,如果其他一些应用注册了更具体的 Intent 过滤器,您的应用将不会收到任何符合这些“更具体”标准的 Intent(参见 How NFC Tags are Dispatched to Applications)。

如果您的应用还应收到有关非 NDEF 格式标签的通知,您可以使用 TECH_DISCOVERED Intent 过滤器(请注意,无需为此特定 Intent 过滤器指定任何类别)。在这种情况下,您还需要声明一个 XML 资源文件,其中包含应匹配的技术列表(声明必须在 <intent-filter ... /> 元素之外!):

<intent-filter>
<action android:name="android.nfc.action.TECH_DISCOVERED" />
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter" />

您还需要一个 XML 资源 nfc_tech_filter.xml (放置在 res/xml/ 下)。为了匹配任何标签,您可以使用:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.NfcA</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NfcB</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NfcF</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NfcV</tech>
</tech-list>
<tech-list>
<tech>android.nfc.tech.NfcBarcode</tech>
</tech-list>
</resources>

最后,不要使用 TAG_DISCOVERED list 中的 Intent 过滤器,除非你真的知道它的所有含义(特别是在用户体验和用户期望方面)。此 Intent 过滤器只是 API 级别 9(在 Android 2.3.3 之前)的兼容模式,其中 NFC 支持非常非常有限,并且是一种后备模式,可用于创建处理任何不支持的 NFC 标签的应用程序其他应用。

检测前台应用中的标签

由于您写道您希望您的应用始终接收这些 Intent “当它处于 Activity 状态并且您读取 NFC 标签时”,您可能需要考虑从 list 中完全删除 Intent 过滤器并使用前台调度系统代替。在这种情况下,您的应用将不会在读取 NFC 标签时启动,但它会收到所有 NFC 发现事件,并且它会优先于所有 其他应用程序,同时它在前台。

您可以通过简单地将其添加到您的应用程序中来做到这一点(尽管不太确定 Python 语法):

def on_pause(self):
print 'paused'
self.nfc_adapter.disableForegroundDispatch(PythonActivity.mActivity)
return True

def on_resume(self):
print 'resumed'
self.nfc_adapter.enableForegroundDispatch(PythonActivity.mActivity, self.nfc_pending_intent, None, None)

关于android - 如何在 Kivy + Python 中读取 NFC 标签?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37953101/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com