Timer in Xamarin.Forms

14,536

Take a look at Device class in Xamarin.Forms and particularly at StartTimer method.

Given that, you can setup your timer :

Device.StartTimer(TimeSpan.FromMilliseconds(300.0), TimerElapsed);

private bool TimerElapsed()
{
    Device.BeginInvokeOnMainThread(() => 
    {
        //put here your code which updates the view
    });
    //return true to keep timer reccurring
    //return false to stop timer
}

It will fire approximately every 300 milliseconds (depending on the device capabilities)

Regarding your code, you can start with something like that:

1.Add following to your play command :

Device.StartTimer(TimeSpan.FromSeconds(1.0), CheckPositionAndUpdateSlider);

2.Add CheckPositionAndUpdateSlider method :

private bool CheckPositionAndUpdateSlider()
{
    var position = DependencyService.Get<IAudio>().GetCurrentPosition();
    Device.BeginInvokeOnMainThread(() => 
    {
         slider.Value = position;
    });
    return true;
}
Share:
14,536
Arti
Author by

Arti

Updated on June 04, 2022

Comments

  • Arti
    Arti about 2 years

    I want to build my own audio player (as there no plugins available). I have used a slider to show progress of the player. I could allow user to go to specific location when the slider is moved but I can not synchronize it with the recording being played.

    Form

    int i = 1;
    Button btnPlay = new Button
    {
        Text = "Play/Pause",
        Command = new Command(() =>
        {
            DependencyService.Get<IAudio>().PlayMp3File();
            TimeSpan tmspan = new TimeSpan(00, 00, 00);
            label.Text = String.Format("{0:hh\\:mm\\:ss}", tmspan.Add(TimeSpan.FromMilliseconds(i)));
            i++;
            return true;
        })
    };
    Button btnStop = new Button { Text = "Stop" };
    TimeSpan timeSpan = DependencyService.Get<IAudio>().GetInfo();
    Label lblDuration = new Label { Text = String.Format("{0:hh\\:mm\\:ss}", timeSpan) };
    
    var slider = new Slider {
        Minimum = 0,
        Maximum = timeSpan.TotalHours,
    };
    var label = new Label {
        Text = "Slider value is 0",
        FontSize = 25,
        HorizontalOptions = LayoutOptions.Start,
    };
    slider.ValueChanged += 
        (sender, e) => 
        {
            label.Text = String.Format("Slider value is {0:hh\\:mm\\:ss}", TimeSpan.FromMilliseconds(e.NewValue));
            DependencyService.Get<IAudio>().SeekTo(Convert.ToInt32(e.NewValue));
        };
    MainPage = new ContentPage
    {
        Content = new StackLayout 
        {
            Children = 
            {
                btnPlay,
                btnStop,
                slider,
                lblDuration,
                label
            }
        },  
        Padding = new Thickness (10, Device.OnPlatform (20, 0, 0), 10, 5)
    };
    

    Service

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using Android.App;
    using Android.Content;
    using Android.OS;
    using Android.Runtime;
    using Android.Views;
    using Android.Widget;
    using AudioTest.Droid;
    using Xamarin.Forms;
    using Android.Media;
    using System.Threading.Tasks;
    
    [assembly: Dependency(typeof(AudioService))]
    
    namespace AudioTest.Droid
    {
        public class AudioService : IAudio
        {
            public AudioService() { }
    
            MediaPlayer player = null;
    
            public async Task StartPlayerAsync()
            {
                try
                {
                    if (player == null)
                    {
                        player = new MediaPlayer();
                        player = MediaPlayer.Create(global::Android.App.Application.Context, Resource.Raw.test);
                        player.Start();
                    }
                    else
                    {
                        if (player.IsPlaying == true)
                        {
                            player.Pause();
                        }
                        else
                        {
                            player.Start();
                        }
                    }
                }
                catch (Exception ex)
                {
                    Console.Out.WriteLine(ex.StackTrace);
                }
            }
    
            public void StopPlayer()
            {
                if ((player != null))
                {
                    if (player.IsPlaying)
                    {
                        player.Stop();
                    }
                    player.Release();
                    player = null;
                }
            }
    
            public async Task PlayMp3File()
            {
                await StartPlayerAsync();
            }
    
            public void Stop()
            {
                this.StopPlayer();
            }
    
            public async Task SeekTo( int s)
            {
                await seekTo(s);
            }
    
            public double CurrentPosition()
            {
                if ((player != null))
                {
                    return player.CurrentPosition;
                }
                else
                { return 0; }
            }
    
            private async Task seekTo(int mseconds)
            {
                if (player == null)
                {
                    player = new MediaPlayer();
                    player = MediaPlayer.Create(global::Android.App.Application.Context, Resource.Raw.test);
    
                }
    
                player.SeekTo(mseconds);
                player.Start();
            }
    
    
    
            public TimeSpan GetInfo()
            {
                int arr;
                if (player == null)
                {
                    player = new MediaPlayer();
                    player = MediaPlayer.Create(global::Android.App.Application.Context, Resource.Raw.test);
    
                }
                arr = player.Duration;
    
                return TimeSpan.FromMilliseconds(arr);//TimeSpan.FromMilliseconds(arr).TotalMinutes;
            }
        }
    }
    

    Anyone has any idea on how to go about it?

    Edit Screenshot of the screen enter image description here

    On play the timer should start and also my slider value should increment. On pause the timer and slider should be paused and on stop it should be stopped.

  • Arti
    Arti about 8 years
    Is there a way to pause or stop the timer?
  • Arkadiusz K
    Arkadiusz K about 8 years
    Just return false from TimerElapsed method in order to stop it. When you want to pause timer then you have to write this logic on your own. I mean stop the timer and then start timer again when you want to resume it.
  • Arti
    Arti about 8 years
    I cannot get my slider to move as per the recording progress. Any idea on that?
  • Arkadiusz K
    Arkadiusz K about 8 years
    Did you tested whether your timer is fired at all? I can't see your timer code, but maybe you forgot to notify about property changed for Slider?
  • Arti
    Arti about 8 years
    On click of play button I would like to start a timer (which is working-displayed in Label) also start my slider ( ie. move slider value as per the recording.) Getting my slider to move as recording proceed does't work.
  • Arkadiusz K
    Arkadiusz K about 8 years
    In code in your question there isn't any code which starts timer and anything which after that updates slider value. I've edited my answer to include example how you can add code which will update slider.
  • Arti
    Arti about 8 years
    Doesn't work. It seems to be blocking the UI and also the recording
  • Arkadiusz K
    Arkadiusz K about 8 years
  • mr5
    mr5 over 4 years
    Down side of this is that you can't use this without calling Xamarin.Forms.Init() which would be hassle if you're using this in a background service.
  • c-sharp-and-swiftui-devni
    c-sharp-and-swiftui-devni over 2 years
    U dont show what TimerElapsed should be ?