fundstrack_lite 0.0.8
fundstrack_lite: ^0.0.8 copied to clipboard
A Flutter plugin to extract and parse debit/credit bank SMS on Android. Supports UPI and bank notifications.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:fundstrack_lite/fundstrack_lite.dart';
void main() {
runApp(const BankSmsApp());
}
class BankSmsApp extends StatelessWidget {
const BankSmsApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Bank SMS Parser',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blueAccent),
useMaterial3: true,
),
home: const BankSmsScreen(),
);
}
}
class BankSmsScreen extends StatefulWidget {
const BankSmsScreen({super.key});
@override
State<BankSmsScreen> createState() => _BankSmsScreenState();
}
class _BankSmsScreenState extends State<BankSmsScreen> {
List<Map<String, dynamic>>? _smsList;
String? _error;
bool _loading = true;
@override
void initState() {
super.initState();
_loadSms();
}
Future<void> _loadSms() async {
setState(() {
_loading = true;
_error = null;
});
try {
// Fetch all transaction SMS, header argument is ignored in plugin
final smsList = await FundstrackLite.getBankSms([]);
setState(() {
_smsList = smsList;
_loading = false;
});
} catch (e) {
setState(() {
_error = e.toString();
_loading = false;
});
}
}
@override
Widget build(BuildContext context) {
Widget body;
if (_loading) {
body = const Center(child: CircularProgressIndicator());
} else if (_error != null) {
body = Center(child: Text('Error: $_error'));
} else if (_smsList == null || _smsList!.isEmpty) {
body = const Center(child: Text('No debit/credit SMS found.'));
} else {
body = _smsListView(_smsList!);
}
return Scaffold(
appBar: AppBar(
title: const Text('Bank SMS Parser'),
actions: [
IconButton(icon: const Icon(Icons.refresh), onPressed: _loadSms),
],
),
body: body,
);
}
Widget _smsListView(List<Map<String, dynamic>> smsList) {
return ListView.separated(
itemCount: smsList.length,
separatorBuilder: (_, __) => Divider(),
itemBuilder: (context, index) {
final sms = smsList[index];
final DateTime smsTime = DateTime.fromMillisecondsSinceEpoch(
(sms['smsTimestamp'] ?? 0) is int
? sms['smsTimestamp'] ?? 0
: int.tryParse(sms['smsTimestamp']?.toString() ?? '0') ?? 0,
);
final dateStr =
(sms['date'] != null && (sms['date'] as String).isNotEmpty)
? sms['date']
: "${smsTime.day.toString().padLeft(2, '0')}/${smsTime.month.toString().padLeft(2, '0')}/${smsTime.year}";
final timeStr =
(sms['time'] != null && (sms['time'] as String).isNotEmpty)
? sms['time']
: "${smsTime.hour.toString().padLeft(2, '0')}:${smsTime.minute.toString().padLeft(2, '0')}";
return Card(
margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
elevation: 2,
child: Padding(
padding: const EdgeInsets.all(14.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Amount: ${sms['amount'] ?? '--'}",
style: const TextStyle(
fontWeight: FontWeight.bold,
fontSize: 16,
),
),
Text("Account Number: ${sms['account'] ?? '--'}"),
Text("Type: ${sms['type'] ?? '--'}"),
Text("Sender: ${sms['sender'] ?? '--'}"),
Text("Date: $dateStr"),
Text("Time: $timeStr"),
// Uncomment below to show full SMS
// Text("Full SMS: ${sms['body'] ?? ''}", style: TextStyle(color: Colors.grey.shade600, fontSize: 12)),
],
),
),
);
},
);
}
}