簡體   English   中英

iOS Audio Streaming僅適用於**某些**藍牙設備?

[英]iOS Audio Streaming only works for **SOME** bluetooth devices?

我正在開發iOS應用程序,它將與iOS 6/7兼容並從網站流式傳輸音頻.mp3文件。

已經使用以下代碼將其工作:

-(NSString*)documentsFolder
{
    NSString* dataPath =  [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
    if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath])
        [[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:NULL];
    return dataPath;
}

-(NSString*)createURLFile:(NSString*)songURL
{
   NSString* M3U_FILE = @"song.m3u";
   NSString* path = [NSString stringWithFormat:@"%@",[[self documentsFolder] stringByAppendingPathComponent:M3U_FILE]];
    if([[NSFileManager defaultManager] createFileAtPath:path contents:nil attributes:nil])
    {
      NSFileHandle* outFile = [NSFileHandle fileHandleForWritingAtPath:path];
        if(outFile != nil)
      {
         NSData* buffer = [songURL dataUsingEncoding:NSUTF8StringEncoding];
         [outFile writeData:buffer];
         return path;
      }
   }
    return nil;
}


- (void)createStreamer
{
    // Remove any previous references.
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    // Create a new player.
    NSString* fileURL = [self createURLFile:self.aSong.songpath];
    self.songPlayer = [[AVPlayer alloc]initWithURL:[NSURL fileURLWithPath:fileURL]];
    NSAssert(self.songPlayer != nil, @"NIL AVPlayer Created!!!");
    // Observer for when the song ends...
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(playerItemDidReachEnd:)
                                                 name:AVPlayerItemDidPlayToEndTimeNotification
                                               object:[self.songPlayer currentItem]];
    [[UIApplication sharedApplication] setIdleTimerDisabled: YES];
}

我將.mp3文件的url存儲在本地.m3u文件中,並使用它來加載AVPlayer。 在早期版本的iOS中,我被告知AVPlayer會首先加載歌曲然后播放它,而不是立即播放它。 雖然這在iOS 6/7中似乎不是這樣(歌曲幾乎立即開始流式傳輸),但是正在創建.m3u文件以防萬一由於沒有以這種方式完成而產生任何問題。

有了這個,一個循環正在監視AVPlayer的狀態,幾秒鍾后,音頻開始播放手機沒有問題。

出於測試目的,我在播放歌曲的頁面上設置了一個MPVolumeView:

MPVolumeView *volumeView = [[[MPVolumeView alloc] initWithFrame:CGRectMake(0, 0, 310, 20)] autorelease];
volumeView.center = CGPointMake(160,62);
[volumeView sizeToFit];
[self.view addSubview:volumeView];

這樣做的原因是音量滑塊還會顯示一個指示燈,如果藍牙連接為音頻輸出源,並允許我更改手機和藍牙設備之間的音頻路徑。 到現在為止還挺好。

我通過藍牙將手機連接到我的Jawbox Jambone,在一首歌上啟動AVPlayer,然后歌曲按照預期從Jawbox中傳出。 音量控制有一個小的“帶箭頭的矩形”表示我可以切換音頻輸出,實際上,在播放歌曲時,我可以在手機和Jawbox之間切換。 幸福。

當我嘗試將其連接到汽車時會出現問題。 我有兩個經驗:

  1. 該車已與手機配對,可撥打/接聽電話。 當我上車時,手機甚至表示它已配對。 但是,當我使用相同的代碼播放相同的音頻文件時,它們只能從手機中取出。 音量滑塊根本不顯示“藍牙路線”指示器(就像它不能將汽車識別為音頻輸出路線一樣)。
  2. 在另一輛車中,音頻從另一個應用程序(一些無線電流媒體應用程序)流式傳輸。 另一個應用程序停止了,這個開始了。 音頻開始播放上面測試的同一首歌,但在一兩秒后停止播放。 同樣,此時藍牙連接的音量滑塊上沒有指示器。

有人可以向我解釋為什么音頻可以流式傳輸到一個藍牙設備而不是另一個嗎?

我的應用程序配置文件中是否遺漏了某些內容(權利?),以便通過藍牙將音頻流式傳輸到汽車中?

