Flutter中实现AlertDialog弹出时触发设备提示音
Flutter弹出AlertDialog时触发设备提示音方案
方案一:使用第三方插件(推荐)
可以用flutter_beep插件实现,它已适配Android和iOS平台,能直接调用系统默认提示音:
- 在
pubspec.yaml中添加依赖:
dependencies: flutter_beep: ^1.0.6
- 修改原有代码,在弹窗触发前播放提示音:
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter_beep/flutter_beep.dart'; // 引入插件 void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Application', theme: ThemeData( primarySwatch: Colors.blue, ), debugShowCheckedModeBanner: false, home: const HomePage(), ); } } class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { return TextButton( onPressed: () { showAlertDialog(context); }, child: const Text('Press button'), ); } } showAlertDialog(BuildContext context) { // 弹出Dialog前播放系统提示音 FlutterBeep.playSysSound(AndroidSoundIDs.TONE_PROMPT); // iOS可替换为:FlutterBeep.playSysSound(IosSoundIDs.BEEP); Widget button = TextButton( child: const Text('OK'), onPressed: () { Navigator.pop(context); }, ); AlertDialog alert = AlertDialog( title: const Text("Alert title"), content: const Text('Alert message.'), actions: [ button, ], ); showDialog( context: context, builder: (BuildContext context) { return alert; }, ); }
方案二:自定义Platform Channel(无第三方依赖)
如果不想用插件,可以自己写平台通道调用原生API:
Android端(Kotlin)
在MainActivity.kt中添加通道逻辑:
import android.media.RingtoneManager import android.net.Uri import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel class MainActivity : FlutterActivity() { private val CHANNEL = "com.example.alert_sound/channel" override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result -> if (call.method == "playAlertSound") { val notification: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION) val ringtone = RingtoneManager.getRingtone(applicationContext, notification) ringtone.play() result.success(null) } else { result.notImplemented() } } } }
iOS端(Swift)
在AppDelegate.swift中添加通道逻辑:
import UIKit import Flutter import AudioToolbox @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { private let CHANNEL = "com.example.alert_sound/channel" override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let channel = FlutterMethodChannel(name: CHANNEL, binaryMessenger: controller.binaryMessenger) channel.setMethodCallHandler { (call: FlutterMethodCall, result: FlutterResult) -> Void in if call.method == "playAlertSound" { AudioServicesPlaySystemSound(1007) // iOS默认提示音ID result(nil) } else { result(FlutterMethodNotImplemented) } } GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } }
Flutter端调用
修改原代码,添加通道调用逻辑:
import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Application', theme: ThemeData( primarySwatch: Colors.blue, ), debugShowCheckedModeBanner: false, home: const HomePage(), ); } } class HomePage extends StatelessWidget { const HomePage({super.key}); @override Widget build(BuildContext context) { return TextButton( onPressed: () { showAlertDialog(context); }, child: const Text('Press button'), ); } } // 定义平台通道 const MethodChannel _channel = MethodChannel('com.example.alert_sound/channel'); // 播放提示音方法 Future<void> _playAlertSound() async { try { await _channel.invokeMethod('playAlertSound'); } on PlatformException catch (e) { print("播放失败: ${e.message}"); } } showAlertDialog(BuildContext context) { // 先播放提示音再弹Dialog _playAlertSound(); Widget button = TextButton( child: const Text('OK'), onPressed: () { Navigator.pop(context); }, ); AlertDialog alert = AlertDialog( title: const Text("Alert title"), content: const Text('Alert message.'), actions: [ button, ], ); showDialog( context: context, builder: (BuildContext context) { return alert; }, ); }
注意事项
- 方案一的插件已封装原生逻辑,无需自己编写平台代码,开发效率更高
- 方案二中iOS的系统提示音ID可按需更换,比如
1000为短信提示音,1007为默认提醒音 - Android端可指定其他类型提示音,比如
TYPE_ALARM或自定义音频Uri
内容的提问来源于stack exchange,提问作者Ken U
相关产品推荐
相关产品推荐

