公司一款对讲软件需要适配 Phonak这款蓝牙耳机,查找很多资料之后 整理出一个示例。这段代码的完成离不开各路大神无私分享。
public class SCOHelper {
private final static String TAG = "SCOHelper";
private static SCOHelper instance;
private Context context;
private AudioManager audioManager;
private BluetoothHeadset bluetoothHeadset;
private BluetoothDevice bluetoothDevice;
private BluetoothStateReceiver bluetoothStateReceiver;
private BluetoothAdapter adapter;
private MediaSession mediaSession;
//*****
private final static String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";
private ConnectThread connectThread;
//
private final static int MESSAGE_RECEIVER_FORM_BLUETOOTH = 0x001;//
private final static int MESSAGE_WAIT_BLUETOOTH_CONNECTED_REFUSH = 0x002;//刷新等待蓝牙连接后 系统内状态更新
private final static String ACTION_PHONAK_BLUETOOTH_PTT_PRESS = "+PTT=P";//Phonak 蓝牙耳机PTT按键按下
private final static String ACTION_PHONAK_BLUETOOTH_PTT_RELEASE = "+PTT=R";//Phonak 蓝牙耳机PTT按键抬起
public static SCOHelper getInstance() {
if (instance == null) {
synchronized (SCOHelper.class) {
if (instance == null) {
instance = new SCOHelper();
}
}
}
return instance;
}
public void init(Context context) {
this.context = context;
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
registerBlueToothHeadset();
registerSCO();
registerMediaButtonReceiver();
registerBluetooth();
}
public void release() {
unRegisterMediaButtonReceiver();
unRegisterSCO();
closeSCO();
unRegisterBluetooth();
}
private void registerBlueToothHeadset() {
BluetoothManager bm = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
adapter = bm.getAdapter();
adapter.getProfileProxy(context, blueHeadsetListener, BluetoothProfile.HEADSET);
}
private void registerSCO() {
IntentFilter newintent = new IntentFilter();
newintent.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED);
newintent.addAction("android.bluetooth.device.action.ACL_CONNECTED");
context.registerReceiver(mSCOHeadsetAudioState, newintent);
}
private void registerBluetooth() {
bluetoothStateReceiver = new BluetoothStateReceiver();
IntentFilter intentFilter = new IntentFilter();
// 监视蓝牙关闭和打开的状态
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
// 监视蓝牙设备与APP连接的状态
intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
context.registerReceiver(bluetoothStateReceiver, intentFilter);
}
private void unRegisterBluetooth() {
context.unregisterReceiver(bluetoothStateReceiver);
}
public void unRegisterSCO() {
context.unregisterReceiver(mSCOHeadsetAudioState);
}
public void registerMediaButtonReceiver() {
// mediaSession = new MediaSession(context,"media");
// ComponentName mediaButtonReceiverComponentName = new ComponentName(context, MediaButtonReceiver.class);
// Intent mediaButtonIntent = new Intent(Intent.ACTION_MEDIA_BUTTON);
// mediaButtonIntent.setComponent(mediaButtonReceiverComponentName);
// PendingIntent mediaButtonReceiverPendingIntent = PendingIntent.getBroadcast(context, 0, mediaButtonIntent, 0);
// mediaSession.setFlags(MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS | MediaSession.FLAG_HANDLES_MEDIA_BUTTONS);
// mediaSession.setMediaButtonReceiver(mediaButtonReceiverPendingIntent);
ComponentName mComponentName = new ComponentName(context.getPackageName(), MediaButtonReceiver.class.getName());
int result = audioManager.requestAudioFocus(new MyOnAudioFocusChangeListener(), AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
if (AudioManager.AUDIOFOCUS_REQUEST_GRANTED == result) {//到这一步,焦点已经请求成功了
//注册媒体按键 API 21 以下, 通常的做法
audioManager.registerMediaButtonEventReceiver(mComponentName);
}
}
//解注册 多媒体按钮广播
public void unRegisterMediaButtonReceiver() {
mediaSession.release();
}
//开启SCO
public void openSCO() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
audioManager.setMode(AudioManager.MODE_IN_CALL);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
audioManager.setMode(AudioManager.MODE_IN_CALL);
}
if (audioManager.isBluetoothScoOn()) {
audioManager.stopBluetoothSco();
audioManager.setBluetoothScoOn(false);
}
audioManager.setBluetoothScoOn(true);
audioManager.startBluetoothSco();
}
//关闭SCO
public void closeSCO() {
audioManager.setMode(AudioManager.MODE_NORMAL);//切换为普通模式
if (audioManager.isBluetoothScoOn()) {
audioManager.stopBluetoothSco();
audioManager.setBluetoothScoOn(false);
}
}
private BluetoothProfile.ServiceListener blueHeadsetListener = new BluetoothProfile.ServiceListener() {
@Override
public void onServiceDisconnected(int profile) {
Log.i(TAG, "onServiceDisconnected:" + profile);
if (profile == BluetoothProfile.HEADSET) {
if (bluetoothHeadset != null) {
bluetoothHeadset.stopVoiceRecognition(bluetoothDevice);
}
closeSCO();
bluetoothHeadset = null;
if (connectThread != null) {
connectThread.dissConnect();
}
}
}
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
Log.i(TAG, "onServiceConnected: profile-->" + profile + proxy.getConnectedDevices().size());
if (profile == BluetoothProfile.HEADSET) {
bluetoothHeadset = (BluetoothHeadset) proxy;
openSCO();
handler.sendEmptyMessageDelayed(MESSAGE_WAIT_BLUETOOTH_CONNECTED_REFUSH, 1000);
// if (bluetoothHeadset.getConnectedDevices().size() > 0) {
// for (BluetoothDevice bluetoothDevice : bluetoothHeadset.getConnectedDevices()) {
// Log.d(TAG, "onServiceConnected: " + bluetoothDevice.getName() + " " + bluetoothDevice.getAddress() + " " + bluetoothDevice.getBondState());
// }
// bluetoothDevice = bluetoothHeadset.getConnectedDevices().get(0);
// Log.i(TAG, bluetoothHeadset.startVoiceRecognition(bluetoothDevice) + "");
//
//
// }
}
}
};
private final BroadcastReceiver mSCOHeadsetAudioState = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
if (intent.getAction() == null) {
return;
}
// Log.d(TAG, "onReceive: " + intent.getAction() + " " + intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1));
if (intent.getAction().equals("android.bluetooth.device.action.ACL_CONNECTED")) {
registerBlueToothHeadset();
} else {
//if(DEBUG)
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, -1);
// Log.d(TAG, " mSCOHeadsetAudioState--->onReceive:" + state);
if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
Log.i(TAG, "SCO_AUDIO_STATE_CONNECTED");
unRegisterSCO();
} else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
Log.i(TAG, "SCO_AUDIO_STATE_DISCONNECTED");
}
}
}
};
class MyOnAudioFocusChangeListener implements AudioManager.OnAudioFocusChangeListener {
@Override
public void onAudioFocusChange(int focusChange) {
switch (focusChange) {
case AudioManager.AUDIOFOCUS_GAIN:
break;
case AudioManager.AUDIOFOCUS_LOSS:
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
break;
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
break;
}
}
}
//
private class BluetoothStateReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action != null) {
switch (action) {
case BluetoothAdapter.ACTION_STATE_CHANGED:
int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1);
switch (blueState) {
case BluetoothAdapter.STATE_TURNING_ON:
Log.d(TAG, "onReceive:----> 蓝牙正在打开");
break;
case BluetoothAdapter.STATE_ON:
Log.d(TAG, "onReceive:----> 蓝牙已经开启");
break;
case BluetoothAdapter.STATE_TURNING_OFF:
Log.d(TAG, "onReceive:----> 蓝牙正在关闭");
break;
case BluetoothAdapter.STATE_OFF:
Log.d(TAG, "onReceive:----> 蓝牙已经关闭");
break;
}
break;
case BluetoothDevice.ACTION_ACL_CONNECTED:
handler.sendEmptyMessageDelayed(MESSAGE_WAIT_BLUETOOTH_CONNECTED_REFUSH, 1000);
Log.d(TAG, "onReceive:----> 蓝牙设备已连接");
break;
case BluetoothDevice.ACTION_ACL_DISCONNECTED:
Log.d(TAG, "onReceive:----> 蓝牙设备已断开");
break;
}
}
}
}
/**
* 定义 SPP 连接线程
*/
private class ConnectThread implements Runnable {
private BluetoothDevice device;
private BluetoothSocket bluetoothSocket;
private boolean transfer = false;
public ConnectThread(BluetoothDevice bluetoothDevice) {
this.device = bluetoothDevice;
try {
transfer = true;
adapter.cancelDiscovery();
bluetoothSocket = device.createRfcommSocketToServiceRecord(UUID.fromString(SPP_UUID));
Log.d(TAG, "ConnectThread: connected..");
} catch (IOException e) {
transfer = false;
e.printStackTrace();
}
}
//判断 Bluetoothsocket 是否连接
public boolean isConnect() {
return bluetoothSocket.isConnected();
}
//断开 Bluetooth连接
public void dissConnect() {
try {
transfer = false;
if (bluetoothSocket != null) {
bluetoothSocket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
try {
if (!bluetoothSocket.isConnected()) {
bluetoothSocket.connect();
}
InputStream inputStream = bluetoothSocket.getInputStream();
int bytes = 0;
byte[] buffer = new byte[1024];
while (transfer) {
bytes = inputStream.read(buffer);
Log.d(TAG, "run: " + bytes);
Message message = handler.obtainMessage();
message.obj = buffer;
message.arg1 = bytes;
message.what = MESSAGE_RECEIVER_FORM_BLUETOOTH;
handler.sendMessage(message);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
@SuppressLint("HandlerLeak")
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == MESSAGE_RECEIVER_FORM_BLUETOOTH) {
String s = new String((byte[]) msg.obj, StandardCharsets.UTF_8).trim();
Log.d(TAG, "handleMessage: " + s);
if (s.equals(ACTION_PHONAK_BLUETOOTH_PTT_PRESS)) {
ProcessControl.getInstance().getControl().startTalk();//开始PTT 对讲
} else if (s.equals(ACTION_PHONAK_BLUETOOTH_PTT_RELEASE)) {
ProcessControl.getInstance().getControl().stopTalk();//停止PTT 对讲
}
} else if (msg.what == MESSAGE_WAIT_BLUETOOTH_CONNECTED_REFUSH) {
Class<BluetoothAdapter> bluetoothAdapterClass = BluetoothAdapter.class;//得到BluetoothAdapter的Class对象
try {//得到连接状态的方法
Method method = bluetoothAdapterClass.getDeclaredMethod("getConnectionState", (Class[]) null);
//打开权限
method.setAccessible(true);
int state = (int) method.invoke(adapter, (Object[]) null);
if (state == BluetoothAdapter.STATE_CONNECTED) {
Log.i(TAG, "BluetoothAdapter.STATE_CONNECTED");
Set<BluetoothDevice> devices = adapter.getBondedDevices();
Log.i(TAG, "devices:" + devices.size());
for (BluetoothDevice device : devices) {
Method isConnectedMethod = BluetoothDevice.class.getDeclaredMethod("isConnected", (Class[]) null);
method.setAccessible(true);
boolean isConnected = (boolean) isConnectedMethod.invoke(device, (Object[]) null);
if (isConnected) {
bluetoothDevice = device;
Log.i(TAG, "connected:" + device.getName());
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (bluetoothDevice == null) {
return;
}
Log.d(TAG, "onServiceConnected: " + bluetoothDevice.getName());
connectThread = new ConnectThread(bluetoothDevice);
new Thread(connectThread).start();
}
}
};
}
以上代码可能冗余 不完善,请谅解。