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

Flutter本地通知权限添加:解决无声音及权限手动开启问题

Flutter本地通知:提示音修复与权限配置方案

一、解决真机通知无提示音问题

Android平台

Android 8.0(API 26)及以上依赖通知渠道,仅设置playSound: true无法保证提示音正常播放,需为渠道明确指定声音资源:

  1. 将自定义铃声文件(如notification_sound.mp3)放入android/app/src/main/res/raw目录,也可直接使用系统默认铃声
  2. 修改notificationDetails()方法,补充声音配置:
AndroidNotificationDetails('channelId', 'channelName',
  importance: Importance.max,
  playSound: true,
  // 自定义铃声配置
  sound: const RawResourceAndroidNotificationSound('notification_sound'),
  // 或使用系统默认铃声:sound: UriAndroidNotificationSound.defaultSoundUri,
  channelShowBadge: true,
  enableVibration: true,
)

注意:通知渠道一旦创建,后续通过代码修改渠道配置(如声音、震动)不会生效,需卸载重装APP或引导用户手动修改系统内的通知渠道设置

iOS平台

需确保DarwinNotificationDetails指定声音参数,同时确认权限已正常获取:
修改notificationDetails()中的iOS配置:

iOS: const DarwinNotificationDetails(
  sound: 'default', // 使用系统默认提示音,自定义铃声需放入iOS项目资源并配置
)

二、完善通知权限配置

Android平台

1. 配置Manifest权限

在android/app/src/main/AndroidManifest.xml中添加权限声明:

<!-- Android 13+ 必需的通知权限 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />

2. 动态请求权限

添加permission_handler依赖后,在NotificationService中实现权限检查与请求逻辑:

import 'package:permission_handler/permission_handler.dart';
import 'package:flutter/foundation.dart';

// 新增:Android通知权限请求方法
Future<bool> requestAndroidNotificationPermission() async {
  if (await Permission.notification.isGranted) {
    return true;
  } else {
    PermissionStatus status = await Permission.notification.request();
    return status.isGranted;
  }
}

// 修改initNotification,先请求权限再初始化
Future<void> initNotification() async {
  if (kIsWeb == false && defaultTargetPlatform == TargetPlatform.android) {
    await requestAndroidNotificationPermission();
  }

  // 原初始化代码保留...
}

iOS平台

iOS初始化阶段已请求权限,但需处理权限被拒绝的场景,引导用户前往系统设置开启:

// 新增:iOS通知权限检查方法
Future<bool> checkIOSNotificationPermission() async {
  NotificationSettings settings = await notificationsPlugin.getNotificationSettings();
  return settings.authorizationStatus == AuthorizationStatus.authorized;
}

// 在initNotification末尾添加权限引导逻辑
if (kIsWeb == false && defaultTargetPlatform == TargetPlatform.iOS) {
  bool hasPermission = await checkIOSNotificationPermission();
  if (!hasPermission) {
    await notificationsPlugin.openNotificationSettings();
  }
}

完整修改后的代码

import 'package:flutter/foundation.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:timezone/timezone.dart' as tz;

class NotificationService {
  final FlutterLocalNotificationsPlugin notificationsPlugin =
      FlutterLocalNotificationsPlugin();

  // Android通知权限请求
  Future<bool> requestAndroidNotificationPermission() async {
    if (await Permission.notification.isGranted) {
      return true;
    } else {
      PermissionStatus status = await Permission.notification.request();
      return status.isGranted;
    }
  }

  // iOS通知权限检查
  Future<bool> checkIOSNotificationPermission() async {
    NotificationSettings settings = await notificationsPlugin.getNotificationSettings();
    return settings.authorizationStatus == AuthorizationStatus.authorized;
  }

  Future<void> initNotification() async {
    // Android权限处理
    if (kIsWeb == false && defaultTargetPlatform == TargetPlatform.android) {
      await requestAndroidNotificationPermission();
    }

    AndroidInitializationSettings initializationSettingsAndroid =
        const AndroidInitializationSettings('mipmap/ic_launcher');

    var initializationSettingsIOS = DarwinInitializationSettings(
        requestAlertPermission: true,
        requestBadgePermission: true,
        requestSoundPermission: true,
        onDidReceiveLocalNotification:
            (int id, String? title, String? body, String? payload) async {});

    var initializationSettings = InitializationSettings(
        android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
    await notificationsPlugin.initialize(initializationSettings,
        onDidReceiveNotificationResponse:
            (NotificationResponse notificationResponse) async {});

    // iOS权限引导
    if (kIsWeb == false && defaultTargetPlatform == TargetPlatform.iOS) {
      bool hasPermission = await checkIOSNotificationPermission();
      if (!hasPermission) {
        await notificationsPlugin.openNotificationSettings();
      }
    }
  }

  Future<NotificationDetails> notificationDetails() async {
    return NotificationDetails(
        android: AndroidNotificationDetails(
          'channelId',
          'channelName',
          importance: Importance.max,
          playSound: true,
          sound: const RawResourceAndroidNotificationSound('notification_sound'),
          channelShowBadge: true,
          enableVibration: true,
        ),
        iOS: const DarwinNotificationDetails(
          sound: 'default',
        ));
  }

  Future showNotification(
      {int id = 0, String? title, String? body, String? payLoad}) async {
    return notificationsPlugin.show(
        id, title, body, await notificationDetails());
  }

  Future scheduleNotification(
      {int id = 0,
      String? title,
      String? body,
      String? payLoad,
      required DateTime scheduledNotificationDateTime}) async {
    return notificationsPlugin.zonedSchedule(
        id,
        title,
        body,
        tz.TZDateTime.from(
          scheduledNotificationDateTime,
          tz.local,
        ),
        await notificationDetails(),
        androidAllowWhileIdle: true,
        uiLocalNotificationDateInterpretation:
            UILocalNotificationDateInterpretation.absoluteTime);
  }
}

额外注意事项

  • 依赖安装:需在pubspec.yaml中添加permission_handler包,执行flutter pub get完成安装
  • Android渠道配置:首次创建的通知渠道无法通过代码修改,如需调整需卸载重装APP或引导用户手动修改系统设置
  • iOS自定义铃声:需将铃声文件放入iOS项目的Resources目录,并在Info.plist中完成配置

内容的提问来源于stack exchange,提问作者bino arin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 11:35:20