在Android中检测当前音频路由的有效方法?

时间:2013-03-08 02:49:10

标签: android audio android-audiomanager

我的应用程序需要能够知道用户选择的基本音频路由。在iOS上,这是微不足道的,因为您只需注册一个回调,并且您确切知道音频的去向。

在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中这是一项如此艰巨的任务?

1 个答案:

答案 0 :(得分: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();
}