2

I am new so excuse me if I dont ask a question right or post enough information.

I am new to creating mobile applications and i am using Xamarin.Forms to create a custom view. with this view I am using an Android ViewRenderer to play audio/video with built in android MediaPlayer/VideoView.

pretty much the exact same thing as the android renderer posted and accepted as the answer for Renderer I copied and is working

My issue is when the video starts and you click the homepage/back button the audio continues playing for a few seconds and then stops. I want to audio to stop immediately.

Methods I have tried:

In my ViewRenderer I have attempted to override SurfaceDestroyed to call player.stop(). This has not worked, no errors or anything just audio continues like this code doesnt exist. Audio stops after about 3-5 seconds.

In the ViewRenderer I have attempted to use the Control.SystemUiVisibilityChange event to call player.stop(). No errors or anything. Audio continues for 3-5 seconds.

I am unable to pass the player instance to the main activity onPause() method as I am to new to Xamarin.Forms and android ViewRenderers to understand how to. Possibly calling this player.stop() on the onPause() method will work but I cant find how to do this. Can anyone assist? I have searched many forums for weeks and have finally given up to post a question.

Peter Zhao
  • 7,456
  • 3
  • 21
  • 22
Nick C
  • 21
  • 1
  • Have you tried overriding onbackbuttonpressed() and ondisappearing() to then put player.stop() on that? – Behavior Feb 28 '18 at 10:32
  • I did start to try that but was unable to get the proper override structure to override onbackbuttonpressed() from my viewrenderer. I will work on trying that tonight to see if that works. When my app is interrupted (call / another app / minimized) is onbackbuttonpressed() called? I thought onPause() was called from the MainActivity when the home button was pressed. If thats the case how to I find the mediaplayer instance from MainActivity if its initiated and called by a viewrenderer? – Nick C Feb 28 '18 at 19:51
  • I did try override OnDisappearing from the Xamarin.Forms application. In my view I made a method called "StopAction" and on my renderer im doing e.newelement.StopAction => () => player.pause(); On my ondisappearing I was calling "VideoView.StopAction()" and the video would not pause. I would get a null error and then the application would do its normal behavior. – Nick C Feb 28 '18 at 20:14

1 Answers1

1

For back button, you simply need to override OnBackButtonPressed of your current Xamarin.Forms' page:

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

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

For home button, I referred to this thread and made a Xamarin version of HomeWatcher out of Jack's answer:

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();
                        }
                    }
                }
            }
        }
    }
}

And use it in the VideoViewRenderer ( StartWatch() when video start play, StopWatch() when the videoview is cleaned):

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
        });

       ...
     }

  }
Elvis Xia - MSFT
  • 10,801
  • 1
  • 13
  • 24
  • Elvis, Thank you. I didnt get a change to work on my code last night I will attempt to do it tonight and let you know and accept the answer if it works. Thanks! – Nick C Mar 01 '18 at 18:26
  • So this did not work for me either. It appears that on the first time im calling this.player.pause(); in my code its not registering. If I hit pause then play then pause my mediaplayer pauses..... its a really weird issue. I think my question has nothing to do with a home button reading. Should I form a new question with code samples? – Nick C Mar 04 '18 at 04:53
  • You need to provide your codes of implementation. You can form a new question, if you want. – Elvis Xia - MSFT Mar 05 '18 at 00:31