android - 如何通过扫描NDEF NFC标签启动应用程序?

标签 android android-manifest nfc intentfilter ndef

我正在尝试通过扫描 NFC 标签来启动我的应用程序。我有两个标签要测试,

  1. 一个(我们称之为“标签 A”),具有一种 URI 数据类型“http://panasonic.net”和
  2. 另一个(我们称之为“标签 B”)具有两种数据类型 - URI(包含 TNF:TNF_WELL_KNOWN 和 RTD:RTD_URI)“urn:nfc:testing.com/ecm/ecap”和 URN (TNF : TNF_EXTERNAL_TYPE) "urn:nfc:ext:testing.com:ecm"。

注意:我的主要目标是让标签 B 发挥作用。标签 A 是我的测试标签,它不需要与此应用程序一起使用。

在我的 list 中,我授予了 NFC 权限,并在 list 中添加了技术发现列表的 XML。

在 Intent 过滤器标记中,我有以下内容:

<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,这是正确的行为,因为 Chrome 在 <data ... android:host="panasonic.net"/> 时接管并自动启动。不存在。

接下来,我在 Intent 过滤器中指定了一些数据标签:

<data android:scheme="http" android:host="panasonic.net"/>
<data android:scheme="http" android:host="fake.com"/>

扫描标签 A 时,它会使应用程序显示在列表中。扫描标签B时,该应用程序未显示在列表中。这是正确的行为。

然后我将数据标签添加到标签 B 的 Intent 过滤器中:

<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",但还是尝试了一下,这次“捕获了救命稻草”。

标签 B 是我需要工作的标签,标签 A 是我拥有的测试标签。

我已阅读文档 https://developer.android.com/guide/topics/connectivity/nfc/nfc#ext-typehttps://developer.android.com/guide/topics/manifest/data-element#mime以及论坛上的其他几篇帖子基本上与developer.androidsights 中的内容相同。

最佳答案

添加标签 B 的 Intent 过滤器会导致标签 A 不再被选取

当您添加数据元素时

<data android:scheme="vnd.android.nfc"
      android:host="ext"
      android:pathPrefix="/com.informationmediary:ecm" />

到您现有的 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>

Android 会将所有数据元素合并为一个。因此,您的 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" />
    <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 永远不会与 Intent 过滤器匹配

只有标签上的第一条记录与 Intent 过滤器相匹配。因此,为了匹配外部类型记录,您需要将其设为标签上的第一条记录。然后,如果您的外部类型记录包含 URI“urn:nfc:ext:informationmediary.com:ecm”,它将与上述 Intent 过滤器匹配。请注意,该记录实际上必须仅包含“informationmediary.com:ecm”部分,因为前缀是隐式的。

如果您无法更改标签 B 的内容,则需要将该标签上的 URI 记录与 Intent 过滤器相匹配。不幸的是,标签 B 上的 URI 不容易在 Android 中使用。问题是 Android 只能匹配“scheme://host/path”形式的 URL 的主机和路径(注意斜杠!)。由于您使用 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 的其余组件(即不存在由主机或路径组件提供的此类区别)。

关于android - 如何通过扫描NDEF NFC标签启动应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52390003/

相关文章:

android - Mifare 超轻 : lock specific pages

java - 带身份验证的 NTAG212 Mifare Ultralight

java - 动态添加 TextInputLayout 抛出异常

android - 0 台设备支持的应用

android - 如何像卡拉OK应用一样从歌曲中删除声音或人声?

java - 在android中实现保存按钮

android - 发现 APK : AndroidManifest. xml 的重复文件

android - APDU 命令使用三星 Galaxy S4 从支持 visa Paywave NFC 的卡中读取信用卡数据

Android Jetpack Compose TextField 禁用键盘自动建议

java - 位图大小超过 Vm 预算错误 android