1

I have an app for iPhone and iPad that plays an audio stream using AVPlayer, I am using the same player of the Apple Sample StitchedStreamPlayer, but I made some changes to play music instead of video.

When I run the app, I can listen for some few seconds and then, the device restarts and following error is displayed:

Terminating in response to SpringBoard's termination.

(when I am running using xcode on the device it plays some minutes, but when I unplug the device and run the app again the app crashes)

I am using the iPhone 4 and an iPad mini for testing, none of them are Jailbroken and booth are iOS 6.

The code is quite big, but here is some parts:

header:

@interface NewPlayer : NSObject <AVAudioSessionDelegate>

@property (strong) AVPlayer *player;
@property (strong) AVPlayerItem *playerItem;

some important methods of Implementation

-(void)play:(NSString *)audio
{
    /* Has the user entered a audio URL? */

    NSURL *audioUrl = [NSURL URLWithString:audio];
    if ([audioUrl scheme])  /* Sanity check on the URL. */
    {
        /*
         Create an asset for inspection of a resource referenced by a given URL.
         Load the values for the asset keys "tracks", "playable".
         */
        AVURLAsset *asset = [AVURLAsset URLAssetWithURL:audioUrl options:nil];

        NSArray *requestedKeys = [NSArray arrayWithObjects:kTracksKey, kPlayableKey, nil];

        /* Tells the asset to load the values of any of the specified keys that are not already loaded. */
        [asset loadValuesAsynchronouslyForKeys:requestedKeys completionHandler:
         ^{
             dispatch_async( dispatch_get_main_queue(),
                            ^{
                                /* IMPORTANT: Must dispatch to main queue in order to operate on the AVPlayer and AVPlayerItem. */
                                [self prepareToPlayAsset:asset withKeys:requestedKeys];
                            });
         }];
    }

}






- (void)prepareToPlayAsset:(AVURLAsset *)asset withKeys:(NSArray *)requestedKeys
{
    /* Make sure that the value of each key has loaded successfully. */
    for (NSString *thisKey in requestedKeys)
    {
        NSError *error = nil;
        AVKeyValueStatus keyStatus = [asset statusOfValueForKey:thisKey error:&error];
        if (keyStatus == AVKeyValueStatusFailed)
        {
            [self assetFailedToPrepareForPlayback:error];
            return;
        }
        /* If you are also implementing the use of -[AVAsset cancelLoading], add your code here to bail
         out properly in the case of cancellation. */
    }

    /* Use the AVAsset playable property to detect whether the asset can be played. */
    if (!asset.playable)
    {
        /* Generate an error describing the failure. */
        NSString *localizedDescription = NSLocalizedString(@"Item cannot be played", @"Item cannot be played description");
        NSString *localizedFailureReason = NSLocalizedString(@"The assets tracks were loaded, but could not be made playable.", @"Item cannot be played failure reason");
        NSDictionary *errorDict = [NSDictionary dictionaryWithObjectsAndKeys:
                                   localizedDescription, NSLocalizedDescriptionKey,
                                   localizedFailureReason, NSLocalizedFailureReasonErrorKey,
                                   nil];
        NSError *assetCannotBePlayedError = [NSError errorWithDomain:@"StitchedStreamPlayer" code:0 userInfo:errorDict];

        /* Display the error to the user. */
        [self assetFailedToPrepareForPlayback:assetCannotBePlayedError];

        return;
    }

    /* At this point we're ready to set up for playback of the asset. */

    /* Stop observing our prior AVPlayerItem, if we have one. */
    if (self.playerItem)
    {
        /* Remove existing player item key value observers and notifications. */

        [self.playerItem removeObserver:self forKeyPath:kStatusKey];

        [[NSNotificationCenter defaultCenter] removeObserver:self
                                                        name:AVPlayerItemDidPlayToEndTimeNotification
                                                      object:self.playerItem];
    }

    /* Create a new instance of AVPlayerItem from the now successfully loaded AVAsset. */
    self.playerItem = [AVPlayerItem playerItemWithAsset:asset];

    /* Observe the player item "status" key to determine when it is ready to play. */
    [self.playerItem addObserver:self
                      forKeyPath:kStatusKey
                         options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                         context:MyStreamingAudioViewControllerPlayerItemStatusObserverContext];

    /* When the player item has played to its end time we'll toggle
     the movie controller Pause button to be the Play button */
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playerItemDidReachEnd:)
                                                 name:AVPlayerItemDidPlayToEndTimeNotification
                                               object:self.playerItem];


    /* Create new player, if we don't already have one. */
    if (![self player])
    {
        /* Get a new AVPlayer initialized to play the specified player item. */
        [self setPlayer:[AVPlayer playerWithPlayerItem:self.playerItem]];

        /* Observe the AVPlayer "currentItem" property to find out when any
         AVPlayer replaceCurrentItemWithPlayerItem: replacement will/did
         occur.*/
        [self.player addObserver:self
                      forKeyPath:kCurrentItemKey
                         options:NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew
                         context:MyStreamingAudioViewControllerCurrentItemObservationContext];


    }

    /* Make our new AVPlayerItem the AVPlayer's current item. */
    if (self.player.currentItem != self.playerItem)
    {
        /* Replace the player item with a new player item. The item replacement occurs
         asynchronously; observe the currentItem property to find out when the
         replacement will/did occur*/
        [[self player] replaceCurrentItemWithPlayerItem:self.playerItem];

        [self syncPlayPauseButtons];
    }

}





