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

.NET MAUI定时器结束播放声音报错及解决方案

.NET MAUI定时器结束播放声音报错及解决方法

我在编写.NET MAUI代码时,希望定时器结束时播放声音,最初使用Plugin.SimpleAudioPlayer包的PlaySound函数实现,但定时器结束执行播放操作时,在var player处抛出错误:

System.NotImplementedException: 'This functionality is not implemented in the .NET standard version of this assembly. Reference the NuGet package from your platform-specific (head) application project in order to reference the platform-specific implementation.'

改用Plugin.Maui.Audio包实现后,问题解决,前后代码如下:

原代码

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using Microsoft.Maui.Controls;
using Plugin.SimpleAudioPlayer;

namespace CookOff.Models
{
    public class Step : INotifyPropertyChanged
    {
        private bool isSelected;
        private TimeSpan timer;
        private bool isTimerRunning;
        private bool isTimerPaused;
        private TimeSpan originalTimer;

        public int RecipeID { get; set; }
        public string Description { get; set; }
        public bool TimerRequired { get; set; }
        public TimeSpan Timer
        {
            get => timer;
            set
            {
                timer = value;
                OnPropertyChanged();
            }
        }
        public bool IsSelected
        {
            get => isSelected;
            set
            {
                isSelected = value;
                OnPropertyChanged();
            }
        }

        public ICommand StartTimerCommand { get; }
        public ICommand PauseTimerCommand { get; }
        public ICommand StopTimerCommand { get; }

        public Step()
        {
            StartTimerCommand = new Command(StartTimer);
            PauseTimerCommand = new Command(PauseTimer);
            StopTimerCommand = new Command(StopTimer);
        }

        public Step(int recipeID, string description, bool timerRequired, TimeSpan timer)
        {
            RecipeID = recipeID;
            Description = description;
            TimerRequired = timerRequired;
            Timer = timer;

            StartTimerCommand = new Command(StartTimer);
            PauseTimerCommand = new Command(PauseTimer);
            StopTimerCommand = new Command(StopTimer);
        }

        private void StartTimer()
        {
            if (!isTimerRunning || isTimerPaused)
            {
                isTimerRunning = true;
                isTimerPaused = false;
                originalTimer = Timer;
                Device.StartTimer(TimeSpan.FromSeconds(1), () =>
                {
                    if (!isTimerRunning)
                        return false;

                    Timer = Timer.Subtract(TimeSpan.FromSeconds(1));
                    if (Timer <= TimeSpan.Zero)
                    {
                        Timer = TimeSpan.Zero;
                        isTimerRunning = false;
                        // PLAY SOUND WHEN TIMER RUNS OUT
                        PlaySound();
                    }
                    return isTimerRunning;
                });
            }
        }

        private void PauseTimer()
        {
            isTimerPaused = true;
            isTimerRunning = false;
        }

        private void StopTimer()
        {
            isTimerRunning = false;
            isTimerPaused = false;
            Timer = originalTimer;
        }

        private void PlaySound() //ISSUE HERE
        {
            var player = CrossSimpleAudioPlayer.Current;
            player.Load("Resources/Raw/timer_end.mp3");
            player.Play();
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

修改后代码

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Windows.Input;
using Microsoft.Maui.Controls;
using Plugin.Maui.Audio;

namespace CookOff.Models
{
    public class Step : INotifyPropertyChanged
    {
        private bool isSelected;
        private TimeSpan timer;
        private bool isTimerRunning;
        private bool isTimerPaused;
        private TimeSpan originalTimer;

        public int RecipeID { get; set; }
        public string Description { get; set; }
        public bool TimerRequired { get; set; }
        public TimeSpan Timer
        {
            get => timer;
            set
            {
                timer = value;
                OnPropertyChanged();
            }
        }
        public bool IsSelected
        {
            get => isSelected;
            set
            {
                isSelected = value;
                OnPropertyChanged();
            }
        }

        public ICommand StartTimerCommand { get; }
        public ICommand PauseTimerCommand { get; }
        public ICommand StopTimerCommand { get; }

        public Step()
        {
            StartTimerCommand = new Command(StartTimer);
            PauseTimerCommand = new Command(PauseTimer);
            StopTimerCommand = new Command(StopTimer);
        }

        public Step(int recipeID, string description, bool timerRequired, TimeSpan timer)
        {
            RecipeID = recipeID;
            Description = description;
            TimerRequired = timerRequired;
            Timer = timer;

            StartTimerCommand = new Command(StartTimer);
            PauseTimerCommand = new Command(PauseTimer);
            StopTimerCommand = new Command(StopTimer);
        }

        private void StartTimer()
        {
            if (!isTimerRunning || isTimerPaused)
            {
                isTimerRunning = true;
                isTimerPaused = false;
                originalTimer = Timer; // Store the original time when the timer starts
                Device.StartTimer(TimeSpan.FromSeconds(1), () =>
                {
                    if (!isTimerRunning)
                        return false;

                    Timer = Timer.Subtract(TimeSpan.FromSeconds(1));
                    if (Timer <= TimeSpan.Zero)
                    {
                        Timer = TimeSpan.Zero;
                        isTimerRunning = false;
                        // Play sound
                        PlaySound();
                    }
                    return isTimerRunning;
                });
            }
        }

        private void PauseTimer()
        {
            isTimerPaused = true;
            isTimerRunning = false;
        }

        private void StopTimer()
        {
            isTimerRunning = false;
            isTimerPaused = false;
            Timer = originalTimer; 
        }

        private async void PlaySound()
        {
            try
            {
                Debug.WriteLine("Attempting to play sound in PlaySound method");

                // STRAIGHTFORWARD AUDIO PLAYER
                var audioPlayer = AudioManager.Current.CreatePlayer(await FileSystem.OpenAppPackageFileAsync("Resources/Raw/timer_end.mp3"));

                if (audioPlayer == null)
                {
                    Debug.WriteLine("AudioPlayer creation failed");
                    return;
                }

                audioPlayer.Play();
                Debug.WriteLine("Sound played");
            }
            catch (Exception ex)
            {
                Debug.WriteLine($"Exception in PlaySound method: {ex.Message}");
                Debug.WriteLine(ex.StackTrace);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

内容的提问来源于stack exchange,提问作者HungryMonkey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 15:44:53