Android: воспроизведение звука через гарнитуру Sco Bluetooth
Последние несколько дней я пытался воспроизвести любой звук через мою sco bluetooth-гарнитуру с моего телефона Android. Моя конечная цель в этом проекте - в конечном итоге сделать устройство для открывания гаражных ворот, но сначала я должен уметь воспроизводить звук через гарнитуру.
Вот основа текущего кода, который я использую:
==Manifest==
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
==Code==
audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
audioManager.setMode(AudioManager.MODE_IN_CALL);
audioManager.startBluetoothSco();
audioManager.setBluetoothScoOn(true);
short[] soundData = new short [8000*20];
for (int iii = 0; iii < 20*8000; iii++) {
soundData[iii] = 32767;
iii++;
soundData[iii] = -32768;
}
audioTrack = new AudioTrack(AudioManager.STREAM_VOICE_CALL,
8000, AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT, soundData.length
* Short.SIZE, AudioTrack.MODE_STATIC);
audioTrack.write(soundData, 0, soundData.length);
audioTrack.play();
Прежде чем запустить это, я подключаю свою Bluetooth-гарнитуру к телефону и подключаю ее. Я подтвердил, что это работает, позвонив в мою голосовую почту. Однако когда я запускаю свой код, нигде нет звука.
Вот эффекты различных строк кода:
Когда я просто запускаю свое приложение:
audioManager.setMode(AudioManager.MODE_IN_CALL);
Эта строка заставляет перестать работать весь мой звук, независимо от того, что я делаю, поэтому он обычно закомментирован.
audioManager.startBluetoothSco();
audioManager.setBluetoothScoOn(true);
Эти две строки заставляют звук прекращать выходить из фронтального динамика и заставляют мою гарнитуру щелкать и шипеть, как будто она включена, но нет выхода.
AudioManager.STREAM_VOICE_CALL
Это часть моего обращения к конструктору AudioTrack, но это имеет большое значение. Так как для этого параметра установлено значение STREAM_VOICE_CALL, звук выходит из переднего динамика, если я установлю его на STREAM_MUSIC, вместо этого звук будет выходить из заднего динамика.
Когда я открываю свое приложение во время звонка:
audioManager.setMode(AudioManager.MODE_IN_CALL);
Во время вызова эта строка не имеет никакого эффекта, потому что MODE_IN_CALL уже был установлен. Но отличается то, что мой звук смешивается с телефонным звонком, тогда как обычно он не воспроизводится вообще.
audioManager.startBluetoothSco();
audioManager.setBluetoothScoOn(true);
Они, со своими коллегами из половины, контролируют, откуда исходит звук. Если я отключаю их, мой звук и телефонный звонок поступают из переднего громкоговорителя, а при их включении телефонный звонок поступает из моей гарнитуры, и мой звук теряется.
Что касается того, почему мой код не работает, я, честно говоря, понятия не имею. Я считаю, что выполнил контрольный список для использования startBluetoothSco ().
Even if a SCO connection is established, the following restrictions
apply on audio output streams so that they can be routed to SCO headset:
- the stream type must be STREAM_VOICE_CALL - the format must be mono -
the sampling must be 16kHz or 8kHz
Итак, кто-нибудь имеет представление о том, что я делаю неправильно? Был один раз, когда мне удалось воспроизвести звук через гарнитуру, но это был лишь короткий сигнал, когда я забыл остановить () мой AudioTrack, поэтому я должен предположить, что это был сбой.
4 ответа
Мне действительно удалось это исправить. Проблема заключалась в том, что моя высота, которую я воспроизводил через гарнитуру, была слишком высокой частоты. Я исправил это, просто удвоив код, который создает аудиофайл, чтобы он стал HIGH HIGH LOW LOW вместо HIGH LOW HIGH LOW.
Я нашел решение на этой странице. Вы должны позвонить audioManager.setMode(AudioManager.MODE_IN_CALL);
только после того, как сокет подключен, т.е. вы получили AudioManager.SCO_AUDIO_STATE_CONNECTED
, Я мог слышать TTS на моем Android Spica работает 2.2.2.
Изменить: Вот моя (старая) реализация:
public class BluetoothNotificationReceiver
extends BroadcastReceiver
{
/**
*
*/
public BluetoothNotificationReceiver(Handler h)
{
super();
bnrHandler = h;
}
/* (non-Javadoc)
* @see android.content.BroadcastReceiver#onReceive(android.content.Context, android.content.Intent)
*/
@Override
public void onReceive(Context arg0, Intent arg1)
{
String action = arg1.getAction();
if (action.equalsIgnoreCase(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED))
{
int l_state = arg1.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
Log.d("bnr", "Audio SCO: " + AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED);
switch(l_state)
{
case AudioManager.SCO_AUDIO_STATE_CONNECTED:
{
Log.i("bnr", "SCO_AUDIO_STATE_CONNECTED");
}
break;
case AudioManager.SCO_AUDIO_STATE_DISCONNECTED:
{
Log.e("bnr", "SCO_AUDIO_STATE_DISCONNECTED");
}
break;
default: Log.e("bnr", "unknown state received:"+l_state);
}
}
else
Log.e("bnr", "onReceive:action="+action);
}
}
Я не знаю, работает ли он с новыми API.
Попробуйте установить для audiomanager значение AudioManager.MODE_NORMAL. Тос работал на меня.
Добавить в манифест:
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.BLUETOOTH" />