yan*_*ano 5 audio android 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
Run Code Online (Sandbox Code Playgroud)
然而,这种方法容易出错。例如,如果您连接到蓝牙A2DP,那么您插入耳机,很容易分辨出路线是“耳机”,但是当拔下耳机时,您必须猜测什么路线仍然处于活动状态,通过记录来自所有蓝牙事件的连接状态。
当您的应用程序启动时,确定初始音频路径也存在困难。HEADSET_PLUG 很粘,所以很好,但没有其他东西......
有关如何解决此问题并准确检测此问题的任何建议?为什么在 Android 中这是一项如此艰巨的任务?
这是一种非常hackish的方式来轮询当前路由,它也支持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();
}
Run Code Online (Sandbox Code Playgroud)