2010-08-11 34 views
31

Tôi hiện đang cố gắng thiết lập âm thanh nền cho ứng dụng tôi đang phát triển cho iOS 4. Ứng dụng không có trình phát nhạc chuyên dụng viewController, tuy nhiên, không giống như âm thanh nền khác các ứng dụng như Pandora, làm cho công việc trở nên khó hiểu hơn một chút.iOS 4: Điều khiển từ xa cho âm thanh nền

Tôi đã đặt chính xác các cài đặt Info.plist thích hợp và có đối tượng AVAudioPlayer trong ứng dụng đại biểu có thể truy cập từ mọi nơi. Khi người dùng phát một bài hát, tôi thay thế AVAudioPlayer bằng một bài hát mới được khởi chạy bằng bài hát và phát bài hát đó. Điều này tất cả các công trình lớn, ngoại trừ bây giờ tôi không có ý tưởng làm thế nào để đi về hỗ trợ các sự kiện điều khiển từ xa.

Dựa trên tài liệu của Apple, tôi có điều này:

- (void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:animated]; 
    [[UIApplication sharedApplication] beginReceivingRemoteControlEvents]; 
    [self becomeFirstResponder]; 
} 

- (void)viewWillDisappear:(BOOL)animated { 
    [super viewWillDisappear:animated]; 
    [[UIApplication sharedApplication] endReceivingRemoteControlEvents]; 
    [self resignFirstResponder]; 
} 

- (BOOL)canBecomeFirstResponder { 
    return YES; 
} 

- (void)remoteControlReceivedWithEvent:(UIEvent *)event { 
    switch(event.subtype) { 
     case UIEventSubtypeRemoteControlTogglePlayPause: 
      if([iPhoneAppDelegate backgroundAudioPlayer].playing) 
       [iPhoneAppDelegate pauseBackgroundAudioPlayer]; 
      else 
       [iPhoneAppDelegate playBackgroundAudioPlayer]; 
      break; 
    } 
} 

Có điều là, nơi nào tôi đặt này? Tài liệu của Apple dường như đề nghị điều này nên đi trong một số bộ điều khiển xem một nơi nào đó, nhưng ứng dụng của tôi có rất nhiều bộ điều khiển xem và bộ điều khiển điều hướng. Bất cứ nơi nào tôi cố gắng đặt điều này, vì lý do nào đó, nhấn nút Toggle Play/Pause trong khay điều khiển từ xa đa nhiệm khiến bài hát tạm dừng một lúc và sau đó bỏ tạm dừng hoặc bằng cách nào đó khiến bài hát phát hai lần.

+0

Cách u thay đổi nút phát/dừng trong thanh tác vụ đa nhiệm ?! –

Trả lời

19

Tôi đã tìm thấy một vài giải pháp để nhận sự kiện kiểm soát từ xa toàn cầu trên Diễn đàn nhà phát triển Apple sau một chút tìm kiếm.

Một cách là để phân lớp UIWindow và ghi đè remoteControlReceivedWithEvent: của nó.

Cách thứ hai, có lẽ đẹp hơn là phân lớp UIApplication và ghi đè sendEvent:. Bằng cách đó, bạn có thể chặn tất cả các sự kiện điều khiển từ xa và xử lý chúng ở đó trên toàn cầu và không có bất kỳ người phản hồi nào khác xử lý chúng sau này trong chuỗi phản hồi.

- (void)sendEvent:(UIEvent *)event { 
    if (event.type == UIEventTypeRemoteControl) { 
      // Handle event 
    } 
    else 
      [super sendEvent:event]; 
} 
+2

Xem nhận xét của tôi về câu trả lời của Brian Dam Pedersen – HiveHicks

+0

Một cách hay hơn để làm điều này là thêm nó vào UIApplication bình thường trong một loại – hypercrypt

+0

Tôi muốn giới thiệu Brian's Answer – Mazyod

4

Phương pháp thứ hai không hoạt động đối với tôi, sendEvent chưa bao giờ được gọi. Tuy nhiên phương pháp đầu tiên chỉ làm việc tốt (subclassing UIWindow).

+0

Hoạt động như một sự quyến rũ. Tôi muốn thêm rằng beginReceivingRemoteControlEvents có thể được gọi bên trong của đại biểu ứng dụng để đăng ký cho sự kiện điều khiển từ xa. – Andy

0

