XamarinMediaManager icon indicating copy to clipboard operation
XamarinMediaManager copied to clipboard

How to manage errors related to the URL or to connectivity?

Open pcdus opened this issue 4 years ago • 7 comments

Hello,

I use the XamarinMediaManager in a Xamarin.Forms project, to play audio from a web radio.

But I would like to manage error cases, like when the URL is no longer available, or if there is not internet access for example.

I launch the audio stream like this: var mediaItem = await CrossMediaManager.Current.Play(audioUrl);

If I use a "wrong" URL, nothing happens, but I didn't found how to "identify" this case. It's the same thing if I activate the airplane mode.

I would like to display an error message to the user in both cases, so he could understand why the audio doesn't launch.

Is there a way to manage this?

pcdus avatar Feb 09 '21 16:02 pcdus

From the top of my head: there's a OnMetadataUpdated that you can subscribe to for updates. mediaItem.MetadataUpdated += (sender, args) => { var title = args.MediaItem.Title; // Perhands check for null values and act accordingly. };

RichardSV15 avatar Feb 09 '21 21:02 RichardSV15

Thanks @RichardSV15, it's seems the better solution.

pcdus avatar Feb 11 '21 09:02 pcdus

Finally, I've did like this:

var mediaItem = await mediaManager.Play(radioUrl);
CurrentTitle = mediaItem.Title;
Debug.WriteLine($"PlayStopAsync() - CurrentTitle: {CurrentTitle.ToString()}");
mediaItem.MetadataUpdated += (sender, args) =>
{
    CurrentTitle = args.MediaItem.Title;
    Debug.WriteLine($"PlayStopAsync() - mediaItem.MetadataUpdated  - CurrentTitle: {CurrentTitle}");
};

I check the Title directly from the mediaItem: it seems the MetadataUpdated is never fired, from a valid or from a invalid URL...

However, I find strange that if I use an invalid URL, the State varies to Paused:

private void OnStateChanged(object sender, MediaManager.Playback.StateChangedEventArgs e)
{
    Debug.WriteLine($"OnStateChanged() - StateChangedEventArgs e: {e.State.ToString()}");
    ...
}

Cause if the user try to press the "Play" button a second time, the State varies to Buffering and the to Playing. To abord this, I'm forced to call mediaManager.Stop() if the CurrentTitle is null.

So it works now, but it's not very clear...

pcdus avatar Feb 11 '21 12:02 pcdus

Finally, I've implemented a solution that one have suggested by using MediaItem.Title:

var mediaItem = await CrossMediaManager.Current.Play(radioUrl);
var currentTitle = mediaItem.Title;

This only works for iOS, on Android the use of mediaItem.Title raise an Exception...

So, to manage Android case, I use the MediaItemFailed:

CrossMediaManager.Current.MediaItemFailed += OnCurrentMediaItemFailed; 

The event is only raised after 1 minute on Android, and it's not raised at all on iOS.

This solution is not perfect and is no the same for 2 platforms, but I don't found a better one yet...

pcdus avatar Feb 12 '21 18:02 pcdus

Thanks for bringing it up and posting your solution. I'll be implementing it myself, on dead links that users may be trying replay... The events not firing seems to be consistent across a few other issues that I've seen come up with the library. Not ideal but still this library is still the best go to for media management

RichardSV15 avatar Feb 13 '21 04:02 RichardSV15

In add to this, I would like to know if there is a way to "cancel" a Play() request? I've tried to call Stop() in case of errros, but it doesn't seem having any effet: the State is still Pause or Buffering after this...

pcdus avatar Feb 17 '21 11:02 pcdus

I've did some investigations, and it seems that the behaviour is not the same on iOS and Android.

As a reminder, I would like to manage errors that can occur when the user try to play a webradio stream.

On Android, I use the MediaItemFailed event, that is raised after 1 minute: CrossMediaManager.Current.MediaItemFailed += OnCurrentMediaItemFailed;

On iOS the event is not raised, so I check the MediaItem.Title like this:

var mediaItem = await CrossMediaManager.Current.Play(radioUrl);
var currentTitle = mediaItem.Title;

But in both cases, I would to display an error message to the user, and to reset CrossMediaManager.Current.State to Stopped.

For this, I call the Stop() method when an issue is detected: await CrossMediaManager.Current.Stop();

But this seems only working on Android. On iOS, the State is still Pause or Buffering after this...

Is there any explanation?

pcdus avatar Feb 19 '21 11:02 pcdus