Я разрабатываю приложение с Text-To-Speech, и оно работает. Теперь я хочу использовать Bluetooth-гарнитуру (не AD2P) для приема звука. Чтение документации на Android о startBluetoothScoOn Я вижу:Text-To-Speech over bluetooth
Обратите внимание, что приложение телефона всегда имеет приоритет при использовании соединения SCO для телефонии. Если этот метод вызывается во время вызова телефона, он будет проигнорирован. Аналогичным образом, если вызов получен или отправлен, когда приложение использует соединение SCO, соединение будет потеряно для приложения и НЕ будет возвращено автоматически при завершении вызова.
Теперь мои вопросы:
- мне нужно слушать состояния телефона, чтобы повторно позвонить startBluetoothScoOn, когда вызов заканчивается ли? Если да, то как? Я не нашел никакого примера;
- Нужно ли мне слушать подключенную/отсоединенную гарнитуру? Если да, то как?
Я полагаю, что когда завершение вызова или моя гарнитура отключены, система передает SCO_AUDIO_STATE_DISCONNECTED, правильно?
Edit: я выкладываю код я использую:
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);
}
}
В этом примере startBluetoothScoOn не вызывается вообще, так что я думаю, что я могу использовать в качестве вдохновения только для точки 2. Однако я действительно не understande разницы между onServiceConnected/onServiceDisconnected и приемник намерения ACTION_CONNECTION_STATE_CHANGED - это одно и то же. В самом деле, они оба называют onHeadsetConnected(). Или onServiceConnected/onServiceDisconnected не относятся к соединению гарнитуры, а к другому аспекту. – user1633717
В каком примере вы говорите? если вы ссылаетесь на ссылку, которую я предоставил, тогда startBluetoothSco() вызывается в mBroadcastReceiver и нет onServiceConnected/onServiceDisconnected в любом месте в кодах, поэтому я не знаю, к чему вы относитесь. –
Я использую API> = 11, я говорю о классе BluetoothHeadsetUtils – user1633717