Android NFC 在启动应用程序时传递单个参数

Android NFC passing single parameter when starting application

我想启动一个使用 NFC 标签的应用程序。我按照 Start Android application from NFC-tag with extra data 中所述或通过使用 NDEF_DISCOVERED / TECH_DISCOVERED intent 使用 android 应用程序记录 (AAR) 使该部分工作过滤器。但是如何在通过 NFC 事件启动它时将数据从 NFC 标签(例如一些文本)传递到我的 activity?

我已经通读了NFC Basics,但据我了解,它似乎想实现一种读取标签的机制,当我真的不想重新读取标签时app是通过标签打开的,而我只想同时传入数据

此外,这些机制似乎允许应用程序在标签启动后读取标签。换句话说,我担心如果有人稍后在应用程序已经打开时点击该标签,该标签将被再次读取(这是我所做的 而不是 想要的)。

其次,如何创建这样的NDEF消息?

Android会自动读取NFC标签的NDEF报文并进行处理,以便

  • 根据第一个 NDEF 记录开始注册活动,并且
  • 根据 NDEF 消息中任意位置的 Android 应用程序记录 (AAR) 启动应用程序。

为了启动您的 activity 并让 Android 传递预读 NDEF 消息,您可以使用 NDEF_DISCOVERED 意图过滤器:

<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="/example.com:mycustomtype"/>
</intent-filter>

然后在您的 activity 中,您可以处理该 ND​​EF 消息:

public void onResume() {
    super.onResume();
    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
        NdefMessage[] msgs = null;
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (rawMsgs != null) {
            msgs = new NdefMessage[rawMsgs.length];
            for (int i = 0; i < rawMsgs.length; ++i) {
                msgs[i] = (NdefMessage)rawMsgs[i];
            }
        }

        if ((msgs != null) && (msgs.length > 0)) {
            NdefRecord[] records = msgs[0].getRecords();
            NdefRecord firstRecord = records[0];
            byte[] payloadData = firstRecord.getPayload();

            // do something with the payload (data passed through your NDEF record)
            // or process remaining NDEF message

        }
    }
}

请注意,只要您的 activity 成为前景 activity,onResume() 就是 运行。因此,同一个标签可能 运行 多次。因此,您可以使用其他生命周期方法或采取一些预防措施,以免多次解析消息。

如果您想删除所有进一步的 NFC 事件,一旦您的 activity 打开,您可以按照我在回复 Android app enable NFC only for one Activity 时描述的方法进行操作。因此,您将注册前台调度(这使您 activity 优先接收 NFC 事件,然后您可以简单地 删除 这些事件。

public void onResume() {
    super.onResume();
    NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
    nfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null);
}

public void onPause() {
    super.onPause();
    NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
    nfcAdapter.disableForegroundDispatch(this);
}

public void onNewIntent(Intent intent) {
    if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
        // drop NFC events
    }
}

最后,要为您的 NFC 标签创建 NDEF 消息,您可以这样做:

byte[] payload = ...  // generate your data payload
NdefMessage msg = new NdefMessage(
    NdefRecord.createExternal("example.com", "mycustomtype", payload)
)

如果您想确保只有您的应用程序通过此标签启动(或者如果您的应用程序未安装 Play 商店已打开),您还可以添加一个 AAR:

NdefMessage msg = new NdefMessage(
    NdefRecord.createExternal("example.com", "mycustomtype", payload),
    NdefRecord.createApplicationRecord("com.example.your.app.package")
)