Không cần phải phân lớp cửa sổ hoặc chuyển tiếp sự kiện. Đơn giản chỉ cần xử lý nó từ bộ điều khiển xem chính của bạn. Xem ví dụ về Trình trộn âm thanh (MixerHost) để biết chi tiết.

http://developer.apple.com/LIBRARY/IOS/#samplecode/MixerHost/Listings/Classes_MixerHostViewController_m.html

+2

Vấn đề là, bộ điều khiển chế độ xem chính của bạn không phải lúc nào cũng xuất hiện trên màn hình trong khi ứng dụng chuyển sang nền, nghĩa là ứng dụng sẽ không trở thành trả lời đầu tiên nếu phương thức trên màn hình. – pablasso

+0

@pablasso có thể tùy thuộc vào ứng dụng. Nhưng không phải trong mọi trường hợp, tôi đồng ý với điều đó. – slf

37

Các ví dụ tài liệu là một chút sai lầm, nhưng không có nhu cầu để phân lớp bất cứ điều gì bất cứ nơi nào. Nơi chính xác để đặt remoteControlReceivedWithEvent: là trong ứng dụng đại biểu, vì nó vẫn còn trong chuỗi trả lời bất kể cho dù các ứng dụng đang ở phía trước hay không. Ngoài ra bắt đầu/kết thúc nhận được sự kiện điều khiển từ xa nên được dựa trên việc bạn thực sự cần các sự kiện, không phải trên tầm nhìn của một số xem ngẫu nhiên.

+11

Hoàn toàn chính xác. Để kiểm soát hoàn toàn các điều khiển từ xa cho ứng dụng của bạn (cho dù đó là tiền cảnh hoặc nền) bạn cần gọi beginReceivingRemoteControlEvents trong ứng dụng: didFinishLaunchingWithOptions :, nhưng đó không phải là tất cả. UIApplicationDelegate của bạn bắt đầu nhận các sự kiện điều khiển từ xa sau khi ứng dụng của bạn cho iOS biết rằng nó đang phát một bản nhạc - bằng cách thiết lập thuộc tính MPNowPlayingInfoCenter nowPlayingInfo. – HiveHicks

+0

Nó thực sự là câu trả lời tuyệt vời, tôi đã bị mắc kẹt từ một tuần. –

+0

Đưa remoteControlReceivedWithEvent: vào ứng dụng đại biểu chỉ không làm việc cho tôi; Tôi đã phải đi với subclassing UIWindow. – JosephH

3

Tôi đã vật lộn với vấn đề này một lúc và không có câu trả lời nào ở trên hiệu quả. Lỗi trong mã của tôi, và tôi hy vọng rằng nó sẽ giúp ai đó đọc được điều này, là tôi đã đặt AudioSession để kết hợp với những người khác. Bạn muốn trở thành trình phát âm thanh nền trước để nhận các sự kiện Điều khiển từ xa. Hãy kiểm tra để xem nếu bạn có mã KHÔNG ĐÚNG như thế này:

[[AVAudioSession sharedInstance] setDelegate: self]; 
    [[AVAudioSession sharedInstance] setCategory: AVAudioSessionCategoryPlayback error: nil]; 
    UInt32 doSetProperty = 0; 
    AudioSessionSetProperty (
          kAudioSessionProperty_OverrideCategoryMixWithOthers, 
          sizeof (doSetProperty), 
          &doSetProperty 
          ); 
    NSError *activationError = nil; 
    [[AVAudioSession sharedInstance] setActive: YES error: &activationError];  

Và loại bỏ các AudioSessionSetProperty, hoặc thay đổi doSetProperty để 1.

0

Một điều có vẻ ảnh hưởng đến hành vi này là bất kỳ tùy chọn danh mục nào bạn đặt cho AVAudioSession bằng setCategory: withOptions: error: thay vì chỉ setCategory: error :. Đặc biệt, từ thử nghiệm và lỗi, có vẻ như nếu bạn đặt AVAudioSessionCategoryOptionMixWithOthers bạn sẽ không nhận được các sự kiện điều khiển từ xa; các điều khiển đang phát sẽ vẫn kiểm soát ứng dụng iPod. Nếu bạn đặt AVAudioSessionCategoryOptionDuckOthers bạn sẽ nhận được các sự kiện điều khiển từ xa, nhưng có vẻ như có thể có một số sự mơ hồ về ứng dụng được kiểm soát. Đặt categoryOptions thành 0 hoặc chỉ gọi setCategory: error: hoạt động tốt nhất.

Các vấn đề liên quan