Skip to content

Commit cf05a25

Browse files
committed
doc: separate streaming to example dir
Signed-off-by: Shengqi Chen <harry-chen@outlook.com>
1 parent 98802be commit cf05a25

File tree

3 files changed

+80
-61
lines changed

3 files changed

+80
-61
lines changed

README.md

Lines changed: 4 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -38,61 +38,6 @@ To use this plugin on Android, you also need to:
3838

3939
* Add [android.permission.NFC](https://developer.android.com/reference/android/Manifest.permission.html#NFC) to your `AndroidManifest.xml`.
4040

41-
By default, to ensure the consistency of cross-platform interactions, we recommend to use the `poll` method to read NFC tags. However, to receive NFC tag events even when your app is in the foreground, you can set up tag event stream support:
42-
43-
1. Create a custom Activity that extends `FlutterActivity` in your Android project:
44-
45-
```kotlin
46-
package your.package.name
47-
48-
import android.app.PendingIntent
49-
import android.content.Intent
50-
import android.nfc.NfcAdapter
51-
import android.nfc.Tag
52-
import io.flutter.embedding.android.FlutterActivity
53-
import im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin
54-
55-
class MainActivity : FlutterActivity() {
56-
override fun onResume() {
57-
super.onResume()
58-
val adapter: NfcAdapter? = NfcAdapter.getDefaultAdapter(this)
59-
val pendingIntent: PendingIntent = PendingIntent.getActivity(
60-
this, 0, Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE
61-
)
62-
// See https://developer.android.com/reference/android/nfc/NfcAdapter#enableForegroundDispatch(android.app.Activity,%20android.app.PendingIntent,%20android.content.IntentFilter[],%20java.lang.String[][]) for details
63-
adapter?.enableForegroundDispatch(this, pendingIntent, null, null)
64-
}
65-
66-
override fun onPause() {
67-
super.onPause()
68-
val adapter: NfcAdapter? = NfcAdapter.getDefaultAdapter(this)
69-
adapter?.disableForegroundDispatch(this)
70-
}
71-
72-
override fun onNewIntent(intent: Intent) {
73-
intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)?.apply(FlutterNfcKitPlugin::handleTag)
74-
}
75-
}
76-
```
77-
78-
2. Update your `AndroidManifest.xml` to use this activity instead of the default Flutter activity.
79-
80-
3. In your Flutter code, listen to the tag event stream:
81-
82-
```dart
83-
@override
84-
void initState() {
85-
super.initState();
86-
// Listen to NFC tag events
87-
FlutterNfcKit.tagStream.listen((tag) {
88-
print('Tag detected: ${tag.id}');
89-
// Process the tag
90-
});
91-
}
92-
```
93-
94-
This will allow your app to receive NFC tag events through a stream, which is useful for scenarios where you need continuous tag reading or want to handle tags even when your app is in the foreground but not actively polling.
95-
9641
### iOS
9742

9843
This plugin now supports Swift package manager, and requires iOS 13+.
@@ -118,3 +63,7 @@ Refer to the [documentation](https://pub.dev/documentation/flutter_nfc_kit/) for
11863
### Error codes
11964

12065
We use error codes with similar meaning as HTTP status code. Brief explanation and error cause in string (if available) will also be returned when an error occurs.
66+
67+
### Operation Mode
68+
69+
We provide two operation modes: polling (default) and event streaming. Both can give the same `NFCTag` object. Please see [example](example/example.md) for more details.

example/example.md

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Example of flutter_nfc_kit
22

3-
## Simple usage
3+
## Polling
4+
5+
This is the default operation mode and is supported on all platforms.
6+
We recommend using this method to read NFC tags to ensure the consistency of cross-platform interactions.
7+
48

59
```dart
610
import 'package:flutter_nfc_kit/flutter_nfc_kit.dart';
@@ -71,6 +75,68 @@ await FlutterNfcKit.finish(iosAlertMessage: "Success");
7175
await FlutterNfcKit.finish(iosErrorMessage: "Failed");
7276
```
7377

78+
## Event Streaming
79+
80+
This is only supported on Android now. To receive NFC tag events even when your app is in the foreground, you can set up tag event stream support by:
81+
82+
1. Create a custom Activity that extends `FlutterActivity` in your Android project:
83+
84+
```kotlin
85+
package your.package.name
86+
87+
import android.app.PendingIntent
88+
import android.content.Intent
89+
import android.nfc.NfcAdapter
90+
import android.nfc.Tag
91+
import io.flutter.embedding.android.FlutterActivity
92+
import im.nfc.flutter_nfc_kit.FlutterNfcKitPlugin
93+
94+
class MainActivity : FlutterActivity() {
95+
override fun onResume() {
96+
super.onResume()
97+
val adapter: NfcAdapter? = NfcAdapter.getDefaultAdapter(this)
98+
val pendingIntent: PendingIntent = PendingIntent.getActivity(
99+
this, 0, Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE
100+
)
101+
// See https://developer.android.com/reference/android/nfc/NfcAdapter#enableForegroundDispatch(android.app.Activity,%20android.app.PendingIntent,%20android.content.IntentFilter[],%20java.lang.String[][]) for details
102+
adapter?.enableForegroundDispatch(this, pendingIntent, null, null)
103+
}
104+
105+
override fun onPause() {
106+
super.onPause()
107+
val adapter: NfcAdapter? = NfcAdapter.getDefaultAdapter(this)
108+
adapter?.disableForegroundDispatch(this)
109+
}
110+
111+
override fun onNewIntent(intent: Intent) {
112+
val tag: Tag? = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
113+
tag?.apply(FlutterNfcKitPlugin::handleTag)
114+
}
115+
}
116+
```
117+
118+
You may also invoke `enableForegroundDispatch` and `disableForegroundDispatch` in other places as needed.
119+
120+
2. Update your `AndroidManifest.xml` to use it as the main activity instead of the default Flutter activity.
121+
122+
3. In Flutter code, listen to the tag event stream and process events:
123+
124+
```dart
125+
@override
126+
void initState() {
127+
super.initState();
128+
// listen to NFC tag events
129+
FlutterNfcKit.tagStream.listen((tag) {
130+
print('Tag detected: ${tag.id}');
131+
// process the tag as in polling mode
132+
FlutterNfcKit.transceive("xxx", ...);
133+
// DO NOT call `FlutterNfcKit.finish` in this mode!
134+
});
135+
}
136+
```
137+
138+
This will allow your app to receive NFC tag events through a stream, which is useful for scenarios where you need continuous tag reading or want to handle tags even when your app is in the foreground but not actively polling.
139+
74140
## GUI Application
75141

76142
See `lib/main.dart` for a GUI application on Android / iOS / web. Skeleton code for specific platforms are not uploaded to <pub.dev>. Please refer to the [GitHub repository](https://github.com/nfcim/flutter_nfc_kit).

lib/flutter_nfc_kit.dart

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,9 @@ class FlutterNfcKit {
281281
EventChannel('flutter_nfc_kit/event');
282282

283283
/// Stream of NFC tag events. Each event is a [NFCTag] object.
284+
///
285+
/// This is only supported on Android.
286+
/// On other platforms, this stream will always be empty.
284287
static Stream<NFCTag> get tagStream {
285288
return _tagEventChannel.receiveBroadcastStream().map((dynamic event) {
286289
final Map<String, dynamic> json = jsonDecode(event as String);
@@ -349,10 +352,11 @@ class FlutterNfcKit {
349352
return NFCTag.fromJson(jsonDecode(data));
350353
}
351354

352-
/// Works only on iOS
353-
/// Calls NFCTagReaderSession.restartPolling()
354-
/// Call this if you have received "Tag connection lost" exception
355-
/// This will allow to reconnect to tag without closing system popup
355+
/// Works only on iOS.
356+
///
357+
/// Calls `NFCTagReaderSession.restartPolling()`.
358+
/// Call this if you have received "Tag connection lost" exception.
359+
/// This will allow to reconnect to tag without closing system popup.
356360
static Future<void> iosRestartPolling() async =>
357361
await _channel.invokeMethod("restartPolling");
358362

@@ -420,7 +424,7 @@ class FlutterNfcKit {
420424
return await _channel.invokeMethod('writeNDEF', {'data': data});
421425
}
422426

423-
/// Finish current session.
427+
/// Finish current session in polling mode.
424428
///
425429
/// You must invoke it before start a new session.
426430
///

0 commit comments

Comments
 (0)