Маршрутизация аудио в Bluetooth-гарнитуру (не A2DP) на Android
У меня есть гарнитура для наушников с одним ухом без A2DP (Plantronics 510) и вы хотите использовать ее с моим Android HTC Magic для прослушивания низкокачественного звука, такого как подкасты/аудиокниги.
После долгих поисковых запросов я обнаружил, что только телефонные звонки могут быть направлены на гарнитуры, отличные от A2DP BT. (Я хотел бы знать, нашли ли вы готовое решение для маршрутизации всех видов аудио в не-A2DP BT-гарнитуры)
Итак, я понял, как-то программно я могу направлять аудио в поток, который передает звук телефонного звонка. Таким образом, я буду обманывать телефон, чтобы нести свой mp3-звук в мою BT-гарнитуру. Я написал следующий простой код.
import android.content.*;
import android.app.Activity;
import android.os.Bundle;
import android.media.*;
import java.io.*;
import android.util.Log;
public class BTAudioActivity extends Activity
{
private static final String TAG = "BTAudioActivity";
private MediaPlayer mPlayer = null;
private AudioManager amanager = null;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
amanager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
amanager.setBluetoothScoOn(true);
amanager.setMode(AudioManager.MODE_IN_CALL);
mPlayer = new MediaPlayer();
try {
mPlayer.setDataSource(new FileInputStream(
"/sdcard/sample.mp3").getFD());
mPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
mPlayer.prepare();
mPlayer.start();
} catch(Exception e) {
Log.e(TAG, e.toString());
}
}
@Override
public void onDestroy()
{
mPlayer.stop();
amanager.setMode(AudioManager.MODE_NORMAL);
amanager.setBluetoothScoOn(false);
super.onDestroy();
}
}
Как вы можете видеть, я пробовал сочетания различных методов, которые, как я думал, обманут телефон, чтобы поверить, что мой звук является телефонным звонком:
- Использование MediaPlayer setAudioStreamType (STREAM_VOICE_CALL)
- с помощью AudioManager setBluetoothScoOn (true)
- с помощью AudioManager setMode (MODE_IN_CALL)
Но ничего из этого не было. Если я удаляю вызовы AudioManager в приведенном выше коде, звук воспроизводится с динамика, и если я их замену, как показано выше, звук перестает поступать от динамиков, но он не приходит через гарнитуру BT. Таким образом, это может быть частичным успехом.
Я проверил, что гарнитура BT работает нормально с телефонными звонками.
Должна быть причина, по которой Android не поддерживает это. Но я не могу отпустить ощущение, что невозможно программно перенаправить аудио. Любые идеи?
P.S. над кодом требуется следующее разрешение
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
Ответы
Ответ 1
Этот поток может быть длинным, но для тех, кто может попробовать одно и то же, некоторые примечания из документов AudioManager могут быть полезными. Похоже, что отсутствующим элементом является команда startBluetoothSco(), но есть ограничения на использование этого канала. С сайта Android Dev здесь:
public void startBluetoothSco() Начиная с: API уровня 8 Запустите bluetooth SCO аудио соединение.
Требуется разрешение: MODIFY_AUDIO_SETTINGS.
Этот метод может быть использован приложений, желающих отправить и получил звук в/из Bluetooth SCO когда телефон не находится в вызов.
Как установление соединения SCO может занять несколько секунд, приложения не должны полагаться на соединение с быть доступным, когда метод возвращается но вместо этого зарегистрируйтесь, чтобы получить намерение ACTION_SCO_AUDIO_STATE_CHANGED и ждать, пока состояние будет SCO_AUDIO_STATE_CONNECTED.
Поскольку соединение не гарантируется преуспеть, приложения должны ждать это намерение с тайм-аутом.
По завершении соединения SCO или если время истечения срока приложение должно вызывать stopBluetoothSco(), чтобы очистить запросить и выключить Bluetooth подключение.
Даже если соединение SCO установлены следующие применяются ограничения на аудиовыход потоки, чтобы их можно было SCO-гарнитура: - тип потока должен быть STREAM_VOICE_CALL - формат должен быть моно - выборка должна быть 16 кГц или 8 кГц
Следующие ограничения применяются к входные потоки: - формат должен быть моно - выборка должна быть 8 кГц
Обратите внимание, что приложение телефона всегда имеет приоритет при использовании SCO для телефонии. Если это метод вызывается, когда телефон находится в вызов будет проигнорирован. Аналогично, если вызов принимается или отправляется, когда приложение использует SCO соединение, соединение будет потерянный для приложения и НЕ автоматически возвращается при вызове заканчивается.
См. также stopBluetoothSco() ACTION_SCO_AUDIO_STATE_CHANGED
Заметьте, что я не тестировал это, я просто передаю руководство, которое я нашел в исследовании аналогичного проекта. Я думаю, что Джайеш был близок к решению, и ограничения, наложенные выше, возможно, были тем, что удерживало его от работы.
Ответ 2
Чтобы включить:
localAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
localAudioManager.setMode(0);
localAudioManager.setBluetoothScoOn(true);
localAudioManager.startBluetoothSco();
localAudioManager.setMode(AudioManager.MODE_IN_CALL);
Чтобы отключить:
localAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
localAudioManager.setBluetoothScoOn(false);
localAudioManager.stopBluetoothSco();
localAudioManager.setMode(AudioManager.MODE_NORMAL);
Я взял его здесь
Ответ 3
Отличная работа, он отлично работает для меня, пожалуйста, сделайте бит-модификацию в своем коде, он будет отлично работать.
mPlayer.setAudioStreamType(AudioManager.STREAM_VOICE_CALL);
to
mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
Ответ 4
Для медиаплеера должен быть маршрут маршрута ALSA, чтобы он мог открыть другой аудиоканал, а затем направлять аудио в гарнитуру BT.
Ответ 5
Невозможно увидеть ясное принятое рабочее приложение, поэтому добавьте новый ответ. Это приложение направляет музыку и аудио в гарнитуры Non A2dp. Попробуйте мое приложение и найдите исходный код также в github для ссылочного кода. https://github.com/sauravpradhan/AnySound2BT