How can I open an app via NFC and pass embedded data in the same action?

1,317

I know the reason for your problem but not the solution for your problem in Flutter (I know the solution in Java), but hopefully this answer will point you in the right direction.

When your App is in running in the foreground there are two ways the System NFC App sends you data about the NFC Tag it has detected.

The new enableReaderMode better API use a Callback onTagDiscovered to handle the data.

The old enableForgroundDispatch API pauses and resumes your App to send it an Intent that contains data about the NFC Tag and this is handled by the onNewIntent method.

The nfc_in_flutter package handles both of these methods for you BUT it does not handle when your App is started by the System NFC App.

When your App is not running and the System NFC App see an NFC Tag it reads the Tag to identify the Type and data content and generates an Intent (Much like the Intent format used for the enableForgroundDispatch API, it then looks at the Manifest to see which App handles this type of Intent as shares it with the App.
The difference is that onNewIntent method is only called on App Restart not on App Start.

Normally in Java in your onCreate method you would call getIntent() to get the Intent your Activity was started with and then call directly the method that processes the NFC Intents (so you could use the code in onCreate like onNewIntent(getIntent()); to process the incoming shared data)

So when you App is started by the reading of an NFC Tag the mechanism more like one Android Activity sharing data with another Android Activity than it is actually to do with NFC reading.

Thus in flutter getting data from the NFC Tag that was read when your App was not running is more about receiving "sharing" Intents and this post might help you https://muetsch.io/how-to-receive-sharing-intents-in-flutter.html

Share:
1,317
Dumpster Fire
Author by

Dumpster Fire

Updated on November 28, 2022

Comments

  • Dumpster Fire
    Dumpster Fire over 1 year

    I'm new to both android and NFC, and trying to make a simple little Flutter relay app which takes json data embedded on an NFC tag and executes the action described. ie:

    1. Tap my phone on this NFC sticker
    2. Open my flutter app
    3. Automatically pass the json data to some function which can read and execute the instructions.

    My issue is that I can do #2, or #3, but not with the same NFC scan. If I scan with the app closed, it opens my app, but doesn't hit my NFC listening function in the MyApp.build. If the app is already foreground it will hit it, but that limits the value.

    NFC Tag (via NFC Tools)

    DATA
    {"action" : "Do the thing and you will have the power."}
    FORMAT
    Media (0x02)
    Defined by RFC 2046
    TYPE
    application/json
    

    AndroidManifest.xml

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

    MainActivity.kt

    package com.example.package
    
    import io.flutter.embedding.android.FlutterActivity
    
    import android.content.Intent;
    import android.os.Bundle;
    
    class MainActivity: FlutterActivity() {
    }
    

    main.dart (using nfc_in_flutter)

    import 'package:flutter/material.dart';
    import 'package:nfc_in_flutter/nfc_in_flutter.dart';
    
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        var stream = NFC.readNDEF();
    
        stream.listen((NDEFMessage message) {
          for (var record in message.records) {
            print("Payload: ${record.payload}"); // This works when foregrounded
          }
        });
    
        return MaterialApp(
          title: 'Material App',
          home: Scaffold(
            appBar: AppBar(
              title: Text('Material App Bar'),
            ),
            body: Text("Foo"),
          ),
        );
      }
    }