AVPlayer
과 함께 정말 이상한 문제가 있습니다. 매우 간단한 뮤직 플레이어 (iTunes Store에서 샘플 음악을 스트리밍)가 시뮬레이터에서 제대로 작동하지만 (iOS 5.1이 적용된 iPhone 및 iPad 모두) 실제 장치에서는 비정상적으로 작동합니다.iOS AVPlayer 스트리밍 음악 문제
iOS 5.1.1이 설치된 iPad 2에서 헤드폰을 장치에 연결해도 제대로 재생됩니다. 하지만 스피커를 연결 해제하자마자 스피커를 통해 소리가 나지 않습니다 (다시 연결하면 노래를들을 수 있음).
iOS 5.1이 설치된 iPhone 4에서는 스피커를 통해 전혀 재생되지 않지만 내 헤드폰을 통해 음악을들을 수 있습니다. 스피커를 통해 연주하는 것 같지는 않지만 현재는 듣고 잠시 동안 음악을 재생할 수 있습니다 (실제로 UI가 그에 따라 반응하기 때문에 실제로 재생되는 것을 확인할 수 있습니다).
나는 요구 사항을 충족시키기 때문에 AVPlayer
을 사용하고 있습니다. 다른 라이브러리를 사용해야합니까? 사운드를 수동으로 라우트해야합니까? 왜 이런 종류의 문제가 있습니까? 그리고 오디오 세션을 올바르게 사용하고 있습니까?
Media.h :
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
#import <AudioToolbox/AudioToolbox.h>
#define NOT_PLAYING -1
@protocol MediaDelegate <NSObject>
@optional
- (void) didEndPlayingAtIndex:(int) index;
- (void) startedToPlayAtIndex:(int) index;
- (void) stoppedToPlayAtIndex:(int) index;
- (void) startedToPlayAtIndex:(int) to fromIndex:(int) from;
- (void) pausedAtIndex:(int) index;
@end
@interface Media : NSObject <AVAudioSessionDelegate>
@property (nonatomic, assign) int currentItem;
@property (nonatomic, strong) NSURL *url;
@property (nonatomic, strong) AVPlayer *player;
@property (nonatomic, assign) id<MediaDelegate> delegate;
- (void) toggle:(int) index;
- (void) stop;
@end
Media.m : 당신이 올바른 오디오 라우팅에 문제가있는 것처럼
#import "Media.h"
@implementation Media
@synthesize currentItem;
@synthesize player;
@synthesize delegate;
@synthesize url;
- (id)init
{
self = [super init];
if (self) {
NSError *activationError = nil;
NSError *setCategoryError = nil;
AVAudioSession *session = [AVAudioSession sharedInstance];
session.delegate = self;
[session setActive:YES error:&activationError];
[session setCategory:AVAudioSessionCategoryPlayback error:&setCategoryError];
if(activationError || setCategoryError)
NSLog(@"ERROR: %@, %@",activationError,setCategoryError);
self.currentItem = NOT_PLAYING;
}
return self;
}
- (void)dealloc{
NSError *activationError = nil;
[[AVAudioSession sharedInstance] setActive:NO error:&activationError];
if(activationError)
NSLog(@"ERROR: %@",activationError);
[self.player removeObserver:self forKeyPath:@"status"];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
switch (player.status) {
case AVPlayerItemStatusReadyToPlay:
[self.player play];
if([self.delegate respondsToSelector:@selector(startedToPlayAtIndex:)])
[self.delegate startedToPlayAtIndex:self.currentItem];
break;
default:
break;
}
}
- (void) toggle:(int) index{
if (self.currentItem == NOT_PLAYING) {
self.player = [AVPlayer playerWithPlayerItem:[AVPlayerItem playerItemWithURL:self.url]];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(didEnd:)
name:AVPlayerItemDidPlayToEndTimeNotification
object:self.player];
self.currentItem = index;
[self.player addObserver:self forKeyPath:@"status" options:0 context:nil];
}
else {
if (self.currentItem == index) {
[self.player pause];
if([self.delegate respondsToSelector:@selector(stoppedToPlayAtIndex:)])
[self.delegate stoppedToPlayAtIndex:index];
self.currentItem = NOT_PLAYING;
[self.player removeObserver:self forKeyPath:@"status"];
self.player = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
else{
[self.player replaceCurrentItemWithPlayerItem:[AVPlayerItem playerItemWithURL:self.url]];
if([self.delegate respondsToSelector:@selector(startedToPlayAtIndex:fromIndex:)])
[self.delegate startedToPlayAtIndex:index fromIndex:self.currentItem];
self.currentItem = index;
}
}
}
- (void) stop{
[self.player pause];
if([self.delegate respondsToSelector:@selector(stoppedToPlayAtIndex:)])
[self.delegate stoppedToPlayAtIndex:self.currentItem];
}
-(void) didEnd:(id)sender{
if([self.delegate respondsToSelector:@selector(didEndPlayingAtIndex:)])
[self.delegate didEndPlayingAtIndex:self.currentItem];
self.currentItem = NOT_PLAYING;
[self.player removeObserver:self forKeyPath:@"status"];
self.player = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - AVAudioSession delegate
-(void)beginInterruption{
NSLog(@"Interruption");
if(self.currentItem != NOT_PLAYING){
[self.player pause];
if([self.delegate respondsToSelector:@selector(pausedAtIndex:)])
[self.delegate pausedAtIndex:self.currentItem];
}
}
-(void)endInterruption{
NSLog(@"Ended interruption");
if(self.currentItem != NOT_PLAYING){
[self.player play];
if([self.delegate respondsToSelector:@selector(startedToPlayAtIndex:)])
[self.delegate startedToPlayAtIndex:self.currentItem];
}
}
@end
나는 그것이 길다는 것을 알고 있지만 setCategory를 호출 한 후에 setActive를 호출 해보십시오. – SteveB
글쎄, 내가 동시에 다른 부분을 변경했기 때문에 그렇게 한 것은 아닙니다.하지만 스피커를 연결 해제 할 때마다 스피커로 라우트되지 않는 사운드는 예외입니다. 헤드폰. 고마워요! – dvieira
AVAudioSessionCategoryPlayback을 사용하면 사운드가 자동으로 스피커로 라우팅됩니다. 그 일을 막는 코드가 있어야합니다. 더 많은 코드를 게시하거나 어딘가에 프로젝트를 업로드 할 수 있다면 한 번 살펴볼 수 있습니다. – SteveB