C# 如何观看MediaPlayer并获得反馈';目前进展如何?

C# 如何观看MediaPlayer并获得反馈';目前进展如何?,c#,android,xamarin,mvvmcross,C#,Android,Xamarin,Mvvmcross,我正在编写一个android应用程序,它使用MediaPlayer。我已经创建了一个自定义的IAudioPlayer,作为MediaPlayer的包装,以便最终将其扩展到iOS public interface IAudioPlayer { bool IsPlaying { get; } void Play(string fileName, int startingPoint); void Play(string fileName); void Pause();

我正在编写一个android应用程序,它使用
MediaPlayer
。我已经创建了一个自定义的
IAudioPlayer
,作为MediaPlayer的包装,以便最终将其扩展到iOS

public interface IAudioPlayer
{
    bool IsPlaying { get; }
    void Play(string fileName, int startingPoint);
    void Play(string fileName);
    void Pause();
    void Stop();
    int CurrentPosition();
    bool HasFile();
    void SkipForward(int seconds);
    void SkipBackward(int seconds);
    void SeekTo(int seconds);
}
我们的应用程序使用Mvvm模式构建,并使用MvvmCross

在FragmentViewModel上,我们有一些命令,比如
IPlayCommand
IStopCommand
,等等

public class HomeFragmentViewModel : ViewModelBase
{

    public HomeFragmentViewModel(IPlayCommand playCommand, 
                                 IStopCommand stopCommand, 
                                 ISkipForwardCommand skipForwardCommand, 
                                 ISkipBackwardCommand skipBackwardCommand)
    {
        _playCommand = playCommand;
        _stopCommand = stopCommand;
        _skipForwardCommand = skipForwardCommand;
        _skipBackwardCommand = skipBackwardCommand;
    }

    private string _playPauseIcon = FontAwesome.icon_play;
    public string PlayPauseIcon
    {
        get { return _playPauseIcon; }
        set { _playPauseIcon = value; RaisePropertyChanged(() => PlayPauseIcon); }
    }

    private IPlayCommand _playCommand;
    public IPlayCommand PlayCommand
    {
        get { return _playCommand; }
        set { _playCommand = value; RaisePropertyChanged(() => PlayCommand); }
    }

    private IStopCommand _stopCommand;
    public IStopCommand StopCommand
    {
        get { return _stopCommand; }
        set { _stopCommand = value; RaisePropertyChanged(() => StopCommand); }
    }

    private ISkipForwardCommand _skipForwardCommand;
    public ISkipForwardCommand SkipForwardCommand
    {
        get { return _skipForwardCommand; }
        set { _skipForwardCommand = value; RaisePropertyChanged(() => SkipForwardCommand); }
    }

    private ISkipBackwardCommand _skipBackwardCommand;
    public ISkipBackwardCommand SkipBackwardCommand
    {
        get { return _skipBackwardCommand; }
        set { _skipBackwardCommand = value; RaisePropertyChanged(() => SkipBackwardCommand); }
    }
}
在我们看来,我们已经有了绑定到这些命令的按钮,所有这些都按预期工作

但是

我们的视图还有一个
SeekBar
,我们将使用它来让用户快速清理。seekbar需要做两件事

  • 允许用户快速导航到所需的位置(这一点“应该”很容易
  • 根据曲目的当前进度自动更新(这一个我被卡住了)
  • 如何编写每秒触发一次的通知程序,并自动更新seekbar绑定?此通知程序需要与Command对象一起生活在PCL中,以便能够跨平台工作。我正在努力开始这方面的工作……我不确定在何处创建它或如何连接它

    根据曲目的当前进度自动更新(这一个我被卡住了)

    您应该能够使用与视图属性的绑定来完成此操作。以下是一些伪代码:

    在ViewModel中,添加SeekPosition属性:

     public double SeekPosition { /* normal INPC get/set */ }
    
    他认为:

  • 添加属性和事件对,如:

     public event EventHandler CurrentPositionChanged;
     public double CurrentPosition
     {
         get { return _mediaPlayer.CurrentPosition; }
         set
         {
             _mediaPlayer.SeekTo(value);
         }
     }
    
  • 添加计时器以在UI线程上触发
    CurrentPositionChanged
    事件。对于Android,在
    OnResume
    中创建此计时器,并在
    OnPause
    中销毁它

  • OnCreate
    中添加绑定:

     public override void OnCreate(args)
     {
          // normal base call and inflate
          // ...
    
          var set = this.CreateBindingSet<MyView, MyViewModel>();
          set.Bind(this).For(v => v.CurrentPosition).To(vm => vm.SeekPosition);
          set.Apply();
     }
    
    public override void OnCreate(args)
    {
    //正常基本呼叫和充气
    // ...
    var set=this.CreateBindingSet();
    set.Bind(this).For(v=>v.CurrentPosition).To(vm=>vm.SeekPosition);
    set.Apply();
    }
    

  • 请注意,这种方法在PCL中不使用计时器。这是因为其他平台(如iOS和Windows)不需要计时器,因为它们应该能够使用来自这些平台上媒体播放器的进度回调/事件。

    我认为Messenger插件在这里会很有用。请参阅@Kiliman上的N=9插曲,我几乎得到了s使用Messenger插件进行操作。问题是我的
    CurrentProgress()
    方法。我正在运行
    while(true){
    在我的自定义watcher中轮询当前进度,但它显然是阻塞的。我必须弄清楚如何从该方法发出信号,或者在不阻塞的情况下进行观察…我实际上开始使用Messenger插件。我真的希望在视图中不使用任何代码的情况下执行此操作。我将在ViewModel和ev上显示当前位置在共享库中还有其他“希望”的东西。实际上,我希望最终将其转换为另一个MvvmCross插件(如果可能的话)。