2013-05-14 22 views
10

Tôi viết trình phát tùy chỉnh từ AVPlayer để phát lại video. Theo tài liệu của Apple thiết lập các lớp video:Tiếp tục phát lại video AVPlayer sau khi ứng dụng hoạt động

self.player = [IPLPlayer new]; 
    self.player.playerLayer = (AVPlayerLayer *)self.playerView.layer; 

đâu self.playerView là lớp bình thường từ những tài liệu:

@implementation PlayerView 

+ (Class) layerClass { 
    return [AVPlayerLayer class]; 
} 

- (AVPlayer *)player { 
    return [(AVPlayerLayer *)[self layer] player]; 
} 

- (void)setPlayer:(AVPlayer *) player { 
    [(AVPlayerLayer *) [self layer] setPlayer:player]; 
} 

Vấn đề là: ứng dụng Khi gần (nút Home), hoặc màn hình khối , phát lại video bị dừng lại và khi tiếp tục phát lại âm thanh CHỈ tiếp tục, hình ảnh trên màn hình vẫn là hình ảnh trước màn hình khối - hoàn toàn là tĩnh và lưu ý các khung thay đổi.

Làm thế nào để tiếp tục phát lại video sau khi màn hình bị chặn?

Có vẻ tôi phải đăng ký thông báo, và sau khi ứng dụng trở nên năng động lớp resume video:

-(void)registerNotification 
{ 
    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(willEnterBackground) 
               name:UIApplicationWillResignActiveNotification object:nil]; 
    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(didEnterForeground) 
               name:UIApplicationDidBecomeActiveNotification object:nil]; 
} 

-(void)unregisterNotification 
{ 
    [[NSNotificationCenter defaultCenter] removeObserver:self]; 
} 


-(void)willEnterBackground 
{ 
    NSLog(@"willEnterBackground"); 
    [self.playerView willEnterBackground]; 
} 

-(void)didEnterForeground 
{ 
    NSLog(@"didEnterForeground"); 
    [self.playerView didEnterForeground]; 
} 

Trả lời

15

Và một giải pháp liên kết tất cả thông tin này với nhau.

Có thể trạng thái người chơi sẽ được xử lý khác nhau, nhưng tôi thích cách đệ quy.

Lưu ý: Nếu bạn không cần thời gian tìm kiếm chính xác, bạn có thể sử dụng [_player seekToTime:<#(CMTime)#> completionHandler:<#^(BOOL finished)completionHandler#>] Nó nhanh hơn nhưng nó tìm đến khung khóa gần nhất.

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

.... 

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnteredForeground) name:UIApplicationWillEnterForegroundNotification object:nil]; 
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appEnteredBackground) name:UIApplicationDidEnterBackgroundNotification object:nil]; 
} 

-(void)viewWillDisappear:(BOOL)animated 
{ 
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillEnterForegroundNotification object:nil]; 
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; 
} 

.... 

-(void) appEnteredForeground { 
    AVPlayerLayer *player = (AVPlayerLayer *)[playerView layer]; 
    [player setPlayer:NULL]; 
    [player setPlayer:_player]; 
    [self playAt:currentTime]; 
} 

-(void) appEnteredBackground { 
    [_player pause]; 
    currentTime = [_player currentTime]; 
} 

-(void)playAt: (CMTime)time { 
    if(_player.status == AVPlayerStatusReadyToPlay && _player.currentItem.status == AVPlayerItemStatusReadyToPlay) { 
     [_player seekToTime:time toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) { 
      [_player play]; 
     }]; 
    } else { 
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 
      [self playAt:time]; 
     }); 
    } 
} 
3

Sử dụng UIApplicationWillEnterForegroundNotification là tốt. Bằng cách đó bạn biết ứng dụng của bạn sẽ được kích hoạt và hiển thị cho người sử dụng:

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(appEnteredForeground:) name:UIApplicationWillEnterForegroundNotification object:nil]; 
+2

Xin lỗi, nhưng câu hỏi của tôi không phải là về nó. – HotJard

1

Sau khi một số nghiên cứu tôi đã tìm thấy, rằng túi cùng là trong máy nghe nhạc iOS (WebBrowser, MPMoviePlayerController). Có thể do loại phân phối nội dung là Tải xuống lũy ​​tiến.

Vì vậy, giải pháp là:

  • Sử dụng dưới đây thông báo và tiết kiệm thời gian hiện tại.
  • Sau khi ứng dụng được tiếp tục, hãy tạo lại AVPlayer và bắt đầu phát từ tiết kiệm thời gian.

Trong tất cả các trường hợp khác, hình ảnh bị chặn hoặc chế độ xem trở thành màu đen.

+0

Đây phải là câu trả lời được chấp nhận. Ngoài ra, nếu bạn thực hiện hành vi trên thông báo, bạn KHÔNG THỂ chuyển đối tượng trình phát tới thông báo UIApplication, nếu thông báo của bạn không bao giờ được gọi là thủ phạm –

1

Bí quyết là để tách tất cả các lớp video từ cầu thủ của họ khi ứng dụng đã nhập nền và reattaching họ khi ứng dụng đã hoạt động trở lại.

Vì vậy, trong bạn -applicationDidEnterBackground: bạn phải kích hoạt một cơ chế có kết quả trong

avPlayerLayer.player = nil; 

và bạn -applicationDidBecomeActive: bạn lắp lại các cầu thủ như

avPlayerLayer.player = self.avPlayer; 

Cũng có một cái nhìn tại Tech này Note (QA1668) từ Apple.

+0

Không phải làm điều đó, có thể nó đã được sửa? –

4

này làm việc cho tôi trên Swift 3

Thêm đâu đó trong khi thiết lập quan điểm:

NotificationCenter.default.addObserver(self, 
    selector: #selector(appWillEnterForegroundNotification), 
    name: .UIApplicationWillEnterForeground, object: nil) 

Grab nghe nhạc của bạn và buộc nó để chơi:

func appWillEnterForegroundNotification() { 
    myPlayer.play() 
} 

Đừng quên loại bỏ các quan sát viên khi bạn không cần chúng:

override func viewWillDisappear(_ animated: Bool) { 
    super.viewWillDisappear(animated) 
    NotificationCenter.default.removeObserver(self) 
} 
+1

Hmm .. Tôi chắc chắn điều này sẽ gây ra +1 cho lớp có chứa nó. Vì vậy, 'deinit' sẽ không bao giờ được gọi. Bạn sẽ phải loại bỏ người quan sát từ một nơi khác để đối tượng không được giải phóng:] –

+1

Vâng 'viewDidDisappear' sẽ là một nơi tốt để loại bỏ người quan sát. – Harish

+0

Tôi đã cập nhật câu trả lời. Cảm ơn bạn @AndresCanella và Harish <3 – budidino