nfc_in_flutter 2.0.0 nfc_in_flutter: ^2.0.0 copied to clipboard
Flutter plugin to read and write NFC tags on both Android and iOS. Currently it only supports reading NDEF formatted tags.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:nfc_in_flutter/nfc_in_flutter.dart';
import './read_example_screen.dart';
import './write_example_screen.dart';
void main() => runApp(ExampleApp());
class ExampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text("NFC in Flutter examples"),
),
body: Builder(builder: (context) {
return ListView(
children: <Widget>[
ListTile(
title: const Text("Read NFC"),
onTap: () {
Navigator.pushNamed(context, "/read_example");
},
),
ListTile(
title: const Text("Write NFC"),
onTap: () {
Navigator.pushNamed(context, "/write_example");
},
),
],
);
}),
),
routes: {
"/read_example": (context) => ReadExampleScreen(),
"/write_example": (context) => WriteExampleScreen(),
},
);
}
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
// _stream is a subscription to the stream returned by `NFC.read()`.
// The subscription is stored in state so the stream can be canceled later
StreamSubscription<NDEFMessage> _stream;
// _tags is a list of scanned tags
List<NDEFMessage> _tags = [];
bool _supportsNFC = false;
// _readNFC() calls `NFC.readNDEF()` and stores the subscription and scanned
// tags in state
void _readNFC(BuildContext context) {
try {
// ignore: cancel_subscriptions
StreamSubscription<NDEFMessage> subscription = NFC.readNDEF().listen(
(tag) {
// On new tag, add it to state
setState(() {
_tags.insert(0, tag);
});
},
// When the stream is done, remove the subscription from state
onDone: () {
setState(() {
_stream = null;
});
},
// Errors are unlikely to happen on Android unless the NFC tags are
// poorly formatted or removed too soon, however on iOS at least one
// error is likely to happen. NFCUserCanceledSessionException will
// always happen unless you call readNDEF() with the `throwOnUserCancel`
// argument set to false.
// NFCSessionTimeoutException will be thrown if the session timer exceeds
// 60 seconds (iOS only).
// And then there are of course errors for unexpected stuff. Good fun!
onError: (e) {
setState(() {
_stream = null;
});
if (!(e is NFCUserCanceledSessionException)) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text("Error!"),
content: Text(e.toString()),
),
);
}
});
setState(() {
_stream = subscription;
});
} catch (err) {
print("error: $err");
}
}
// _stopReading() cancels the current reading stream
void _stopReading() {
_stream?.cancel();
setState(() {
_stream = null;
});
}
@override
void initState() {
super.initState();
NFC.isNDEFSupported.then((supported) {
setState(() {
_supportsNFC = true;
});
});
}
@override
void dispose() {
super.dispose();
_stream?.cancel();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primarySwatch: Colors.grey,
),
home: Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
title: const Text('NFC in Flutter'),
actions: <Widget>[
Builder(
builder: (context) {
if (!_supportsNFC) {
return FlatButton(
child: Text("NFC unsupported"),
onPressed: null,
);
}
return FlatButton(
child:
Text(_stream == null ? "Start reading" : "Stop reading"),
onPressed: () {
if (_stream == null) {
_readNFC(context);
} else {
_stopReading();
}
},
);
},
),
IconButton(
icon: Icon(Icons.clear_all),
onPressed: () {
setState(() {
_tags.clear();
});
},
tooltip: "Clear",
),
],
),
// Render list of scanned tags
body: ListView.builder(
itemCount: _tags.length,
itemBuilder: (context, index) {
const TextStyle payloadTextStyle = const TextStyle(
fontSize: 15,
color: const Color(0xFF454545),
);
return Padding(
padding: const EdgeInsets.fromLTRB(20, 10, 20, 10),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
const Text("NDEF Tag",
style: const TextStyle(fontWeight: FontWeight.bold)),
Builder(
builder: (context) {
// Build list of records
List<Widget> records = [];
for (int i = 0; i < _tags[index].records.length; i++) {
records.add(Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
"Record ${i + 1} - ${_tags[index].records[i].type}",
style: const TextStyle(
fontSize: 13,
color: const Color(0xFF666666),
),
),
Text(
_tags[index].records[i].payload,
style: payloadTextStyle,
),
Text(
_tags[index].records[i].data,
style: payloadTextStyle,
),
],
));
}
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: records,
);
},
)
],
),
);
},
),
),
);
}
}