【问题标题】:Xamarin.Forms ViewRenderer audio doesnt stop on homepage/backbuttonXamarin.Forms ViewRenderer 音频不会在主页/后退按钮上停止
【发布时间】:2018-03-01 10:27:19
【问题描述】:

我是新手,如果我没有正确提出问题或发布足够的信息,请原谅。

我是创建移动应用程序的新手,我正在使用Xamarin.Forms 创建自定义视图。有了这个视图,我正在使用 Android ViewRenderer 来播放内置 android MediaPlayer/VideoView 的音频/视频。

与发布并接受为Renderer I copied and is working的答案的android渲染器几乎完全相同

我的问题是当视频开始播放并单击主页/返回按钮时,音频会继续播放几秒钟然后停止。我想立即停止音频。

我尝试过的方法:

在我的ViewRenderer 中,我尝试通过override SurfaceDestroyed 致电player.stop()。这不起作用,没有错误或任何只是音频继续,就像此代码不存在一样。大约 3-5 秒后音频停止。

ViewRenderer 中,我尝试使用Control.SystemUiVisibilityChange 事件调用player.stop()。没有错误或任何东西。音频持续 3-5 秒。

我无法将 player 实例传递给主要活动 onPause() 方法,因为我是 Xamarin.Forms 和 android ViewRenderers 的新手以了解如何。可能在onPause() 方法上调用此player.stop() 将起作用,但我找不到如何执行此操作。有人可以帮忙吗?我搜索了许多论坛数周,最终放弃发布问题。

【问题讨论】:

  • 您是否尝试过覆盖 onbackbuttonpressed() 和 ondisappearing() 然后将 player.stop() 放在上面?
  • 我确实开始尝试这样做,但无法从我的查看器中获得正确的覆盖结构来覆盖 onbackbuttonpressed()。今晚我将努力尝试,看看是否有效。当我的应用程序被中断(调用/另一个应用程序/最小化)时,是否调用 onbackbuttonpressed()?我认为按下主页按钮时从 MainActivity 调用 onPause() 。如果是这种情况,我如何从 MainActivity 中找到 mediaplayer 实例,如果它是由 viewrenderer 发起和调用的?
  • 我确实尝试过覆盖 Xamarin.Forms 应用程序中的 OnDisappearing。在我看来,我创建了一个名为“StopAction”的方法,并在我的渲染器上执行 e.newelement.StopAction => () => player.pause();在我消失时,我正在调用“VideoView.StopAction()”并且视频不会暂停。我会收到一个 null 错误,然后应用程序会执行其正常行为。

标签: android xamarin xamarin.forms android-mediaplayer viewrendering


【解决方案1】:

对于后退按钮,您只需覆盖当前Xamarin.Forms'页面的OnBackButtonPressed

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
    }

    protected override bool OnBackButtonPressed()
    {
        //stop the videoview
        videoview.Stop();
        return base.OnBackButtonPressed();
    }
   ...
}

对于主页按钮,我参考了 this thread 并根据 Jack 的回答制作了 HomeWatcher 的 Xamarin 版本:

public interface IOnHomePressedListener
{
    void OnHomePressed();
    void OnHomeLongPressed();
}

public class HomeWatcher
{
    static readonly String TAG = "hg";
    private Context mContext;
    private IntentFilter mFilter;
    private IOnHomePressedListener mListener;
    private InnerRecevier mRecevier;

    public HomeWatcher(Context context)
    {
        mContext = context;
        mFilter = new IntentFilter(Intent.ActionCloseSystemDialogs);
    }

    public void SetOnHomePressedListener(IOnHomePressedListener listener)
    {
        mListener = listener;
        mRecevier = new InnerRecevier(mListener);
    }

    public void StartWatch()
    {
        if (mRecevier != null)
        {
            mContext.RegisterReceiver(mRecevier, mFilter);
        }
    }

    public void StopWatch()
    {
        if (mRecevier != null)
        {
            mContext.UnregisterReceiver(mRecevier);
        }
    }


    private class InnerRecevier : BroadcastReceiver
    {
        readonly String SYSTEM_DIALOG_REASON_KEY = "reason";
        readonly String SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS = "globalactions";
        readonly String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
        readonly String SYSTEM_DIALOG_REASON_HOME_KEY = "homekey";
        IOnHomePressedListener _listener;

        public InnerRecevier(IOnHomePressedListener listener)
        {
            _listener = listener;
        }

        public override void OnReceive(Context context, Intent intent)
        {
            String action = intent.Action;
            if (action.Equals(Intent.ActionCloseSystemDialogs))
            {
                String reason = intent.GetStringExtra(SYSTEM_DIALOG_REASON_KEY);
                if (reason != null)
                {
                    //Log.e(TAG, "action:" + action + ",reason:" + reason);
                    if (_listener != null)
                    {
                        if (reason.Equals(SYSTEM_DIALOG_REASON_HOME_KEY))
                        {
                            _listener.OnHomePressed();
                        }
                        else if (reason.Equals(SYSTEM_DIALOG_REASON_RECENT_APPS))
                        {
                            _listener.OnHomeLongPressed();
                        }
                    }
                }
            }
        }
    }
}

并在VideoViewRenderer(视频开始播放时StartWatch(),清理视频视图时StopWatch())中使用它:

public class VideoViewRenderer : ViewRenderer<VideoView, Android.Widget.VideoView>, ISurfaceHolderCallback,IOnHomePressedListener
{
    ...

    private MediaPlayer _player;

    private HomeWatcher _homeWatcher;



    public VideoViewRenderer(Context context) : base(context)
    {
        _context = context;
        _homeWatcher = new HomeWatcher(context);
        _homeWatcher.SetOnHomePressedListener(this);

    }

    protected override void OnElementChanged(ElementChangedEventArgs<CustomVideoViewDemo.VideoView> e)
    {
        base.OnElementChanged(e);


        e.NewElement.CleanAction = new Action(() =>
        {
            #region Clean video player action (player no more used)

            if (_player == null)
                return;
            //stop watch home button
            _homeWatcher.StopWatch();


            _player.Release();

            #endregion
        });



        e.NewElement.PlayAction = new Action(() =>
        {
            #region Play video if it was stopped


            if (_player == null)
                return;
            //start watch home button
            _homeWatcher.StartWatch();
            if (!_player.IsPlaying)
            {
                _player.Start();
            }

            #endregion
        });

       ...
     }

  }

【讨论】:

  • 猫王,谢谢。昨晚我没有对我的代码进行更改,我今晚会尝试这样做,如果可行,请告诉您并接受答案。谢谢!
  • 所以这对我也不起作用。看来我第一次调用 this.player.pause();在我的代码中它没有注册。如果我点击暂停然后播放然后暂停我的媒体播放器暂停......这是一个非常奇怪的问题。我认为我的问题与主页按钮阅读无关。我应该用代码示例形成一个新问题吗?
  • 您需要提供您的实施代码。如果需要,您可以提出一个新问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多