如何通过扫描NDEF NFC标签启动应用?

时间:2018-09-18 15:29:24

标签: android android-manifest nfc intentfilter ndef

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

  1. 具有一个URI数据类型为“ http://panasonic.net”的一个(以下称为“标签A”)和
  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是我的测试标签,不需要与此应用一起使用。

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

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

<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”,但无论如何都尝试过,这次是“抓稻草”。

标签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的景点说的一样。

1 个答案:

答案 0 :(得分:2)

为标签B添加意图过滤器会导致不再获取标签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记录与意图过滤器进行匹配。不幸的是,Android上不容易使用标签B上的URI。问题是Android只能匹配形式为“ scheme:// host / path”的URL的主机和路径(请注意斜杠!)。由于使用的是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的其余部分(即,主机或路径组件没有提供这种区分)。