Text-To-Speech を使用してアプリケーションを設計していますが、動作します。ここで、Bluetooth ヘッドセット (AD2P ではない) を使用して音声を受信したいと考えています。startBluetoothScoOn に関する Android ドキュメントを読むと、次のようになります。
電話アプリケーションは、電話で 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();
}
}
}
スコ受信機:
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);
}
}