- (void)observeValueForKeyPath:(NSString*) path
                      ofObject:(id)object
                        change:(NSDictionary*)change
                       context:(void*)context
{
    /* AVPlayerItem "status" property value observer. */
    if (context == MyStreamingAudioViewControllerPlayerItemStatusObserverContext)
    {
        [self syncPlayPauseButtons];

        AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
        switch (status)
        {
                /* Indicates that the status of the player is not yet known because
                 it has not tried to load new media resources for playback */
            case AVPlayerStatusUnknown:
            {
                NSLog(@"desconhecido");
            }
                break;

            case AVPlayerStatusReadyToPlay:
            {
                /* Once the AVPlayerItem becomes ready to play, i.e.
                 [playerItem status] == AVPlayerItemStatusReadyToPlay,
                 its duration can be fetched from the item. */
                NSLog(@"ready to play");

                [player play];

                [self.delegate tocandoMusica];

            }
                break;

            case AVPlayerStatusFailed:
            {
                AVPlayerItem *thePlayerItem = (AVPlayerItem *)object;
                [self assetFailedToPrepareForPlayback:thePlayerItem.error];
                NSLog(@"falhou");

                [self.delegate acabouMusica];
            }
                break;
        }
    }
    /* AVPlayer "rate" property value observer. */
    else if (context == MyStreamingAudioViewControllerRateObservationContext)
    {
        //[self syncPlayPauseButtons];
    }
    /* AVPlayer "currentItem" property observer.
     Called when the AVPlayer replaceCurrentItemWithPlayerItem:
     replacement will/did occur. */
    else if (context == MyStreamingAudioViewControllerCurrentItemObservationContext)
    {
        AVPlayerItem *newPlayerItem = [change objectForKey:NSKeyValueChangeNewKey];

        /* New player item null? */
        if (newPlayerItem == (id)[NSNull null])
        {
            //[self disablePlayerButtons];
            //[self disableScrubber];


        }
        else /* Replacement of player currentItem has occurred */
        {

            /* Specifies that the player should preserve the video’s aspect ratio and
             fit the video within the layer’s bounds. */

            [self syncPlayPauseButtons];
        }
    }
    /* Observe the AVPlayer "currentItem.timedMetadata" property to parse the media stream
     timed metadata. */
    else if (context == MyStreamingAudioViewControllerTimedMetadataObserverContext)
    {
        //NSArray* array = [[player currentItem] timedMetadata];
        //for (AVMetadataItem *metadataItem in array)
        //{

        //}
    }
    else
    {
        [super observeValueForKeyPath:path ofObject:object change:change context:context];
    }

    return;
}

If you want to take a deep look, just take a look on StitchedStreamPlayer Sample, I have no idea. I have looked at:

Failed to play audio file using AVPlayer in iPhone

memory leak in AudioToolbox library AVAudioPlayer

AudioToolBox leak in iOS6?

and many others..

I have tried to forget all this implementation and use just

player = [AVPlayer playerWithURL:[NSURL URLWithString:url]];

[player play];

but it crashes!

Some idea?

EDITED

I Have tried the MPMoviePlayerController but the same happened, the music started and then the device restarted.

This is the code I have used:

[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:NULL];

        player = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:[[arrRadios objectAtIndex:indexPath.row] objectForKey:@"url"]]];

        [player play];
Community
  • 1
  • 1
Roberto Ferraz
  • 2,511
  • 24
  • 43

0 Answers0