|
@@ -0,0 +1,308 @@
|
|
|
+package com.xplora.xpsettings;
|
|
|
+
|
|
|
+import android.bluetooth.BluetoothA2dp;
|
|
|
+import android.bluetooth.BluetoothAdapter;
|
|
|
+import android.bluetooth.BluetoothClass;
|
|
|
+import android.bluetooth.BluetoothDevice;
|
|
|
+import android.bluetooth.BluetoothHeadset;
|
|
|
+import android.bluetooth.BluetoothProfile;
|
|
|
+import android.content.Context;
|
|
|
+
|
|
|
+public class BtManager {
|
|
|
+
|
|
|
+ private static volatile BtManager instance;
|
|
|
+
|
|
|
+ private BluetoothAdapter mBluetoothAdapter;
|
|
|
+
|
|
|
+ private BluetoothA2dp mBluetoothA2dp;
|
|
|
+ private BluetoothHeadset mBluetoothHeadset;
|
|
|
+
|
|
|
+ private BtManager() {
|
|
|
+ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static BtManager getInstance() {
|
|
|
+ if (instance == null) {
|
|
|
+ synchronized (BtManager.class) {
|
|
|
+ if (instance == null) {
|
|
|
+ instance = new BtManager();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return instance;
|
|
|
+ }
|
|
|
+
|
|
|
+ public BluetoothAdapter getBluetoothAdapter() {
|
|
|
+ return mBluetoothAdapter;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查当前手机是否支持蓝牙
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public boolean isSupprotBt() {
|
|
|
+ return mBluetoothAdapter != null;
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean isEnabled() {
|
|
|
+ if (mBluetoothAdapter != null) {
|
|
|
+ return mBluetoothAdapter.isEnabled();
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean setEnable(boolean isEnable) {
|
|
|
+ boolean isChanged = false;
|
|
|
+ if (mBluetoothAdapter != null) {
|
|
|
+ int state = mBluetoothAdapter.getState();
|
|
|
+ if (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_TURNING_ON) { //当前开
|
|
|
+ if (!isEnable) {
|
|
|
+ mBluetoothAdapter.disable();
|
|
|
+ isChanged = true;
|
|
|
+ }
|
|
|
+ } else { //当前关
|
|
|
+ if (isEnable) {
|
|
|
+ mBluetoothAdapter.enable();
|
|
|
+ isChanged = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return isChanged;
|
|
|
+ }
|
|
|
+
|
|
|
+ public BluetoothDevice getRemoteDevice(String btAddress) {
|
|
|
+ BluetoothDevice device = null;
|
|
|
+ if (mBluetoothAdapter != null) {
|
|
|
+ device = mBluetoothAdapter.getRemoteDevice(btAddress);
|
|
|
+ }
|
|
|
+ return device;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void startScan() {
|
|
|
+ if (mBluetoothAdapter != null) {
|
|
|
+ mBluetoothAdapter.startDiscovery();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void stopScan() {
|
|
|
+ if (mBluetoothAdapter != null) {
|
|
|
+ mBluetoothAdapter.cancelDiscovery();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void bondDevice(BluetoothDevice device) {
|
|
|
+ if (device != null && device.getBondState() == BluetoothDevice.BOND_NONE) {
|
|
|
+ //直接调用(api 19 以后才支持)
|
|
|
+ device.createBond();
|
|
|
+ /*
|
|
|
+ //反射工具类调用
|
|
|
+ try {
|
|
|
+ RefInvoke.invokeMethod(BluetoothDevice.class.getName(), "createBond", device);
|
|
|
+ } catch (Exception e) {
|
|
|
+ if (BuildConstants.DEBUG_SWITCH) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ */
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void removeBondDevice(BluetoothDevice device) {
|
|
|
+ if (device != null && device.getBondState() != BluetoothDevice.BOND_NONE) {
|
|
|
+ //直接调用(需要源码环境)
|
|
|
+ //device.removeBond();
|
|
|
+ /*
|
|
|
+ //反射工具类调用
|
|
|
+ try {
|
|
|
+ RefInvoke.invokeMethod(BluetoothDevice.class.getName(), "removeBond", device);
|
|
|
+ } catch (Exception e) {
|
|
|
+ if (BuildConstants.DEBUG_SWITCH) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ */
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getConnectionState(BluetoothDevice device) {
|
|
|
+ int state = BluetoothAdapter.STATE_DISCONNECTED;
|
|
|
+ try {
|
|
|
+ if (mBluetoothA2dp != null && doesClassMatch(device, BluetoothProfile.A2DP)) {
|
|
|
+ state = mBluetoothA2dp.getConnectionState(device);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (state == BluetoothAdapter.STATE_DISCONNECTED) {
|
|
|
+ if (mBluetoothHeadset != null && doesClassMatch(device, BluetoothProfile.HEADSET)) {
|
|
|
+ state = mBluetoothHeadset.getConnectionState(device);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+ }
|
|
|
+ return state;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void connBluetoothProfile(Context context) {
|
|
|
+ connBluetoothProfile(context, null);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void connBluetoothProfile(Context context, final BluetoothDevice device) {
|
|
|
+ try {
|
|
|
+ final BluetoothProfile.ServiceListener profileListener = new BluetoothProfile.ServiceListener() {
|
|
|
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
|
|
|
+ if (profile == BluetoothProfile.HEADSET) {
|
|
|
+ mBluetoothHeadset = (BluetoothHeadset) proxy;
|
|
|
+ } else if (profile == BluetoothProfile.A2DP) {
|
|
|
+ mBluetoothA2dp = (BluetoothA2dp) proxy;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (device != null) {
|
|
|
+ connectDevice(device);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void onServiceDisconnected(int profile) {
|
|
|
+ if (profile == BluetoothProfile.HEADSET) {
|
|
|
+ mBluetoothHeadset = null;
|
|
|
+ } else if (profile == BluetoothProfile.A2DP) {
|
|
|
+ mBluetoothA2dp = null;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ mBluetoothAdapter.getProfileProxy(context, profileListener, BluetoothProfile.HEADSET);
|
|
|
+ mBluetoothAdapter.getProfileProxy(context, profileListener, BluetoothProfile.A2DP);
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void closeBluetoothProfile() {
|
|
|
+ try {
|
|
|
+ if (mBluetoothHeadset != null) {
|
|
|
+ mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
|
|
|
+ mBluetoothHeadset = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mBluetoothA2dp != null) {
|
|
|
+ mBluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP, mBluetoothA2dp);
|
|
|
+ mBluetoothA2dp = null;
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void connectDevice(Context context, BluetoothDevice device) {
|
|
|
+ try {
|
|
|
+ if (mBluetoothHeadset != null && mBluetoothA2dp != null) {
|
|
|
+ connectDevice(device);
|
|
|
+ } else {
|
|
|
+ connBluetoothProfile(context, device);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void connectDevice(BluetoothDevice device) {
|
|
|
+ if (device != null) {
|
|
|
+ try {
|
|
|
+ if (mBluetoothHeadset != null) {
|
|
|
+ //直接调用(需要源码环境)
|
|
|
+ //mBluetoothHeadset.connect(device);
|
|
|
+ //反射工具类调用
|
|
|
+ //RefInvoke.invokeMethod(mBluetoothHeadset.getClass().getName(), "connect", mBluetoothHeadset, device);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mBluetoothA2dp != null) {
|
|
|
+ //直接调用(需要源码环境)
|
|
|
+ //mBluetoothA2dp.connect(device);
|
|
|
+ //反射工具类调用
|
|
|
+ //RefInvoke.invokeMethod(mBluetoothA2dp.getClass().getName(), "connect", mBluetoothA2dp, device);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void disConnectDevice(BluetoothDevice device) {
|
|
|
+ if (device != null) {
|
|
|
+ try {
|
|
|
+ if (mBluetoothHeadset != null && doesClassMatch(device, BluetoothProfile.HEADSET)) {
|
|
|
+ //直接调用(需要源码环境)
|
|
|
+ //mBluetoothHeadset.disconnect(device);
|
|
|
+ //反射工具类调用
|
|
|
+ //RefInvoke.invokeMethod(mBluetoothHeadset.getClass().getName(), "disconnect", mBluetoothHeadset, device);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mBluetoothA2dp != null && doesClassMatch(device, BluetoothProfile.A2DP)) {
|
|
|
+ //直接调用(需要源码环境)
|
|
|
+ //mBluetoothA2dp.disconnect(device);
|
|
|
+ //反射工具类调用
|
|
|
+ //RefInvoke.invokeMethod(mBluetoothA2dp.getClass().getName(), "disconnect", mBluetoothA2dp, device);
|
|
|
+ }
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void doDestroy() {
|
|
|
+ stopScan();
|
|
|
+ closeBluetoothProfile();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void destroy() {
|
|
|
+ if (instance != null) {
|
|
|
+ instance.doDestroy();
|
|
|
+ }
|
|
|
+ instance = null;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断是否支持某profile,需要源码环境
|
|
|
+ * @param device
|
|
|
+ * @param profile 参数只支持BluetoothProfile.A2DP,BluetoothProfile.HEADSET
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private boolean doesClassMatch(BluetoothDevice device, int profile) {
|
|
|
+ try {
|
|
|
+ //int deviceProfile = profile == BluetoothProfile.A2DP ? BluetoothClass.PROFILE_A2DP : BluetoothClass.PROFILE_HEADSET;
|
|
|
+ //return device.getBluetoothClass().doesClassMatch(deviceProfile);
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断设备是否支持音频(耳机/音箱)
|
|
|
+ * @param device
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public boolean isAudioDevice(BluetoothDevice device) {
|
|
|
+ if (device == null) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ //根据设备类型判断(根据常见的设备)
|
|
|
+ int deviceClass = device.getBluetoothClass().getDeviceClass();
|
|
|
+ if (deviceClass == BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET
|
|
|
+ || deviceClass == BluetoothClass.Device.AUDIO_VIDEO_HEADPHONES) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ */
|
|
|
+
|
|
|
+ //根据设备类型判断(系统的判断更全面)
|
|
|
+ boolean result = doesClassMatch(device, BluetoothProfile.A2DP);
|
|
|
+ if (!result) {
|
|
|
+ result = doesClassMatch(device, BluetoothProfile.HEADSET);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|