如何通过扫描 NDEF NFC 标签启动应用程序?
How to launch app by scanning NDEF NFC tag?
我正在尝试通过扫描 NFC 标签来启动我的应用程序。我有两个要测试的标签,
- 一个(让我们称之为 "tag A")具有一种 URI 数据类型“http://panasonic.net”和
- 另一个(我们称之为 "tag B")具有两种数据类型——URI(TNF:TNF_WELL_KNOWN 和 RTD:RTD_URI)"urn:nfc:testing.com/ecm/ecap" 和URN(肿瘤坏死因子:TNF_EXTERNAL_TYPE)"urn:nfc:ext:testing.com:ecm".
注意:我的主要目标是让标签 B 正常工作。标签 A 是我的测试标签,它不需要与此应用一起使用。
在我的清单中,我授予了 NFC 权限,并且我在清单中为技术发现列表添加了 XML。
在 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"/>
如果没有 TECH_DISCOVERED
,标签 A 会显示在要自动启动的应用程序列表中,但标签 B 不会显示。使用 TECH_DISCOVERED
,两个标签都显示在列表中。
更正:没有TECH_DISCOVERED
,对于标签A和标签B,该应用程序不会出现在自动启动列表中。但是如果没有 TECH_DISCOVERED
和 <data android:scheme="http" android:host="panasonic.net"/>
,标签 A 确实会让应用程序显示在自动启动列表中。对于标签 A,这是正确的行为,因为当 <data ... android:host="panasonic.net"/>
不存在时 Chrome 接管并自动启动。
接下来,我在 intent-filter 中指定了一些数据标签:
<data android:scheme="http" android:host="panasonic.net"/>
<data android:scheme="http" android:host="fake.com"/>
当扫描标签 A 时,它会让应用程序显示在列表中。扫描标签 B 时,该应用未显示在列表中。这是正确的行为。
然后我将数据标签添加到标签 B 的意图过滤器中:
<data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/com.informationmediary:ecm" />
这是我开始遇到麻烦的地方。我扫描了标签 A 和标签 B,但应用程序并未显示在两者的自动启动列表中。当我删除 HTTP 数据标签只留下 "vnd.android.nfc" 一个并再次扫描标签 B 时,应用程序仍然没有显示。
我还尝试了以下变体但无济于事:
编辑:此时我删除了以下内容,希望标签 B 只起作用:
<data android:scheme="http" android:host="panasonic.net"/>
<data android:scheme="http" android:host="fake.com"/>
1.
<data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/com.informationmediary:ecm" />
2.
<data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/informationmediary.com:ecm" />
3.
<data android:scheme="urn:nfc"
android:host="ext"
android:pathPrefix="/com.informationmediary:ecm" />
4.
<data android:scheme="urn:nfc"
android:host="ext"
android:pathPrefix="/informationmediary.com:ecm" />
5.
<data android:scheme="vnd.android.nfc"
android:host="informationmediary.com"
android:pathPrefix="/ecm/ecap"/>
6.
<data android:scheme="urn:nfc"
android:host="informationmediary.com"
android:pathPrefix="/ecm/ecap"/>
我已经尝试了前四个中的两个与后两个的所有组合:
1&5、1&6、2&5、2&6、3&5、3&6、4&5 和 4&6
我怀疑 scheme="urn:nfc" 但还是尝试了,这次 "grasping at straws"。
标签 B 是我需要工作的标签,标签 A 是我的测试标签。
我已阅读文档 https://developer.android.com/guide/topics/connectivity/nfc/nfc#ext-type
https://developer.android.com/guide/topics/manifest/data-element#mime 和论坛上的其他几篇帖子基本上与 developer.android 景点中的内容相同。
为标签 B 添加 intent 过滤器导致标签 A 不再被拾取
添加数据元素时
<data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/com.informationmediary:ecm" />
到您现有的意图过滤器
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" android:host="panasonic.net" />
<data android:scheme="http" android:host="fake.com" />
</intent-filter>
Android 会将所有数据元素合并为一个。因此,您的意图过滤器
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" android:host="panasonic.net" />
<data android:scheme="http" android:host="fake.com" />
<data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/informationmediary.com:ecm" />
</intent-filter>
意味着 Android 将尝试匹配标签上的 URL,如下所示:
(scheme == "http" OR scheme == "vnd.android.nfc") AND
(host == "panasonic.net" OR host == "fake.com" OR host == "ext") AND
(path startsWith "/informationmediary.com:ecm")
因此,即使未在其他数据元素上明确指定,android:pathPrefix 属性也必须与 URL 匹配。
您可以通过指定两个单独的 Intent 过滤器轻松解决该问题:
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" android:host="panasonic.net" />
<data android:scheme="http" android:host="fake.com" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/informationmediary.com:ecm" />
</intent-filter>
标签 B 与意图过滤器不匹配
只有标签上的第一条记录与意图过滤器匹配。因此,为了匹配外部类型记录,您需要使其成为标签上的第一条记录。然后,如果您的外部类型记录包含 URI "urn:nfc:ext:informationmediary.com:ecm",它将匹配上述意图过滤器。请注意,记录实际上必须仅包含部分 "informationmediary.com:ecm",因为前缀是隐式的。
如果您不能更改标签 B 的内容,则需要将该标签上的 URI 记录与 intent 过滤器相匹配。不幸的是,您在标签 B 上的 URI 不容易与 Android 一起使用。问题是 Android 只能匹配 URL 形式 "scheme://host/path" 的主机和路径(注意斜杠!)。由于您改用 URN,因此它没有主机或路径组件。在这种情况下,您只能尝试自己匹配方案(即 "urn"):
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="urn" />
</intent-filter>
虽然您无法区分 URN 的其余组件(即没有主机或路径组件提供的区分)。
我正在尝试通过扫描 NFC 标签来启动我的应用程序。我有两个要测试的标签,
- 一个(让我们称之为 "tag A")具有一种 URI 数据类型“http://panasonic.net”和
- 另一个(我们称之为 "tag B")具有两种数据类型——URI(TNF:TNF_WELL_KNOWN 和 RTD:RTD_URI)"urn:nfc:testing.com/ecm/ecap" 和URN(肿瘤坏死因子:TNF_EXTERNAL_TYPE)"urn:nfc:ext:testing.com:ecm".
注意:我的主要目标是让标签 B 正常工作。标签 A 是我的测试标签,它不需要与此应用一起使用。
在我的清单中,我授予了 NFC 权限,并且我在清单中为技术发现列表添加了 XML。
在 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"/>
如果没有 TECH_DISCOVERED
,标签 A 会显示在要自动启动的应用程序列表中,但标签 B 不会显示。使用 TECH_DISCOVERED
,两个标签都显示在列表中。
更正:没有TECH_DISCOVERED
,对于标签A和标签B,该应用程序不会出现在自动启动列表中。但是如果没有 TECH_DISCOVERED
和 <data android:scheme="http" android:host="panasonic.net"/>
,标签 A 确实会让应用程序显示在自动启动列表中。对于标签 A,这是正确的行为,因为当 <data ... android:host="panasonic.net"/>
不存在时 Chrome 接管并自动启动。
接下来,我在 intent-filter 中指定了一些数据标签:
<data android:scheme="http" android:host="panasonic.net"/>
<data android:scheme="http" android:host="fake.com"/>
当扫描标签 A 时,它会让应用程序显示在列表中。扫描标签 B 时,该应用未显示在列表中。这是正确的行为。
然后我将数据标签添加到标签 B 的意图过滤器中:
<data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/com.informationmediary:ecm" />
这是我开始遇到麻烦的地方。我扫描了标签 A 和标签 B,但应用程序并未显示在两者的自动启动列表中。当我删除 HTTP 数据标签只留下 "vnd.android.nfc" 一个并再次扫描标签 B 时,应用程序仍然没有显示。
我还尝试了以下变体但无济于事:
编辑:此时我删除了以下内容,希望标签 B 只起作用:
<data android:scheme="http" android:host="panasonic.net"/>
<data android:scheme="http" android:host="fake.com"/>
1.
<data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/com.informationmediary:ecm" />
2.
<data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/informationmediary.com:ecm" />
3.
<data android:scheme="urn:nfc"
android:host="ext"
android:pathPrefix="/com.informationmediary:ecm" />
4.
<data android:scheme="urn:nfc"
android:host="ext"
android:pathPrefix="/informationmediary.com:ecm" />
5.
<data android:scheme="vnd.android.nfc"
android:host="informationmediary.com"
android:pathPrefix="/ecm/ecap"/>
6.
<data android:scheme="urn:nfc"
android:host="informationmediary.com"
android:pathPrefix="/ecm/ecap"/>
我已经尝试了前四个中的两个与后两个的所有组合: 1&5、1&6、2&5、2&6、3&5、3&6、4&5 和 4&6
我怀疑 scheme="urn:nfc" 但还是尝试了,这次 "grasping at straws"。
标签 B 是我需要工作的标签,标签 A 是我的测试标签。
我已阅读文档 https://developer.android.com/guide/topics/connectivity/nfc/nfc#ext-type https://developer.android.com/guide/topics/manifest/data-element#mime 和论坛上的其他几篇帖子基本上与 developer.android 景点中的内容相同。
为标签 B 添加 intent 过滤器导致标签 A 不再被拾取
添加数据元素时
<data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/com.informationmediary:ecm" />
到您现有的意图过滤器
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" android:host="panasonic.net" />
<data android:scheme="http" android:host="fake.com" />
</intent-filter>
Android 会将所有数据元素合并为一个。因此,您的意图过滤器
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" android:host="panasonic.net" />
<data android:scheme="http" android:host="fake.com" />
<data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/informationmediary.com:ecm" />
</intent-filter>
意味着 Android 将尝试匹配标签上的 URL,如下所示:
(scheme == "http" OR scheme == "vnd.android.nfc") AND
(host == "panasonic.net" OR host == "fake.com" OR host == "ext") AND
(path startsWith "/informationmediary.com:ecm")
因此,即使未在其他数据元素上明确指定,android:pathPrefix 属性也必须与 URL 匹配。
您可以通过指定两个单独的 Intent 过滤器轻松解决该问题:
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="http" android:host="panasonic.net" />
<data android:scheme="http" android:host="fake.com" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/informationmediary.com:ecm" />
</intent-filter>
标签 B 与意图过滤器不匹配
只有标签上的第一条记录与意图过滤器匹配。因此,为了匹配外部类型记录,您需要使其成为标签上的第一条记录。然后,如果您的外部类型记录包含 URI "urn:nfc:ext:informationmediary.com:ecm",它将匹配上述意图过滤器。请注意,记录实际上必须仅包含部分 "informationmediary.com:ecm",因为前缀是隐式的。
如果您不能更改标签 B 的内容,则需要将该标签上的 URI 记录与 intent 过滤器相匹配。不幸的是,您在标签 B 上的 URI 不容易与 Android 一起使用。问题是 Android 只能匹配 URL 形式 "scheme://host/path" 的主机和路径(注意斜杠!)。由于您改用 URN,因此它没有主机或路径组件。在这种情况下,您只能尝试自己匹配方案(即 "urn"):
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="urn" />
</intent-filter>
虽然您无法区分 URN 的其余组件(即没有主机或路径组件提供的区分)。