iOS端Maui健身应用后台运行及音频播放问题求助
健身App iOS后台运行问题修复方案
问题场景
健身App核心需求:
- 启动后追踪训练总时长
- 用户完成一组动作后启动休息倒计时(如30秒),结束时播放提示音提醒开始下一组
Android端运行正常,但iOS端切换到其他App(如音乐、Facebook)时,App会被系统终止,导致训练需重新开始。尝试实现iOS后台任务后,倒计时能完成但无提示音,且倒计时结束后App仍会终止。
现有代码
音效播放与倒计时逻辑
private async Task playSoundAsync() { var file = await FileSystem.OpenAppPackageFileAsync("finalbeepsound.mp3"); player = audioManager.CreatePlayer(file); await Task.Run( () => player.Play()); } public void StartRestTimer() { Debug.WriteLine("Start Rest Timer hit."); if (Set.Rest != 0) { IsCountDownShowing = true; IsSaveButtonShowing = false; IsCountingDown = true; SecondsRemaining = Set.Rest; timer = Application.Current.Dispatcher.CreateTimer(); timer.Interval = TimeSpan.FromSeconds(1); timer.Tick += async (sender, args) => { SecondsRemaining--; if (SecondsRemaining == 0) { IsCountingDown = false; IsCountDownShowing = false; IsSaveButtonShowing = true; await playSoundAsync(); timer.Stop(); } }; timer.Start(); } }
iOS AppDelegate代码
using Foundation; using UIKit; namespace PumpPal; [Register("AppDelegate")] public class AppDelegate : MauiUIApplicationDelegate { nint taskID; protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); public override void OnActivated(UIApplication application) { Console.WriteLine("On Activated called, App is active."); } public override void WillEnterForeground(UIApplication application) { Console.WriteLine("App will enter foreground"); UIApplication.SharedApplication.EndBackgroundTask(taskID); } public override void OnResignActivation(UIApplication application) { Console.WriteLine("OnResignActivation called, App moving to inactive state."); taskID = UIApplication.SharedApplication.BeginBackgroundTask(() => { }); } public override void DidEnterBackground(UIApplication application) { Console.WriteLine("App entering background state."); } public override void WillTerminate(UIApplication application) { Console.WriteLine("App is terminating"); } }
修复方案
1. 配置iOS后台权限
iOS对后台行为管控严格,需在Platforms/iOS/Info.plist中添加后台模式权限:
<key>UIBackgroundModes</key> <array> <string>audio</string> <!-- 允许后台播放音频 --> <string>fetch</string> <!-- 支持后台任务 --> </array>
2. 修复后台任务生命周期管理
调整AppDelegate中后台任务的创建与结束时机,避免被系统判定为无效任务:
public override void DidEnterBackground(UIApplication application) { Console.WriteLine("App entering background state."); // 创建后台任务并设置超时回调 taskID = UIApplication.SharedApplication.BeginBackgroundTask(() => { UIApplication.SharedApplication.EndBackgroundTask(taskID); taskID = nint.MinValue; }); // 后台执行核心逻辑 Task.Run(async () => { // 这里可放置需要持续运行的计时/追踪逻辑 await Task.Delay(TimeSpan.FromSeconds(Set.Rest)); // 任务完成后主动结束后台任务 UIApplication.SharedApplication.EndBackgroundTask(taskID); taskID = nint.MinValue; }); } public override void WillEnterForeground(UIApplication application) { Console.WriteLine("App will enter foreground"); if (taskID != nint.MinValue) { UIApplication.SharedApplication.EndBackgroundTask(taskID); taskID = nint.MinValue; } }
3. 修复后台音效播放
激活iOS音频会话以支持后台播放:
private async Task playSoundAsync() { // 激活音频会话,允许后台播放 var audioSession = AVAudioSession.SharedInstance(); await audioSession.SetCategoryAsync(AVAudioSessionCategory.Playback); await audioSession.SetActiveAsync(true); var file = await FileSystem.OpenAppPackageFileAsync("finalbeepsound.mp3"); player = audioManager.CreatePlayer(file); player.FinishedPlaying += (s, e) => { // 播放结束后关闭音频会话 audioSession.SetActiveAsync(false); }; player.Play(); }
4. 替换UI依赖型计时器
DispatcherTimer依赖UI线程,后台时易失效,改用Task.Delay实现后台兼容的倒计时:
public void StartRestTimer() { Debug.WriteLine("Start Rest Timer hit."); if (Set.Rest != 0) { IsCountDownShowing = true; IsSaveButtonShowing = false; IsCountingDown = true; SecondsRemaining = Set.Rest; Task.Run(async () => { while (SecondsRemaining > 0 && IsCountingDown) { await Task.Delay(TimeSpan.FromSeconds(1)); // 更新UI需回到主线程 MainThread.BeginInvokeOnMainThread(() => SecondsRemaining--); } if (SecondsRemaining == 0) { MainThread.BeginInvokeOnMainThread(() => { IsCountingDown = false; IsCountDownShowing = false; IsSaveButtonShowing = true; }); await playSoundAsync(); } }); } }
内容的提问来源于stack exchange,提问作者Justin Sinnard
相关产品推荐
相关产品推荐

