Я изучаю интересный проект, включающий потоковое воспроизведение потокового аудио по Bluetooth для смартфонов, начиная с android, так как у меня больше всего опыта. Я работал с Bluetooth на андроиде один или два раза, и в своем опыте узнал, что API предварительной сотовой связи не позволяет приложениям подключаться к аудиозахватам A2DP или HFP. Я уже пробовал это на Ginger Bread на HTC EVO, используя нужный UUID безрезультатно.
Согласно официальной документации, начиная с API LEVEL 11, теперь это возможно, но я уверен, что единственными устройствами, которые будут предлагать этот уровень API, станут устройства Ice Cream Sandwich позже, так как поддержка началась только в Honey Comb. Я полный любитель, поэтому маловероятно, что в ближайшее время я получу свои рукавицы на устройстве Ice Cream Sandwich. Адаптация любого кода для последующих версий не будет проблемой, так как я просто хочу доказать концепцию прямо сейчас.
В идеале я бы хотел использовать потоки ввода/вывода парного устройства A2DP для непосредственного чтения и записи данных ИКМ. Однако, если я хочу сделать это сейчас, я, скорее всего, буду использовать обходной путь.
Моя идея - использовать классы android AudioRecord и AudioTrack, которые, по моему мнению, читают аудиовход с микрофона и выталкивают аудиовыход к динамику. Теперь в обоих случаях, когда устройство A2DP не подключено, эти структуры будут использовать микрофон и динамик устройства соответственно. Однако, когда подключено устройство A2DP или HFP, я не знаю, будет ли система теперь устанавливать эти структуры для ввода и вывода на микрофон и динамик гарнитуры. Если это так, то я мог бы эффективно использовать это в своем коде и адаптировать его позже, чтобы воспользоваться прямой поддержкой в Ice Cream Sandwich.
Кто-нибудь с относительно сильным опытом в этой области считает, что этот подход будет работать? Я бы предпочел узнать, был ли кто-то успешным, прежде чем сесть и написать код, который потенциально может быть пустой тратой времени.
На самом деле Android не имеет официального API для подключения устройств a2dp.
Но вы можете использовать отражение для доступа к скрытым классам. Я использовал этот способ в своем проекте, и он работает от android 2.3 до android 4.1.
Во-первых, вам нужно получить файл IBluetoothA2dp.aidl и поместить его в папку проекта src/com.android
Далее, используйте метод ниже, чтобы получить интерфейс IBluetoothA2dp:
private static IBluetoothA2dp getIBluetoothA2dp() {
IBluetoothA2dp ibta = null;
try {
final Class serviceManager = Class.forName("android.os.ServiceManager");
final Method getService = serviceManager.getDeclaredMethod("getService", String.class);
final IBinder iBinder = (IBinder) getService.invoke(null, "bluetooth_a2dp");
final Class iBluetoothA2dp = Class.forName("android.bluetooth.IBluetoothA2dp");
final Class[] declaredClasses = iBluetoothA2dp.getDeclaredClasses();
final Class c = declaredClasses[0];
final Method asInterface = c.getDeclaredMethod("asInterface", IBinder.class);
asInterface.setAccessible(true);
ibta = (IBluetoothA2dp) asInterface.invoke(null, iBinder);
} catch (final Exception e) {
Log.e("Error " + e.getMessage());
}
return ibta;
}
Затем, если вы SDK <11, просто вызовите a2dp.connectSink(btDevice) или a2dp.connect(btDevice), если ваш SDK между 11 и 16.
Он не работает на Android 4.2 из-за полностью измененного стека Bluetooth.