nfc_tag_reader 0.1.0
nfc_tag_reader: ^0.1.0 copied to clipboard
Hand-written Android NFC tag reader for Flutter. Streams scanned tags with decoded NDEF text, URI and raw records over platform channels.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:nfc_tag_reader/nfc_tag_reader.dart';
void main() => runApp(const ExampleApp());
/// A minimal example of the `nfc_tag_reader` plugin: check availability, start a
/// reader session, and list the records of each scanned tag.
///
/// (The `nfc_tag_reader_demo` sibling project shows a more polished, fintech-styled
/// UI built on the same plugin.)
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'nfc_tag_reader example',
theme: ThemeData(colorSchemeSeed: Colors.indigo, useMaterial3: true),
home: const _HomePage(),
);
}
}
class _HomePage extends StatefulWidget {
const _HomePage();
@override
State<_HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<_HomePage> {
final NfcTagReader _nfc = NfcTagReader();
StreamSubscription<NfcTag>? _subscription;
bool _available = false;
bool _scanning = false;
String? _status;
final List<NfcTag> _tags = [];
@override
void initState() {
super.initState();
_refreshAvailability();
_subscription = _nfc.tags.listen(
(tag) => setState(() => _tags.insert(0, tag)),
onError: (Object error) {
final message = error is NfcException ? error.message : '$error';
setState(() => _status = 'Error: $message');
},
);
}
@override
void dispose() {
_subscription?.cancel();
_nfc.stopSession();
super.dispose();
}
Future<void> _refreshAvailability() async {
final available = await _nfc.isAvailable();
setState(() => _available = available);
}
Future<void> _toggleScan() async {
if (_scanning) {
await _nfc.stopSession();
setState(() {
_scanning = false;
_status = 'Stopped.';
});
return;
}
try {
await _nfc.startSession();
setState(() {
_scanning = true;
_status = 'Hold a tag near the phone…';
});
} on NfcException catch (e) {
setState(() => _status = e.message);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('nfc_tag_reader example')),
body: Column(
children: [
ListTile(
leading: Icon(_available ? Icons.nfc : Icons.block),
title: Text('NFC available: $_available'),
subtitle: _status == null ? null : Text(_status!),
trailing: FilledButton(
onPressed: _toggleScan,
child: Text(_scanning ? 'Stop' : 'Scan'),
),
),
const Divider(height: 1),
Expanded(
child: _tags.isEmpty
? const Center(child: Text('No tags scanned yet.'))
: ListView.builder(
itemCount: _tags.length,
itemBuilder: (context, i) {
final tag = _tags[i];
return ListTile(
title: Text('Tag ${tag.id}'),
subtitle: Text(
tag.records.isEmpty
? 'No NDEF records'
: tag.records.map((r) => r.describe()).join('\n'),
),
isThreeLine: tag.records.length > 1,
);
},
),
),
],
),
);
}
}