1

This is my (Xamarin C#) code: (player is an AVPlayer.)

var v = NSNotificationCenter.DefaultCenter.AddObserver(new NSString("Status"), ReadyNow, player.CurrentItem);

It never calls ReadyNow(NSNotification obj) even though the player plays fine.

How do I fix it to call the method? (I don't know if the error is in the Xamarin/C# part or in the object I'm using etc. which would be the same error if written in Swift.)

ispiro
  • 26,556
  • 38
  • 136
  • 291

2 Answers2

1

You can get the player's current item and add the observer to it.

The property:

private AVPlayerItem CurrentItem => Player.CurrentItem;

The observer:

CurrentItem.AddObserver(this, new NSString("status"), 
    NSKeyValueObservingOptions.New | NSKeyValueObservingOptions.Initial,
    StatusObservationContext.Handle);

If you want, you can also attach loadedTimeRanges:

CurrentItem.AddObserver(this, new NSString("loadedTimeRanges"), 
    NSKeyValueObservingOptions.Initial | NSKeyValueObservingOptions.New,
    LoadedTimeRangesObservationContext.Handle);

NB: Always be sure to detach the observer for the status before attaching:

CurrentItem.RemoveObserver(this, new NSString("status"));

Edit: StatusObservationContext is simply a property, pointing to status string.

public static readonly NSString StatusObservationContext = new NSString("Status");

Useful resources You can find everything that you may need for your AVPlayer implementation in Martinj's excellent package - XamarinMediaManager.

Sources:

  1. Play Audio and Video with the MediaManager Plugin for Xamarin
  2. Plugin.MediaManager NuGet
  3. GitHub
Mihail Duchev
  • 4,691
  • 10
  • 25
  • 32
  • Thanks. `Always be sure to detach the observer for the status to an item without one!` - I don't understand that sentence. – ispiro May 22 '20 at 10:17
  • Also, I don't have a `StatusObservationContext`. – ispiro May 22 '20 at 10:54
  • 1
    I used it a little different, but the `CurrentItem.AddObserver` is what led me on the right path. Thanks! – ispiro May 27 '20 at 19:42
  • By the way, I upvoted your answer too (and the other answer as well) but it looks like someone downvoted both. They are both now at 0 but the breakdown shows a +1 (mine) and a -1 for both answers. – ispiro May 27 '20 at 19:44
0

You are trying to observe on the single AVPlayerItem instance is currently held in the CurrentItem property, even if it is currently null.

You can observe on the AVPlayer instance and use the keyPath of the NSObject that you wish to observe changes on:

Example:

obs = player.AddObserver("currentItem", NSKeyValueObservingOptions.New, (NSObservedChange obj) =>
{
    Console.WriteLine($"{obj.NewValue}");
});

Note: Hold a ref. to the returned IDisposable otherwise your observer can go out of scope and|or you will leak mem.

SushiHangover
  • 73,120
  • 10
  • 106
  • 165
  • Thanks. I'm checking that out now. But what did you mean by that last paragraph? Are you referring to `obs`? I thought I can just ignore it and let it get GCd. If not - I'm really glad I asked this question! – ispiro Sep 05 '19 at 20:54
  • @ispiro The observable `IDisposable` is holding a naive ref, GC'ing does not call dispose: https://stackoverflow.com/questions/1691846/does-garbage-collector-call-dispose – SushiHangover Sep 06 '19 at 13:49