2013-03-08 67 views
2

我的應用程序需要能夠知道用戶選擇的基本音頻路線。在iOS上,這是微不足道的,因爲您只需註冊一個回調,並且您確切知道音頻的播放位置。在Android中檢測當前音頻路由的有效方法?

在Android上,我很高興看到MediaRouter類,但令我沮喪的是,事實證明沒有可預測的方式來確定路由類型。例如,切換到藍牙A2DP設備時,唯一的識別項目是RouteInfo.getName()方法,但這會返回A2DP設備的友好名稱,因此無法與之比較。

我還使用下列廣播嘗試:

AudioManager.ACTION_AUDIO_BECOMING_NOISY 
Intent.ACTION_HEADSET_PLUG 
BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED 
BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED 
BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED 

但是這種方法很容易出錯。例如,如果您連接到藍牙A2DP,那麼您插入耳機,很容易將路由告知「耳機」,但是當拔下耳機時,您必須猜測哪些路由仍處於活動狀態,方法是錄製來自所有藍牙事件的連接狀態。

當您的應用程序啓動時,確定初始音頻路徑也存在困難。 HEADSET_PLUG是粘性的,所以這很好,但沒有別的...

任何關於如何處理這個問題的建議,並準確地檢測到這一點?爲什麼在Android中這是如此艱鉅的任務?

回答

2

以下是對當前路由進行輪詢的非常黑客的方式,它也支持檢測A2DP。使用風險自負,因爲這些類別的內容可能在未來發生很大變化。但它應該在Jellybean和Jellybean MR1上工作。

String ouputDeviceName; 
try { 
    MediaRouter mr = (MediaRouter)getSystemService(Context.MEDIA_ROUTER_SERVICE); 
    Class mediaRouterClass = Class.forName("android.media.MediaRouter"); 
    Method getSystemAudioRouteMethod = mediaRouterClass.getMethod("getSystemAudioRoute"); 
    RouteInfo ri = (RouteInfo)getSystemAudioRouteMethod.invoke(mr); 

    Class mediaRouterStaticClass = Class.forName("android.media.MediaRouter$Static"); 
    Field staticField = mediaRouterClass.getDeclaredField("sStatic"); 
    Field a2dpField = mediaRouterStaticClass.getDeclaredField("mBluetoothA2dpRoute"); 
    AccessibleObject.setAccessible(new AccessibleObject[]{staticField}, true); 
    AccessibleObject.setAccessible(new AccessibleObject[]{a2dpField}, true); 
    Object a2dpRoute = a2dpField.get(staticField.get(null)); 
    if (a2dpRoute != mr.getSelectedRoute(MediaRouter.ROUTE_TYPE_LIVE_AUDIO)) { 
     // Phone, Headphone, HDMI, etc.. 
     ouputDeviceName = "name: " + ri.getName().toString(); 
    } else { 
     // Audio is routed to A2DP 
     ouputDeviceName = "name: A2DP"; 
    } 
} catch (Exception e) { 
    e.printStackTrace(); 
} 
+0

藍牙路由是使用SCO還是HFP,還是由第一種情況處理? – yano 2013-03-08 19:35:51

+0

當音頻被路由到BT SCO時,我沒有檢查結果,而且我現在沒有可用的BT附件。不知道您是否從MediaRouter類獲得任何有關路由到BT SCO的信息 - 畢竟,您通常不會將媒體音頻路由到BT SCO(除非在語音呼叫期間進行媒體播放)。 – Michael 2013-03-08 20:17:29

+0

只需查看MediaRouter源代碼http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.1.1_r1/android/media/MediaRouter.java#MediaRouter.Static .updateRoutes%28android.media.AudioRoutesInfo%29他們沒有考慮除A2DP以外的任何內容,他們只是使用AudioManager.isBluetoothA2dpOn() - 我想如果我找到一個我不認識的路由名稱,我可以檢查該方法。 – yano 2013-03-08 20:24:22