Текст в речь через Bluetooth
Я разрабатываю приложение с помощью Text-To-Speech, и оно работает. Теперь я хочу использовать Bluetooth-гарнитуру (не AD2P) для получения звука. Читая Android документацию о запуске Bluetooth, я вижу:
Обратите внимание, что приложение телефона всегда имеет приоритет при использовании соединения SCO для телефонии. Если этот метод вызывается во время разговора по телефону, он будет проигнорирован. Точно так же, если вызов принят или отправлен, когда приложение использует соединение SCO, соединение будет потеряно для приложения и НЕ вернется автоматически после завершения вызова.
Теперь мои вопросы:
- Нужно ли прослушивать состояние телефона, чтобы он перезвонил startBluetoothScoOn после завершения вызова? Если да, то как? Я не нашел ни одного примера;
- Нужно ли прослушивать подключенную / отключенную гарнитуру? Если да, то как?
Я полагаю, что когда вызовы заканчиваются или моя гарнитура выключена, система выдает SCO_AUDIO_STATE_DISCONNECTED, верно?
Изменить: я публикую код, который я использую:
public class BluetoothHeadSetManager implements
BluetoothProfile.ServiceListener {
BluetoothManager manager;
BluetoothHeadset bluetoothHeadset;
Context context;
HeadSetBroadcastReceiver recv;
public BluetoothHeadSetManager(Context cont, BluetoothManager manager) {
this.manager = manager;
this.context = cont;
recv = null;
}
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
// mBluetoothHeadset is just a headset profile,
// it does not represent a headset device.
bluetoothHeadset = (BluetoothHeadset) proxy;
List<BluetoothDevice> devices = bluetoothHeadset.getConnectedDevices();
if (devices.size() > 0)
manager.onHeadSetConnected();
// During the active life time of the app, a user may turn on and off
// the headset.
// So register for broadcast of connection states.
if (recv == null) {
recv = new HeadSetBroadcastReceiver();
context.registerReceiver(recv, new IntentFilter(
BluetoothDevice.ACTION_ACL_CONNECTED));
context.registerReceiver(recv, new IntentFilter(
BluetoothDevice.ACTION_ACL_DISCONNECTED));
}
}
public void close() {
if (recv != null)
context.unregisterReceiver(recv);
if (bluetoothHeadset != null)
BluetoothAdapter.getDefaultAdapter().closeProfileProxy(
BluetoothProfile.HEADSET, bluetoothHeadset);
}
@Override
public void onServiceDisconnected(int arg0) {
Logger.getInstance().writeLog("onServiceDisconnected called");
if (recv != null)
context.unregisterReceiver(recv);
manager.onHeadSetDisconnected();
}
private class HeadSetBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice mConnectedHeadset;
if (action.equals(BluetoothDevice.ACTION_ACL_CONNECTED)) {
mConnectedHeadset = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
BluetoothClass bluetoothClass = mConnectedHeadset
.getBluetoothClass();
if (bluetoothClass != null) {
// Check if device is a headset. Besides the 2 below, are
// there other
// device classes also qualified as headset?
int deviceClass = bluetoothClass.getDeviceClass();
if (deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE
|| deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET) {
// override this if you want to do other thing when the
// device is connected.
manager.onHeadSetConnected();
}
}
} else if (action.equals(BluetoothDevice.ACTION_ACL_DISCONNECTED)) {
manager.onHeadSetDisconnected();
}
}
}
Sco приемник:
public class BluetoothScoReceiver extends BroadcastReceiver {
BluetoothManager manager;
public BluetoothScoReceiver(BluetoothManager manager) {
this.manager = manager;
}
@Override
public void onReceive(Context arg0, Intent intent) {
Bundle extras = intent.getExtras();
if (extras == null)
return;
int state = extras.getInt(AudioManager.EXTRA_SCO_AUDIO_STATE);
if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED)
manager.onScoConnected();
else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED)
manager.onScoDisconnected();
}
Главный:
@Override
public void onScoConnected() {
this.headsetReady = true;
requestState = CONNECTED;
}
@Override
public void onScoDisconnected() {
this.headsetReady = false;
if (requestState == TRY_CONNECTION && headsetConnected)
this.onHeadSetConnected(); //try again
}
@Override
public void onHeadSetConnected() {
headsetConnected = true;
if (requestState == TRY_CONNECTION) {
requestState = TRY_CONNECTION;
audioMng.setMode(AudioManager.MODE_NORMAL);
audioMng.stopBluetoothSco();
audioMng.setMode(AudioManager.MODE_IN_CALL);
audioMng.startBluetoothSco();
} else {
requestState = TRY_CONNECTION;
audioMng.setMode(AudioManager.MODE_IN_CALL);
audioMng.startBluetoothSco();
}
}
@Override
public void onHeadSetDisconnected() {
audioMng.setMode(AudioManager.MODE_NORMAL);
if (requestState != NOT_CONNECTED_IDLE) {
audioMng.stopBluetoothSco();
audioMng.setBluetoothScoOn(false);
requestState = NOT_CONNECTED_IDLE;
}
headsetConnected = false;
}
@SuppressLint("InlinedApi")
@SuppressWarnings("deprecation")
@Override
public void startBluetooth() {
Intent currentScoState;
if (audioMng.isBluetoothScoAvailableOffCall()) {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
if (adapter == null)
return;
blueInit = adapter.getProfileProxy(this, headsetMng,
BluetoothProfile.HEADSET);
if (blueInit) {
scoListner = new BluetoothScoReceiver(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
currentScoState = this
.registerReceiver(
scoListner,
new IntentFilter(
AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED));
else
currentScoState = this
.registerReceiver(
scoListner,
new IntentFilter(
AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));
Bundle extras = currentScoState.getExtras();
if (extras == null)
return;
if (extras
.getInt(AudioManager.EXTRA_SCO_AUDIO_STATE) == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
this.headsetReady = true;
requestState = CONNECTED;
} else {
this.headsetReady = false;
requestState = NOT_CONNECTED_IDLE;
}
}
}
}
@Override
public void stopBluetooth() {
this.onHeadSetDisconnected();
if (blueInit) {
headsetMng.close();
this.unregisterReceiver(scoListner);
}
}
1 ответ
- Вам не обязательно прослушивать состояние телефона, когда вызов закончится (CALL_STATE_IDLE), вы получите SCO_AUDIO_STATE_DISCONNECTED.
- Если вы не прослушиваете подключенную гарнитуру, как узнать, когда подключать звук? Для реализации Bluetooth-гарнитуры вы можете посмотреть Использование Android RecognizerIntent с Bluetooth-гарнитурой.