Android - 检测应用启动时路由音频的位置

时间:2014-04-29 13:08:51

标签: android audio bluetooth android-audiomanager headset

我说的是STREAM_VOICE_CALL

方案如下: 1.将有线耳机连接到手机 2.将蓝牙耳机连接到手机 3.启动向STREAM_VOICE_CALL播放音频的应用程序

操作系统自动将此流的音频重定向到最后连接的设备。 因此,如果蓝牙耳机连接有线耳机后,音频将播放到蓝牙耳机,反之亦然。

所以问题是:在我的应用运行之前,我怎么知道最近连接的设备。

我想提一下,在我的应用程序运行时,我对音频设备的操作没有任何问题 - 我知道要获取所有操作系统事件并确切地知道音频被重定向到的位置。 唯一的问题是我提到的 - 如何确定状态是什么。

有一种弃用的方法 - Audiomanager.getRouting(stream) 这正是我的需要,但我没有找到任何替代方案。

提前谢谢。

2 个答案:

答案 0 :(得分:2)

来自Android开发者网站的

This page建议采用的方法是依次通过AudioManager对每个进行测试。

if (isBluetoothA2dpOn()) {
    // Adjust output for Bluetooth.
} else if (isSpeakerphoneOn()) {
    // Adjust output for Speakerphone.
} else if (isWiredHeadsetOn()) {
    // Adjust output for headsets
} else { 
    // If audio plays and no one can hear it, is it still playing?
}

或者,您可以编写BroasdcastRecievers来监听蓝牙和耳机连接并断开事件并执行一些操作,包括保存输出流目标。如果你走这条路,请注意设备刚启动的情况,并且可能没有触发广播被接收。

答案 1 :(得分:1)

对你来说可能有点晚了,但这是最适合我的API 11+方法:

私有静态BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

private static BluetoothProfile mBtProfile;

public BluetoothInformationClass() {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        mBluetoothAdapter.getProfileProxy(context, getServiceListneer(), BluetoothProfile.HEADSET);
    }
}
/**
 * Tries to get the name of the audio route device we're being played back through.
 * There are some important behaviors to note:
 * 1)  Headphones are always the audio route when plugged in.
 * 2)  BT will be the audio route whenever ever possible except where 1 is relevant.
 *      BT can be on, but not the audio routd.  In that case we allow BT to try and fail
 *      we check its result, if it was a failure we do the final stab at things.
 *
 * @return
 */
public static String getAudioRouteDeviceName() {
    AudioManager audioManager = (AudioManager)
    context.getSystemService(Context.AUDIO_SERVICE);
    BluetoothAdapter bluetooth = BluetoothAdapter.getDefaultAdapter();
    String audioRoute = "";

    if (audioManager.isWiredHeadsetOn()) {
        audioRoute = "Wired Headset";
    } else if (audioManager.isBluetoothA2dpOn()) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
            audioRoute = getApiElevenPlusName(bluetooth);
        }
    }
    if (audioRoute.equals("")) {
        if (audioManager.isSpeakerphoneOn()) {
            audioRoute = "Phone Speaker";
        } else {
            audioRoute = "Phone";
        }
    }
    return audioRoute;
}

/**
 * 11+ api's have this fancy mechanism for figuring out connected devices.  Pre 11 its a lot less stable and for now we're going to ignore it.
 * @return
 */
@TargetApi(11)
private BluetoothProfile.ServiceListener getServiceListneer() {
    return new BluetoothProfile.ServiceListener() {
        public void onServiceConnected(int profile, BluetoothProfile proxy) {

            mBtProfile = proxy;
        }

        public void onServiceDisconnected(int profile) {
            if (profile == BluetoothProfile.HEADSET) {
                mBluetoothHeadset = null;
            }
            mBtProfile = null;

        }
    };
}

/**
 * Tries to locate the currently connected device.
 * @param bluetooth
 * @return
 */
@TargetApi(11)
private static String getApiElevenPlusName(BluetoothAdapter bluetooth) {
    String ret = "";
    BluetoothDevice[] devices = bluetooth.getBondedDevices().toArray(new BluetoothDevice[bluetooth.getBondedDevices().size()]);
    if (mBtProfile != null) {
        for (BluetoothDevice device : devices) {
            if (mBtProfile.getConnectionState(device) == BluetoothProfile.STATE_CONNECTED) {
                ret += device.getName();
            }
        }
    }
    return ret;
}

这里有一些假设:

1)根据我的测试,有线耳机通常最好作为音频路线。即使与BT耳机/汽车音响等配对...一旦你插入有线耳机就成了音频路径。

2)如果您无法获得BT设备的名称,则此方法假定您未使用BT设备。这个假设并非严格正确,但是这种方法适用于所有11个以上的设备,而且因为这个市场的90%以上就足够了。