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

Flutter安卓应用不同通知铃声在Google Play版失效问题求助

问题:调试安装正常,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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 02:14:52