You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter应用无READ SMS权限时控制台打印异常问题求助

问题描述

我编写了如下Flutter代码,希望在应用没有读取SMS权限时控制台打印“no permission”,但运行时报错:

SmsQuery query = new SmsQuery();
List<SmsMessage> AllMessages = [];
Timer? _timer;
var SMSPermStatus = Permission.sms.status;

  @override
  void initState() {
    if (SMSPermStatus.isDenied == true) {
      print("give me read SMS perm");
    } else {
    _timer = Timer.periodic(const Duration(seconds: 1), (Timer t) {
      try {
        GetAllMessages();
      } catch(e) {
        print("give me read SMS perm");
      }
      print("refreshed");
      print(AllMessages); // []
    });
    }
    super.initState();
  }
  Future<void> GetAllMessages() async {
    List<SmsMessage> messages = await query.querySms(
      kinds: [SmsQueryKind.inbox],
      count: 50,
    );
    setState(() {
      AllMessages = messages;
    });
  }

报错截图:
报错截图

请问该如何解决这个错误?


解决方案

你的代码存在两个核心问题,导致权限判断失效并触发报错:

1. 错误处理异步权限状态

Permission.sms.status返回的是Future<PermissionStatus>,并非直接的权限状态值。你直接调用SMSPermStatus.isDenied,本质是对Future对象访问不存在的属性,这会直接引发错误。必须通过await在异步环境中获取真实的权限状态。

2. 未正确捕获异步异常

GetAllMessages()是异步方法,你在try块中直接调用却未使用await,导致异步抛出的异常无法被当前catch块捕获。

修正后的完整代码

SmsQuery query = SmsQuery();
List<SmsMessage> allMessages = [];
Timer? _timer;

@override
void initState() {
  _initPermissionAndTimer();
  super.initState();
}

// 异步处理权限与定时器初始化
Future<void> _initPermissionAndTimer() async {
  final permissionStatus = await Permission.sms.status;
  
  if (permissionStatus.isDenied) {
    print("no permission");
    // 可选:主动请求权限
    // final requestResult = await Permission.sms.request();
    // if (requestResult.isGranted) _startMessageTimer();
  } else {
    _startMessageTimer();
  }
}

void _startMessageTimer() {
  _timer = Timer.periodic(const Duration(seconds: 1), (Timer t) async {
    try {
      await getAllMessages(); // 使用await捕获异步异常
    } catch (e) {
      print("no permission");
      // 可选:捕获异常后停止定时器
      // t.cancel();
    }
    print("refreshed");
    print(allMessages);
  });
}

Future<void> getAllMessages() async {
  final messages = await query.querySms(
    kinds: [SmsQueryKind.inbox],
    count: 50,
  );
  setState(() {
    allMessages = messages;
  });
}

@override
void dispose() {
  _timer?.cancel(); // 页面销毁时取消定时器,避免内存泄漏
  super.dispose();
}

额外优化说明

  • 遵循Dart命名规范:变量和方法名采用小驼峰格式(如allMessages、getAllMessages)
  • 在dispose方法中取消定时器,防止页面销毁后定时器持续运行引发内存泄漏
  • 可在权限被拒绝时主动调用Permission.sms.request()发起权限请求,优化用户体验

内容的提问来源于stack exchange,提问作者Emir Bolat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 04:32:08