Flutter安卓应用不同通知铃声在Google Play版失效问题求助
我用Flutter在Visual Studio开发安卓应用,计划给不同分类的通知设置专属提示铃声。通过USB调试安装到设备时铃声正常工作,但从Google Play商店下载安装后,通知铃声完全没反应,求解决办法。
提供的代码
import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; //import 'package:hive/hive.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:flutter/material.dart'; Future<void> main() async { await Hive.initFlutter(); await init(); runApp(MyApp()); } Future<void> init() async { PermissionStatus status = await Permission.notification.status; if (!status.isGranted) { status = await Permission.notification.request(); } await Firebase.initializeApp(); } class MyApp extends StatelessWidget { final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin(); MyApp({Key? key}) : super(key: key); // Method to initialize notification channels. Future<void> _initializeNotifications() async { const AndroidInitializationSettings initializationSettingsAndroid = AndroidInitializationSettings('@mipmap/launcher_icon'); final InitializationSettings initializationSettings = InitializationSettings(android: initializationSettingsAndroid); await flutterLocalNotificationsPlugin.initialize(initializationSettings); // Define channel for alerts. const AndroidNotificationChannel alertChannel = AndroidNotificationChannel( 'alert', // Kanal ID 'Alert Channel', // Kanal Adı // 'Channel for important alerts', // Kanal Açıklaması importance: Importance.high, sound: RawResourceAndroidNotificationSound("alert")); // Define channel for regular notifications. const AndroidNotificationChannel normalChannel = AndroidNotificationChannel( 'noti', // Kanal ID 'Normal Channel', // Kanal Adı //'Channel for normal notifications', // Kanal Açıklaması importance: Importance.high, sound: RawResourceAndroidNotificationSound("noti")); // Create the channels. await flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(alertChannel); await flutterLocalNotificationsPlugin .resolvePlatformSpecificImplementation< AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(normalChannel); FirebaseMessaging.onMessage.listen((RemoteMessage message) { // Bildirim alındığında bu metot tetiklenecek RemoteNotification? notification = message.notification; AndroidNotification? android = message.notification?.android; if (notification != null && android != null) { _showNotification( android.channelId ?? 'noti', notification.title ?? '', notification.body ?? '', ); } }); } // const MyApp({Key? key}) : super(key: key); // This widget is the root of your application. @override Widget build(BuildContext context) { _initializeNotifications(); return MaterialApp( debugShowCheckedModeBanner: false, localizationsDelegates: const [GlobalMaterialLocalizations.delegate], supportedLocales: const [Locale('en')], home: const LoginPage(), builder: EasyLoading.init(), ); } // Method to display notifications. Future<void> _showNotification( String channelID, String title, String body) async { AndroidNotificationDetails androidPlatformChannelSpecifics = AndroidNotificationDetails( channelID, title, //'your_channel_description', importance: Importance.max, priority: Priority.high, ); NotificationDetails platformChannelSpecifics = NotificationDetails(android: androidPlatformChannelSpecifics); await flutterLocalNotificationsPlugin .show(0, title, body, platformChannelSpecifics, payload: 'item x'); } }
阻止Google Play压缩铃声资源:Google Play的应用签名服务会自动压缩未被代码直接引用的资源,导致铃声文件丢失。在
android/app/build.gradle的android块中添加配置,指定不压缩铃声格式:android { // 其他已有配置 aaptOptions { noCompress "mp3", "wav", "ogg" // 对应你的铃声文件格式 } }调整通知渠道初始化时机:当前在
build方法中调用_initializeNotifications(),build可能被多次触发,且异步初始化可能在推送到达时还未完成。建议把初始化逻辑移到main函数的初始化流程中,确保应用启动时就完成渠道创建:
修改main函数和相关代码:Future<void> main() async { await Hive.initFlutter(); await init(); // 提前初始化通知渠道 final FlutterLocalNotificationsPlugin notificationsPlugin = FlutterLocalNotificationsPlugin(); await _initializeNotifications(notificationsPlugin); runApp(MyApp(notificationsPlugin: notificationsPlugin)); } // 把初始化方法改为独立函数 Future<void> _initializeNotifications(FlutterLocalNotificationsPlugin plugin) async { const AndroidInitializationSettings initSettingsAndroid = AndroidInitializationSettings('@mipmap/launcher_icon'); final InitializationSettings initSettings = InitializationSettings(android: initSettingsAndroid); await plugin.initialize(initSettings); const AndroidNotificationChannel alertChannel = AndroidNotificationChannel( 'alert', 'Alert Channel', importance: Importance.high, sound: RawResourceAndroidNotificationSound("alert")); const AndroidNotificationChannel normalChannel = AndroidNotificationChannel( 'noti', 'Normal Channel', importance: Importance.high, sound: RawResourceAndroidNotificationSound("noti")); await plugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(alertChannel); await plugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>() ?.createNotificationChannel(normalChannel); } // 修改MyApp接收插件实例 class MyApp extends StatelessWidget { final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin; const MyApp({Key? key, required this.flutterLocalNotificationsPlugin}) : super(key: key); // ... 其余代码不变,建议将Firebase消息监听逻辑移到StatefulWidget的initState中,避免重复注册 }添加ProGuard规则避免混淆:发布版本的代码混淆可能破坏通知相关类的功能,在
android/app/proguard-rules.pro中添加以下规则:-keep class com.dexterous.flutterlocalnotifications.** { *; } -keep class com.google.firebase.messaging.** { *; } -keep class android.app.NotificationChannel { *; } -keepnames class android.app.NotificationChannel检查铃声文件的正确性:确保铃声文件放在
android/app/src/main/res/raw/目录下,文件名全小写(比如alert.mp3、noti.mp3),格式为Android支持的mp3、wav或ogg,且文件没有损坏。验证Firebase推送的ChannelID:在Firebase控制台发送通知时,必须指定与代码中一致的
channelId(alert或noti),大小写完全匹配。如果未指定,会使用默认渠道,而默认渠道的铃声可能不是你设置的。测试签名发布APK:先通过
flutter build apk --release生成签名的发布包,手动安装到设备测试,确认问题是否出在Google Play的打包流程中,还是代码本身的发布版本问题。
内容的提问来源于stack exchange,提问作者Kaya