GIT有這個項目。 Play iOS項目是Play的流媒體客戶端,可在iPhone / iPad上運行。 它支持背景音頻以及背景時的媒體鍵。 它支持:

  • 溪流shoutcast流
  • 顯示當前播放的曲目
  • 背景音頻
  • 鎖屏專輯封面和播放控件
  • AirPlay(以及藍牙)流媒體。 支持發送元數據和專輯封面

您可以在此處下載該項目。 我沒有在CAR藍牙音頻播放器上測試過這個。 希望它對你有任何幫助。

在第一個例子中,您的汽車可能只是一個遠程玩家。 你需要注冊這樣的遠程事件(考慮使用AVAudioPlayer而不是AVPlayer)

設置AudioSession以識別藍牙音頻路由:

- (BOOL)prepareAudioSession {

    // deactivate existing session
NSError *setCategoryError = nil;
NSError *activationError = nil;

BOOL success = [[AVAudioSession sharedInstance] setActive:NO error: nil];
if (!success) {
    NSLog(@"deactivationError");
}

    // set audio session category AVAudioSessionCategoryPlayAndRecord options AVAudioSessionCategoryOptionAllowBluetooth
success = [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:&setCategoryError];
if (!success)
{
    NSLog(@"setCategoryError %@",setCategoryError);
}

    // activate audio session
success = [[AVAudioSession sharedInstance] setActive:YES error: &activationError];
if (!success) {
    NSLog(@"activationError");
}

return success;

}

你可以查看路線:

 AVAudioSessionRouteDescription *mAVASRD = audioSession.currentRoute;
NSLog(@"the array is %@",mAVASRD.outputs);

for (int ctr = 0; ctr < [mAVASRD.outputs count]; ctr++)
{
    AVAudioSessionPortDescription *myPortDescription = [mAVASRD.outputs objectAtIndex:ctr];
    NSLog(@"the type is %@",myPortDescription.portType);
    NSLog(@"the name is %@",myPortDescription.portName);
    NSLog(@"the UID is %@",myPortDescription.UID);
    NSLog(@"the data sources are %@",myPortDescription.dataSources);
}

然后初始化您的AVAudioPlayer並打開RemoteControlEvents(您可以使用汽車中的控制台發送播放/暫停/等)

[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];

然后在此堆棧溢出問題中實現類似AVAudioPlayer的委托方法,以捕獲收到的事件並在您的代碼中做出相應的反應:

鎖定屏幕上的AVAudioPlayer

在方案2中,當您將一個應用程序移動到后台(無線電流媒體應用程序)並啟動您的應用程序時,該問題的可能罪魁禍首是相同的原因 - 您的應用程序必須識別音頻的藍牙路由。

順便打電話和Siri,iOS使用不同的藍牙通道,默認為遠程控制(這是我為你的車描述的那個)。

當您設置此路線和遙控事件時,您還會獲得獎勵副產品 - 您的應用程序將可以從鎖定屏幕進行控制。 查看Apple的此技術說明,將您的應用配置為在后台播放,如果屏幕鎖定時您需要執行此操作:技術質量保證文檔QA1668

最后,為了通過您的藍牙路線增加集成,請查看MPNowPlayingInfoCenter - 將標題藝術家的作品和其他好東西放在鎖定屏幕上以及顯示該信息的汽車中的大多數藍牙屏幕上。

我很確定MPVolumeView只能解決符合較新的低功耗藍牙規格的藍牙設備......(藍牙低功耗或BLE)......

我知道手機應用程序不使用MPVolumeView,可能這個其他音頻播放器也沒有..你可能需要調查CoreBluetooth並實現自己的:(祝你好運。在github上可能有一個解決方案

設計為揚聲器的藍牙揚聲器不會有問題。

然而,汽車通常是“手機”藍牙揚聲器,並且只接受“電話”類型的通信。

我的猜測是你必須通過設置“手機音頻”連接並將傳入的音頻傳輸到空白,並將傳出的音樂流作為電話信號來欺騙它。

請注意,信號質量可能會降低,並且可能無法解決這個問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM