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

Flutter Awesome Notifications在API≥26安卓模拟器中无声音问题

Android API 26+ 模拟器中Awesome Notifications自定义声音无法播放问题

在使用Flutter的Awesome Notifications插件发送带自定义声音的通知时,仅Android API版本≥26的模拟器无法正常播放声音,API≤25的设备运行正常。

复现代码

import 'package:awesome_notifications/awesome_notifications.dart';
import 'package:flutter/material.dart';

final LocalNotificationService notificationService = LocalNotificationService();

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  notificationService.initialize();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Flutter Demo",
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: "Flutter Demo Home Page"),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: const <Widget>[
            Text(
              'Awesome Notifications Flutter Test',
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () => notificationService.showNotification(
            title: "title",
            body: "notification body",),
        child: const Icon(Icons.add),
      ),
    );
  }
}

class LocalNotificationService {
  LocalNotificationService();

  final _localNotificationService = AwesomeNotifications();

  initialize() {
    _localNotificationService.initialize(
      'resource://drawable/res_custom_icon',
      [
        NotificationChannel(
          channelKey: 'channel_key',
          channelName: 'channel name',
          channelDescription: 'channel description',
          defaultColor: Colors.green,
          playSound: true,
          importance: NotificationImportance.High,
          enableVibration: true,
          enableLights: true,
          ledColor: Colors.white,
        )
      ],
    );
  }

  void showNotification({
    required String title,
    required String body,
  }) {
    _localNotificationService.createNotification(
      content: NotificationContent(
        id: _createUniqueId(),
        channelKey: 'channel_key',
        title: title,
        body: body,
        customSound: 'resource://raw/res_custom_sound',
      ),
    );
  }

  int _createUniqueId() {
    return DateTime.now().millisecondsSinceEpoch.remainder(100000);
  }
}

pubspec.yaml 配置

name: untitled
description: A new Flutter project.

publish_to: 'none' # Remove this line if you wish to publish to pub.dev

version: 1.0.0+1

environment:
  sdk: '>=2.18.0-271.4.beta <3.0.0'

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  awesome_notifications: ^0.6.21

dev_dependencies:
  flutter_test:
    sdk: flutter
  flutter_lints: ^2.0.0

flutter:
  uses-material-design: true

Android build.gradle 配置(android块)

android {
    compileSdkVersion flutter.compileSdkVersion
    ndkVersion flutter.ndkVersion

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }

    kotlinOptions {
        jvmTarget = '1.8'
    }

    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }

    defaultConfig {
        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
        applicationId "com.example.untitled"
        // You can update the following values to match your application needs.
        // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-build-configuration.
        minSdkVersion 23
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            signingConfig signingConfigs.debug
        }
    }
}

环境信息

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel beta, 3.3.0-0.3.pre, on Microsoft Windows [Version 10.0.19043.1889], locale en-US)
[√] Android toolchain - develop for Android devices (Android SDK version 32.0.0)
[√] Chrome - develop for the web
[√] Visual Studio - develop for Windows (Visual Studio Enterprise 2019 16.11.1)
[√] Android Studio (version 2021.1)
[√] Android Studio (version 4.1)
[√] Android Studio (version 4.2)
[√] VS Code (version 1.69.2)
[√] Connected device (4 available)
    ! Device emulator-5554 is offline.
[√] HTTP Host Availability

• No issues found!

解决方法

Android API 26及以上引入了通知渠道机制,自定义声音必须绑定到渠道,而非直接在通知内容中设置。按以下步骤修改:

  1. 初始化时为通知渠道绑定自定义声音
    修改NotificationChannel配置,添加声音相关参数:

    NotificationChannel(
      channelKey: 'channel_key',
      channelName: 'channel name',
      channelDescription: 'channel description',
      defaultColor: Colors.green,
      playSound: true,
      importance: NotificationImportance.High,
      enableVibration: true,
      enableLights: true,
      ledColor: Colors.white,
      // 新增以下两行
      defaultRingtoneType: DefaultRingtoneType.Notification,
      sound: 'resource://raw/res_custom_sound'
    )
    
  2. 移除通知内容中的自定义声音设置
    在NotificationContent中删除customSound字段,API26+下声音由渠道控制:

    NotificationContent(
      id: _createUniqueId(),
      channelKey: 'channel_key',
      title: title,
      body: body,
      // 删掉customSound这一行
    )
    
  3. 验证声音文件格式与路径
    确保自定义声音为.mp3或.ogg格式,放置在android/app/src/main/res/raw/目录下,文件名全小写、无特殊字符。

  4. 重置通知渠道
    Android渠道创建后无法直接修改,测试时需先卸载应用再重新安装,或调用setChannel更新渠道配置:

    _localNotificationService.setChannel(
      NotificationChannel(
        // 与上面一致的渠道配置
      )
    );
    

原理说明

Android 8.0(API26)开始,所有通知必须归属某个渠道,渠道的配置优先级高于通知内容的单独设置。API25及以下允许直接在通知中指定声音,但API26+强制通过渠道管理声音等通知行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 09:36:29