Xamarin Forms锁屏时MediaElement音频停止:如何实现音乐不暂停
嘿,这个问题我之前帮好几个开发者解决过——锁屏后音频停播是因为Xamarin.Forms的MediaElement默认没配置后台音频播放的权限和会话支持,得针对Android和iOS分别做些配置,再调整下代码才行。下面一步步来:
Android 端配置
Android 8.0+要求后台播放音频的App必须启动前台服务并显示通知,否则系统会终止服务,导致音频停止。
第一步:修改
AndroidManifest.xml
在<manifest>标签下添加前台服务权限,在<application>标签内声明音频服务:<!-- 添加权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- 声明服务 --> <application ...> <service android:name=".AudioPlayerService" android:foregroundServiceType="mediaPlayback" /> </application>第二步:创建前台服务类
在Android项目中新建一个继承自Service的类AudioPlayerService,用来处理后台播放的前台通知:using Android.App; using Android.Content; using Android.Media; using Android.OS; using AndroidX.Core.App; [Service(ForegroundServiceType = Android.Content.PM.ForegroundService.TypeMediaPlayback)] public class AudioPlayerService : Service { public override IBinder OnBind(Intent intent) { return null; } public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId) { // 创建通知渠道(Android 8.0+ 必需) var channelId = "AudioPlaybackChannel"; if (Build.VERSION.SdkInt >= BuildVersionCodes.O) { var channel = new NotificationChannel(channelId, "音频播放", NotificationImportance.Low) { Description = "后台音频播放通知" }; var notificationManager = (NotificationManager)GetSystemService(NotificationService); notificationManager.CreateNotificationChannel(channel); } // 构建前台通知 var notification = new NotificationCompat.Builder(this, channelId) .SetContentTitle("正在播放") .SetContentText("Voice.mp3") .SetSmallIcon(Resource.Drawable.ic_notification) // 替换成你的通知图标 .SetOngoing(true) // 设为不可滑动删除 .Build(); // 启动前台服务 StartForeground(1001, notification); return StartCommandResult.Sticky; } }
iOS 端配置
iOS需要开启后台音频模式,并配置音频会话类别为播放模式。
第一步:修改
Info.plist
添加后台音频权限,找到Required background modes(或直接编辑XML):<key>UIBackgroundModes</key> <array> <string>audio</string> </array>第二步:配置音频会话
在iOS项目的AppDelegate.cs的FinishedLaunching方法中添加音频会话初始化代码:using AVFoundation; public override bool FinishedLaunching(UIApplication app, NSDictionary options) { // 配置音频会话为播放模式 var audioSession = AVAudioSession.SharedInstance(); NSError error = null; audioSession.SetCategory(AVAudioSessionCategory.Playback, out error); if (error != null) { Console.WriteLine($"音频会话配置失败: {error.LocalizedDescription}"); } audioSession.SetActive(true, out error); global::Xamarin.Forms.Forms.Init(); LoadApplication(new App()); return base.FinishedLaunching(app, options); }
Xamarin.Forms 端代码调整
- 首先,你当前设置的
KeepScreenOn="True"是保持屏幕常亮,这和后台播放无关,反而可能不是你需要的(你要的是锁屏后继续播放,不是亮屏),可以把这个属性去掉。 - 然后通过依赖服务统一初始化音频会话和启动前台服务:
- 定义一个接口:
public interface IAudioSessionHelper { void InitializeBackgroundAudio(); } - 在Android项目中实现这个接口:
using Xamarin.Forms; using YourAppNamespace.Droid; // 替换成你的Android项目命名空间 [assembly: Dependency(typeof(AudioSessionHelper_Android))] namespace YourAppNamespace.Droid { public class AudioSessionHelper_Android : IAudioSessionHelper { public void InitializeBackgroundAudio() { var intent = new Intent(Android.App.Application.Context, typeof(AudioPlayerService)); if (Build.VERSION.SdkInt >= BuildVersionCodes.O) { Android.App.Application.Context.StartForegroundService(intent); } else { Android.App.Application.Context.StartService(intent); } } } } - 在iOS项目中实现这个接口(其实iOS的会话已经在AppDelegate初始化了,这里可以留空或者做额外处理):
using Xamarin.Forms; using YourAppNamespace.iOS; // 替换成你的iOS项目命名空间 [assembly: Dependency(typeof(AudioSessionHelper_iOS))] namespace YourAppNamespace.iOS { public class AudioSessionHelper_iOS : IAudioSessionHelper { public void InitializeBackgroundAudio() { // iOS的音频会话已经在AppDelegate中配置,这里可以空实现 } } } - 在播放音频前调用初始化方法:
private void PlayAudio() { // 初始化后台音频支持 DependencyService.Get<IAudioSessionHelper>().InitializeBackgroundAudio(); MyMedia.Play(); }
- 定义一个接口:
这样配置完成后,不管是Android还是iOS设备,锁屏后音频都能继续播放了。记得要在真机上测试,模拟器的后台行为可能和真机不一致哦。
内容的提问来源于stack exchange,提问作者Ashkan
相关产品推荐
相关产品推荐

