设备在音频播放AVPlayer期间重新启动

时间:2013-01-15 03:20:10

标签: iphone objective-c ios6 avplayer

我有一个iPhone和iPad的应用程序,使用AVPlayer播放音频流,我使用Apple Sample StitchedStreamPlayer的相同播放器,但我做了一些更改来播放音乐而不是视频。

当我运行应用程序时,我可以听几秒钟然后,设备重新启动并显示以下错误:

终止以响应SpringBoard的终止。

(当我在设备上使用xcode运行它会播放几分钟时,但当我拔下设备并再次运行应用时,应用程序崩溃了)

我正在使用iPhone 4和iPad mini进行测试,其中没有一个是Jailbroken,而且展位是iOS 6。

代码非常大,但这里有一些部分:

头:

@interface NewPlayer : NSObject <AVAudioSessionDelegate>

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

一些重要的实施方法

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

如果你想深入了解一下,只需看看StitchedStreamPlayer Sample,我就不知道了。我看过了:

Failed to play audio file using AVPlayer in iPhone

memory leak in AudioToolbox library AVAudioPlayer

AudioToolBox leak in iOS6?

和其他许多人......

我试图忘记所有这些实现,只使用

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

[player play];

但它崩溃了!

有些想法?

EDITED

我尝试了MPMoviePlayerController,但同样的情况发生了,音乐开始了,然后设备重新启动。

这是我用过的代码:

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

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

        [player play];

0 个答案:

没有答案
相关问题