Flutter使用sms_advanced调用querySms报MissingPluginException求助
问题解决:sms_advanced插件MissingPluginException异常
异常详情
调用querySms()方法读取短信时,触发以下异常:
Unhandled Exception: MissingPluginException(No implementation found for method getSent on channel plugins.elyudde.com/querySMS)
已确认readSmsMessages()函数已执行,但因异常中断。
解决步骤
清理重建项目
执行以下命令清理缓存并重新构建,插件未正确链接到原生端是此类异常的常见原因:flutter clean flutter pub get flutter run检查版本兼容性
查看pubspec.yaml中sms_advanced的版本,确认其与当前Flutter SDK版本兼容。若存在版本不匹配,尝试升级或降级插件后重新执行flutter pub get。验证原生权限配置
- Android:确保
android/app/src/main/AndroidManifest.xml中添加短信读取权限:<uses-permission android:name="android.permission.READ_SMS"/> - iOS:在
ios/Runner/Info.plist中添加短信权限描述:<key>NSMessagesUsageDescription</key> <string>需要读取短信以追踪交易记录</string>
- Android:确保
临时替换方法排查问题
暂时将querySms调用替换为getAllSms,验证是否能正常获取短信:// 替换原querySms调用 final List<SmsMessage> messages = await query.getAllSms;如果此方法正常运行,说明
querySms方法可能存在版本兼容问题,可考虑改用其他方式筛选短信。重启开发环境
重启IDE(如Android Studio/VS Code)以及模拟器或真机,清除缓存异常后重新运行项目。
相关代码参考
导入语句
import 'package:expense_tracker/database_helper.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'transaction_screen.dart'; import 'profile_screen.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:sms_advanced/sms_advanced.dart';
MyApp类
class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Expense Tracker', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), home: const HomeScreen(), ); } } class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override State<HomeScreen> createState() => _HomeScreenState(); }
HomeScreenState类
class _HomeScreenState extends State<HomeScreen> { static const platform = MethodChannel('com.example.expense_tracker/notifications'); String _transactionMessage = 'No transactions yet.'; int _selectedIndex = 0; List<Map<String, dynamic>> transactions = []; @override void initState() { super.initState(); _startNotificationListener(); requestSmsPermission(); readSmsMessages(); fetchAndDisplayTransactions(); } void readSmsMessages() async { debugPrint("readSmsMessages called"); final SmsQuery query = SmsQuery(); // final List<SmsMessage> messages = await query.getAllSms; List<SmsQueryKind> kinds = [SmsQueryKind.Inbox, SmsQueryKind.Sent]; final List<SmsMessage> messages = await query.querySms(kinds: kinds); debugPrint("messages length: ${messages.length}"); if (messages.isNotEmpty) { debugPrint("if"); for (var message in messages) { if (isUpiTransaction(message.body.toString())) { // Extract relevant data (amount, transaction ID, etc.) setState(() { _transactionMessage = message.body.toString(); storeTransaction(extractTransactionData(_transactionMessage)); debugPrint(_transactionMessage); }); } } } } Map<String, dynamic> extractTransactionData(String messageBody) { // Use regex or pattern matching to extract data from message RegExp amountPattern = RegExp(r'(\d+(\.\d{1,2})?)'); RegExp transactionIdPattern = RegExp(r'Transaction ID: (\w+)'); String? amount = amountPattern.firstMatch(messageBody)?.group(0); String? transactionId = transactionIdPattern.firstMatch(messageBody)?.group(1); return { 'amount': amount, 'transactionId': transactionId, 'message': messageBody, }; } bool isUpiTransaction(String messageBody) { // Simple keyword check for UPI-related SMS return messageBody.contains('credited') || messageBody.contains('debited'); } Future<void> _startNotificationListener() async { try { await platform.invokeMethod('startNotificationListener'); } on PlatformException catch (e) { debugPrint("e.message: ${e.message}"); } platform.setMethodCallHandler((call) async { if (call.method == 'notifyTransaction') { String transactionData = call.arguments; setState(() { _transactionMessage = transactionData; debugPrint(_transactionMessage); }); } }); } Future<void> requestSmsPermission() async { var status = await Permission.sms.status; if (!status.isGranted) { await Permission.sms.request(); } } void _onItemTapped(int index) { setState(() { _selectedIndex = index; }); } void storeTransaction(Map<String, dynamic> transactionData) async { await DatabaseHelper.instance.insertTransaction(transactionData); } Future<List<Map<String, dynamic>>> fetchAndDisplayTransactions() async { List<Map<String, dynamic>> dbtransactions = await DatabaseHelper.instance.getTransactions(); transactions = dbtransactions; return dbtransactions; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Expense Tracker'), ), body: IndexedStack( index: _selectedIndex, children: [ TransactionScreen( transactions: transactions, ), const ProfileScreen(), ], ), bottomNavigationBar: BottomNavigationBar( items: const <BottomNavigationBarItem>[ BottomNavigationBarItem( icon: Icon(Icons.list), label: 'Transactions', ), BottomNavigationBarItem( icon: Icon(Icons.person), label: 'Profile', ), ], currentIndex: _selectedIndex, selectedItemColor: Colors.blue, onTap: _onItemTapped, ), ); } }
内容的提问来源于stack exchange,提问作者Shashwat Srivastava
相关产品推荐
相关产品推荐

