隨着物聯網的發展,現在藍牙設備越來越多了,像藍牙耳機、藍牙音箱等,那麼怎樣去連接管理這些設備呢,本文將通過藍牙耳機做實例,來實現藍牙的開關、搜索、配對、連接、設備藍牙的可見性、獲取藍牙信息等;
先來看看具體效果:
1、添加權限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-feature android:name="android.hardware.location.gps" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
2、初始化
mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothadapter = mBluetoothManager.getAdapter();
3、設置廣播監聽
mFilter = new IntentFilter();
mFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//狀態改變
mFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); //藍牙開關狀態
mFilter.addAction(BluetoothDevice.ACTION_FOUND);//藍牙發現新設備(未配對)
mFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); //藍牙開始搜索
mFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); //藍牙搜索結束
mFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); //設備配對狀態改變
mFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);//設備建立連接
mFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); //設備斷開連接
mFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); //BluetoothAdapter連接狀態
mFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); //BluetoothHeadset連接狀態
mFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); //BluetoothA2dp連接狀態
4、搜索藍牙
搜索藍牙之前要判斷藍牙是否打開,打開藍牙可以使用enable()方法,當藍牙打開後,調用startDiscovery()進行搜索,具體相關代碼如下:
@Override
public boolean open() {//打開藍牙 ture-打開成功
if(mBluetoothadapter==null){
return false;
}
return mBluetoothadapter.enable();
}
@Override
public boolean close() {//關閉藍牙
if(mBluetoothadapter==null){
return true;
}
return mBluetoothadapter.disable();
}
@Override
public boolean startDiscovery() {//搜索藍牙
if(mBluetoothadapter==null){
return false;
}
if (mBluetoothadapter.isDiscovering()) {
mBluetoothadapter.cancelDiscovery();
}
return mBluetoothadapter.startDiscovery();
}
@Override
public boolean stopDiscovery() {//停止搜索藍牙
if(mBluetoothadapter==null||!mBluetoothadapter.isDiscovering()){
return true;
}
return mBluetoothadapter.cancelDiscovery();
}
5、連接設備:
當搜索完成之後,找到要連接的設備進行連接,連接之前我們需要獲取各種設備的相關代理服務,一般常用的代理服務有這兩個種:BluetoothA2dp、BluetoothHeadset。BluetoothA2dp進行音頻數據傳送服務,BluetoothHeadset耳機相關服務。首頁獲取相關服務,具體代碼如下:
mBluetoothadapter.getProfileProxy(mContext,mProfileServiceListener, BluetoothProfile.A2DP);
mBluetoothadapter.getProfileProxy(mContext,mProfileServiceListener, BluetoothProfile.HEADSET);
該方式沒有直接方法相關服務代理,而是通過服務監聽返回,mProfileServiceListener的相關代碼如下:
private BluetoothProfile.ServiceListener mProfileServiceListener=new BluetoothProfile.ServiceListener() {
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
Log.i(TAG, "onServiceConnected profile="+profile);
if(profile == BluetoothProfile.A2DP){//播放音樂
mBluetoothA2dp = (BluetoothA2dp) proxy; //轉換
isA2dpComplete=true;
}else if(profile == BluetoothProfile.HEADSET){//打電話
mBluetoothHeadset = (BluetoothHeadset) proxy;
isHeadsetComplete=true;
}
if(isA2dpComplete&&isHeadsetComplete&&isBackConDev&&mBTConnectListener!=null){
List<BluetoothDevice> devices=new ArrayList<>();
if(mBluetoothA2dp!=null){
// removeA2dpMacEqual();
List<BluetoothDevice> deviceList=mBluetoothA2dp.getConnectedDevices();
if(deviceList!=null&&deviceList.size()>0){
devices.addAll(deviceList);
}
}
if(mBluetoothHeadset!=null){
// removeHeadsetMacEqual();
List<BluetoothDevice> deviceList=mBluetoothHeadset.getConnectedDevices();
if(deviceList!=null&&deviceList.size()>0){
devices.addAll(deviceList);
}
}
mBTConnectListener.onConnectedDevice(devices);
}
// else if(profile == BluetoothProfile.HEALTH){//健康
// mBluetoothHealth = (BluetoothHealth) proxy;
// }
}
@Override
public void onServiceDisconnected(int profile) {
Log.i(TAG, "onServiceDisconnected profile="+profile);
if(profile == BluetoothProfile.A2DP){
mBluetoothA2dp = null;
}else if(profile == BluetoothProfile.HEADSET){
mBluetoothHeadset = null;
}
// else if(profile == BluetoothProfile.HEALTH) {
// mBluetoothHealth = null;
// }
}
};
獲取相關的代理服務之後,就可以連接相應的設備了,具體相關代碼如下:
@Override
public boolean connect(BluetoothDevice device) {
int styleMajor = device.getBluetoothClass().getMajorDeviceClass();
boolean isConnect=false;
switch (styleMajor) {
case BluetoothClass.Device.Major.AUDIO_VIDEO://音頻設備
if(connectA2dpAndHeadSet(BluetoothHeadset.class,mBluetoothHeadset,device)){
isConnect=true;
}
if(connectA2dpAndHeadSet(BluetoothA2dp.class,mBluetoothA2dp,device)){
isConnect=true;
}
return isConnect;
// case BluetoothClass.Device.Major.COMPUTER://電腦
// break;
// case BluetoothClass.Device.Major.HEALTH://健康狀況
// break;
// case BluetoothClass.Device.Major.IMAGING://鏡像,映像
// break;
case BluetoothClass.Device.Major.MISC://麥克風
if(connectA2dpAndHeadSet(BluetoothHeadset.class,mBluetoothHeadset,device)){
isConnect=true;
}
if(connectA2dpAndHeadSet(BluetoothA2dp.class,mBluetoothA2dp,device)){
isConnect=true;
}
return isConnect;
// case BluetoothClass.Device.Major.NETWORKING://網絡
// break;
// case BluetoothClass.Device.Major.PERIPHERAL://外部設備
// break;
case BluetoothClass.Device.Major.PHONE://電話
if(connectA2dpAndHeadSet(BluetoothHeadset.class,mBluetoothHeadset,device)){
isConnect=true;
}
if(connectA2dpAndHeadSet(BluetoothA2dp.class,mBluetoothA2dp,device)){
isConnect=true;
}
return isConnect;
// case BluetoothClass.Device.Major.TOY://玩具
// break;
// case BluetoothClass.Device.Major.UNCATEGORIZED://未知的
// break;
// case BluetoothClass.Device.Major.WEARABLE://穿戴設備
// break;
}
if(connectA2dpAndHeadSet(BluetoothHeadset.class,mBluetoothHeadset,device)){
isConnect=true;
}
if(connectA2dpAndHeadSet(BluetoothA2dp.class,mBluetoothA2dp,device)){
isConnect=true;
}
return isConnect;
}
/**
* 連接A2dp 與 HeadSet
* @param device
* @param device
*/
private boolean connectA2dpAndHeadSet(Class btClass,BluetoothProfile bluetoothProfile,BluetoothDevice device){
setPriority(device, 100); //設置priority
try {
//通過反射獲取BluetoothA2dp中connect方法(hide的),進行連接。
Method connectMethod =btClass.getMethod("connect",
BluetoothDevice.class);
connectMethod.setAccessible(true);
connectMethod.invoke(bluetoothProfile, device);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 設置優先級
* 優先級是必要的,否則可能導致連接或斷開連接失敗等問題
* @param device
* @param priority
*/
private void setPriority(BluetoothDevice device, int priority) {
if (mBluetoothA2dp == null) return;
try {//通過反射獲取BluetoothA2dp中setPriority方法(hide的),設置優先級
Method connectMethod =BluetoothA2dp.class.getMethod("setPriority",
BluetoothDevice.class,int.class);
connectMethod.setAccessible(true);
connectMethod.invoke(mBluetoothA2dp, device, priority);
} catch (Exception e) {
e.printStackTrace();
}
}
6、其他藍牙設備的連接
不同的藍牙設備,其功能也不相通過,android中可以更具設備的類型來連接相應的服務,android中將設備大致分爲如下如下幾類,在代碼中使用如下:
int styleMajor = bluetoothDevice.getBluetoothClass().getMajorDeviceClass();//獲取藍牙主要分類
switch (styleMajor) {
case BluetoothClass.Device.Major.AUDIO_VIDEO://音頻設備
holder.img_signal.setImageResource(R.mipmap.icon_headset);
break;
case BluetoothClass.Device.Major.COMPUTER://電腦
holder.img_signal.setImageResource(R.mipmap.icon_computer);
break;
case BluetoothClass.Device.Major.HEALTH://健康狀況
holder.img_signal.setImageResource(R.mipmap.icon_bluetooth);
break;
case BluetoothClass.Device.Major.IMAGING://鏡像,映像
holder.img_signal.setImageResource(R.mipmap.icon_bluetooth);
break;
case BluetoothClass.Device.Major.MISC://麥克風
holder.img_signal.setImageResource(R.mipmap.icon_bluetooth);
break;
case BluetoothClass.Device.Major.NETWORKING://網絡
holder.img_signal.setImageResource(R.mipmap.icon_bluetooth);
break;
case BluetoothClass.Device.Major.PERIPHERAL://外部設備
holder.img_signal.setImageResource(R.mipmap.icon_bluetooth);
break;
case BluetoothClass.Device.Major.PHONE://電話
holder.img_signal.setImageResource(R.mipmap.icon_phone);
break;
case BluetoothClass.Device.Major.TOY://玩具
holder.img_signal.setImageResource(R.mipmap.icon_bluetooth);
break;
case BluetoothClass.Device.Major.UNCATEGORIZED://未知的
holder.img_signal.setImageResource(R.mipmap.icon_bluetooth);
break;
case BluetoothClass.Device.Major.WEARABLE://穿戴設備
holder.img_signal.setImageResource(R.mipmap.icon_bluetooth);
break;
}
通過藍牙主要分類來區分不同類型的設備,之後再通過相應的服務代理連接設備,android相關的服務代理如下:
public boolean getProfileProxy(Context context, BluetoothProfile.ServiceListener listener,
int profile) {
if (context == null || listener == null) return false;
if (profile == BluetoothProfile.HEADSET) {
BluetoothHeadset headset = new BluetoothHeadset(context, listener);
return true;
} else if (profile == BluetoothProfile.A2DP) {
BluetoothA2dp a2dp = new BluetoothA2dp(context, listener);
return true;
} else if (profile == BluetoothProfile.A2DP_SINK) {
BluetoothA2dpSink a2dpSink = new BluetoothA2dpSink(context, listener);
return true;
} else if (profile == BluetoothProfile.AVRCP_CONTROLLER) {
BluetoothAvrcpController avrcp = new BluetoothAvrcpController(context, listener);
return true;
} else if (profile == BluetoothProfile.INPUT_DEVICE) {
BluetoothInputDevice iDev = new BluetoothInputDevice(context, listener);
return true;
} else if (profile == BluetoothProfile.PAN) {
BluetoothPan pan = new BluetoothPan(context, listener);
return true;
} else if (profile == BluetoothProfile.HEALTH) {
BluetoothHealth health = new BluetoothHealth(context, listener);
return true;
} else if (profile == BluetoothProfile.MAP) {
BluetoothMap map = new BluetoothMap(context, listener);
return true;
} else if (profile == BluetoothProfile.HEADSET_CLIENT) {
BluetoothHeadsetClient headsetClient = new BluetoothHeadsetClient(context, listener);
return true;
} else if (profile == BluetoothProfile.SAP) {
BluetoothSap sap = new BluetoothSap(context, listener);
return true;
} else if (profile == BluetoothProfile.PBAP_CLIENT) {
BluetoothPbapClient pbapClient = new BluetoothPbapClient(context, listener);
return true;
} else if (profile == BluetoothProfile.MAP_CLIENT) {
BluetoothMapClient mapClient = new BluetoothMapClient(context, listener);
return true;
} else if (profile == BluetoothProfile.INPUT_HOST) {
BluetoothInputHost iHost = new BluetoothInputHost(context, listener);
return true;
} else {
return false;
}
}
可以根據具體的設備來獲取相應的服務,獲取的方式跟獲取BluetoothA2dp、BluetoothHeadset的方式是一致的。
好了,到這裏基本上要的的功能的實現完了,下面將BluetoothHelper類的帶放到下面,面時具體相關的功能實現:
package com.qt.bluetooth.bluetooth;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.text.TextUtils;
import android.util.Log;
import com.qt.bluetooth.bluetooth.interfaces.IBTBoudListener;
import com.qt.bluetooth.bluetooth.interfaces.IBTConnectListener;
import com.qt.bluetooth.bluetooth.interfaces.IBTScanListener;
import com.qt.bluetooth.bluetooth.interfaces.IBTStateListener;
import com.qt.bluetooth.bluetooth.interfaces.IBluetoothHelper;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
*@date 2019/7/23
*@desc 藍牙輔助類
*
*/
public class BluetoothHelper implements IBluetoothHelper {
private final String TAG="BluetoothHelper";
private Context mContext;
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothadapter;
private BluetoothA2dp mBluetoothA2dp;
private BluetoothHeadset mBluetoothHeadset;
// private BluetoothHealth mBluetoothHealth;
private IntentFilter mFilter;
private IBTStateListener mBTStateListener;//藍牙狀態監聽
private IBTScanListener mBTScanListener;//藍牙搜索監聽
private IBTBoudListener mBTBoudListener;//藍牙綁定監聽
private IBTConnectListener mBTConnectListener;//連接監聽
private boolean isBackConDev;//是否返回已連接的設備
private boolean isA2dpComplete,isHeadsetComplete;
@Override
public void init(Context context) {
mContext=context.getApplicationContext();
mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
mBluetoothadapter = mBluetoothManager.getAdapter();
isA2dpComplete=false;
isHeadsetComplete=false;
mBluetoothadapter.getProfileProxy(mContext,mProfileServiceListener, BluetoothProfile.A2DP);
mBluetoothadapter.getProfileProxy(mContext,mProfileServiceListener, BluetoothProfile.HEADSET);
// mBluetoothadapter.getProfileProxy(mContext,mProfileServiceListener, BluetoothProfile.HEALTH);
if(mFilter==null){
mContext.registerReceiver(mBluetoothReceiver,makeFilter());
}
}
private IntentFilter makeFilter() {
if(mFilter==null){
mFilter = new IntentFilter();
mFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);//狀態改變
mFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); //藍牙開關狀態
mFilter.addAction(BluetoothDevice.ACTION_FOUND);//藍牙發現新設備(未配對)
mFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); //藍牙開始搜索
mFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); //藍牙搜索結束
mFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); //設備配對狀態改變
mFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);//設備建立連接
mFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED); //設備斷開連接
mFilter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED); //BluetoothAdapter連接狀態
mFilter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); //BluetoothHeadset連接狀態
mFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED); //BluetoothA2dp連接狀態
}
return mFilter;
}
/**
* 連接A2dp 與 HeadSet
* @param device
* @param device
*/
private boolean connectA2dpAndHeadSet(Class btClass,BluetoothProfile bluetoothProfile,BluetoothDevice device){
setPriority(device, 100); //設置priority
try {
//通過反射獲取BluetoothA2dp中connect方法(hide的),進行連接。
Method connectMethod =btClass.getMethod("connect",
BluetoothDevice.class);
connectMethod.setAccessible(true);
connectMethod.invoke(bluetoothProfile, device);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 斷開A2dp 與 HeadSet
* @param device
*/
private boolean disConnectA2dpAndHeadSet(Class btClass,BluetoothProfile bluetoothProfile,BluetoothDevice device){
setPriority(device, 0);
try {
//通過反射獲取BluetoothA2dp中connect方法(hide的),斷開連接。
Method connectMethod =btClass.getMethod("disconnect",
BluetoothDevice.class);
connectMethod.setAccessible(true);
connectMethod.invoke(bluetoothProfile, device);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 設置優先級
* 優先級是必要的,否則可能導致連接或斷開連接失敗等問題
* @param device
* @param priority
*/
private void setPriority(BluetoothDevice device, int priority) {
if (mBluetoothA2dp == null) return;
try {//通過反射獲取BluetoothA2dp中setPriority方法(hide的),設置優先級
Method connectMethod =BluetoothA2dp.class.getMethod("setPriority",
BluetoothDevice.class,int.class);
connectMethod.setAccessible(true);
connectMethod.invoke(mBluetoothA2dp, device, priority);
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public boolean open() {//打開藍牙 ture-打開成功
if(mBluetoothadapter==null){
return false;
}
return mBluetoothadapter.enable();
}
@Override
public boolean close() {//關閉藍牙
if(mBluetoothadapter==null){
return true;
}
return mBluetoothadapter.disable();
}
@Override
public boolean startDiscovery() {//搜索藍牙
if(mBluetoothadapter==null){
return false;
}
if (mBluetoothadapter.isDiscovering()) {
mBluetoothadapter.cancelDiscovery();
}
return mBluetoothadapter.startDiscovery();
}
@Override
public boolean stopDiscovery() {//停止搜索藍牙
if(mBluetoothadapter==null||!mBluetoothadapter.isDiscovering()){
return true;
}
return mBluetoothadapter.cancelDiscovery();
}
@Override
public String getName() {//獲取本地藍牙名稱
if(mBluetoothadapter==null){
return null;
}
return mBluetoothadapter.getName();
}
@Override
public boolean setName(String name) {//設置藍牙的名稱
if (mBluetoothadapter == null) {
return false;
}
return mBluetoothadapter.setName(name);
}
@Override
public String getAddress() {//獲取本地藍牙地址
if(mBluetoothadapter==null){
return null;
}
return mBluetoothadapter.getAddress();
}
@Override
public boolean isEnable() {//藍牙是否可用,即是否打開
if(mBluetoothadapter==null){
return false;
}
return mBluetoothadapter.isEnabled();
}
@Override
public boolean isSupport() {//是否支持藍牙
return mBluetoothadapter==null?false:true;
}
@Override
public Set<BluetoothDevice> getBondedDevices() {//獲取以配對設備
if(mBluetoothadapter==null){
return null;
}
return mBluetoothadapter.getBondedDevices();
}
@Override
public boolean createBond(BluetoothDevice device) {//配對
if(device==null){
return false;
}
return device.createBond();
}
@Override
public boolean removeBond(BluetoothDevice device) {//取消配對
Class btDeviceCls = BluetoothDevice.class;
Method removeBond = null;
try {
removeBond = btDeviceCls.getMethod("removeBond");
removeBond.setAccessible(true);
return (boolean) removeBond.invoke(device);
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
@Override
public boolean connect(BluetoothDevice device) {
int styleMajor = device.getBluetoothClass().getMajorDeviceClass();
boolean isConnect=false;
switch (styleMajor) {
case BluetoothClass.Device.Major.AUDIO_VIDEO://音頻設備
if(connectA2dpAndHeadSet(BluetoothHeadset.class,mBluetoothHeadset,device)){
isConnect=true;
}
if(connectA2dpAndHeadSet(BluetoothA2dp.class,mBluetoothA2dp,device)){
isConnect=true;
}
return isConnect;
// case BluetoothClass.Device.Major.COMPUTER://電腦
// break;
// case BluetoothClass.Device.Major.HEALTH://健康狀況
// break;
// case BluetoothClass.Device.Major.IMAGING://鏡像,映像
// break;
case BluetoothClass.Device.Major.MISC://麥克風
if(connectA2dpAndHeadSet(BluetoothHeadset.class,mBluetoothHeadset,device)){
isConnect=true;
}
if(connectA2dpAndHeadSet(BluetoothA2dp.class,mBluetoothA2dp,device)){
isConnect=true;
}
return isConnect;
// case BluetoothClass.Device.Major.NETWORKING://網絡
// break;
// case BluetoothClass.Device.Major.PERIPHERAL://外部設備
// break;
case BluetoothClass.Device.Major.PHONE://電話
if(connectA2dpAndHeadSet(BluetoothHeadset.class,mBluetoothHeadset,device)){
isConnect=true;
}
if(connectA2dpAndHeadSet(BluetoothA2dp.class,mBluetoothA2dp,device)){
isConnect=true;
}
return isConnect;
// case BluetoothClass.Device.Major.TOY://玩具
// break;
// case BluetoothClass.Device.Major.UNCATEGORIZED://未知的
// break;
// case BluetoothClass.Device.Major.WEARABLE://穿戴設備
// break;
}
if(connectA2dpAndHeadSet(BluetoothHeadset.class,mBluetoothHeadset,device)){
isConnect=true;
}
if(connectA2dpAndHeadSet(BluetoothA2dp.class,mBluetoothA2dp,device)){
isConnect=true;
}
return isConnect;
}
@Override
public boolean disconnect(BluetoothDevice device) {
boolean isDisconnect=false;
if(mBluetoothA2dp!=null){
List<BluetoothDevice> devices=mBluetoothA2dp.getConnectedDevices();
if(devices!=null&&devices.contains(device)){
Log.d(TAG,"disconnect A2dp");
isDisconnect=disConnectA2dpAndHeadSet(BluetoothA2dp.class,mBluetoothA2dp,device);
}
}
if(mBluetoothHeadset!=null){
List<BluetoothDevice> devices=mBluetoothHeadset.getConnectedDevices();
if(devices!=null&&devices.contains(device)){
Log.d(TAG,"disconnect Headset");
isDisconnect=disConnectA2dpAndHeadSet(BluetoothHeadset.class,mBluetoothHeadset,device);
}
}
return isDisconnect;
// int styleMajor = device.getBluetoothClass().getMajorDeviceClass();
// switch (styleMajor) {
// case BluetoothClass.Device.Major.AUDIO_VIDEO://音頻設備
// return disConnectA2dpAndHeadSet(BluetoothA2dp.class,device);
// case BluetoothClass.Device.Major.COMPUTER://電腦
// break;
// case BluetoothClass.Device.Major.HEALTH://健康狀況
// return disConnectA2dpAndHeadSet(BluetoothHealth.class,device);
// case BluetoothClass.Device.Major.IMAGING://鏡像,映像
// break;
// case BluetoothClass.Device.Major.MISC://麥克風
// break;
// case BluetoothClass.Device.Major.NETWORKING://網絡
// break;
// case BluetoothClass.Device.Major.PERIPHERAL://外部設備
// break;
// case BluetoothClass.Device.Major.PHONE://電話
// return disConnectA2dpAndHeadSet(BluetoothHeadset.class,device);
// case BluetoothClass.Device.Major.TOY://玩具
// break;
// case BluetoothClass.Device.Major.UNCATEGORIZED://未知的
// break;
// case BluetoothClass.Device.Major.WEARABLE://穿戴設備
// break;
// }
// return disConnectA2dpAndHeadSet(BluetoothA2dp.class,device);
}
@Override
public void destroy() {
if(mFilter!=null){
mFilter=null;
mContext.unregisterReceiver(mBluetoothReceiver);
}
isA2dpComplete=false;
isHeadsetComplete=false;
mBluetoothadapter.closeProfileProxy(BluetoothProfile.A2DP,mBluetoothA2dp);
mBluetoothadapter.closeProfileProxy(BluetoothProfile.HEADSET,mBluetoothHeadset);
}
@Override
public void getConnectedDevices() {
if(isBackConDev){
return;
}
isBackConDev=true;
if(isA2dpComplete&&isHeadsetComplete){
List<BluetoothDevice> devices=new ArrayList<>();
if(mBluetoothA2dp!=null){
// removeA2dpMacEqual();
List<BluetoothDevice> deviceList=mBluetoothA2dp.getConnectedDevices();
if(deviceList!=null&&deviceList.size()>0){
devices.addAll(deviceList);
}
}
if(mBluetoothHeadset!=null){
// removeHeadsetMacEqual();
List<BluetoothDevice> deviceList=mBluetoothHeadset.getConnectedDevices();
if(deviceList!=null&&deviceList.size()>0){
devices.addAll(deviceList);
}
}
mBTConnectListener.onConnectedDevice(devices);
isBackConDev=false;
}
}
// /**
// * 移除A2dp mac相等設備
// */
// private void removeA2dpMacEqual(){
// if(mBluetoothA2dp==null){
// return;
// }
// List<BluetoothDevice> deviceList=mBluetoothA2dp.getConnectedDevices();
// if(deviceList==null||deviceList.size()<1){
// return;
// }
// for(int i=0;i<deviceList.size();){
// BluetoothDevice bluetoothDevice=deviceList.get(i);
// boolean isSkip=false;
// for(int j=i+1;j<deviceList.size();){
// BluetoothDevice device=deviceList.get(j);
// if(!TextUtils.isEmpty(device.getAddress())&&device.getAddress().equals(bluetoothDevice.getAddress())){
// isSkip=true;
// if(mBluetoothA2dp.getConnectionState(bluetoothDevice) == BluetoothA2dp.STATE_CONNECTED){
// deviceList.remove(device);
// }else if(mBluetoothA2dp.getConnectionState(device) == BluetoothA2dp.STATE_CONNECTED){
// deviceList.remove(bluetoothDevice);
// }else{
// deviceList.remove(bluetoothDevice);
// }
// break;
// }
// j++;
// }
// if(isSkip){
// continue;
// }
// i++;
// }
// }
// /**
// * 移除Headset mac相等設備
// */
// private void removeHeadsetMacEqual(){
// if(mBluetoothHeadset==null){
// return;
// }
// List<BluetoothDevice> deviceList=mBluetoothHeadset.getConnectedDevices();
// if(deviceList==null||deviceList.size()<1){
// return;
// }
// for(int i=0;i<deviceList.size();){
// BluetoothDevice bluetoothDevice=deviceList.get(i);
// boolean isSkip=false;
// for(int j=i+1;j<deviceList.size();){
// BluetoothDevice device=deviceList.get(j);
// if(!TextUtils.isEmpty(device.getAddress())&&device.getAddress().equals(bluetoothDevice.getAddress())){
// isSkip=true;
// if(mBluetoothHeadset.getConnectionState(bluetoothDevice) == BluetoothHeadset.STATE_CONNECTED){
// deviceList.remove(device);
// }else if(mBluetoothHeadset.getConnectionState(device) == BluetoothHeadset.STATE_CONNECTED){
// deviceList.remove(bluetoothDevice);
// }else{
// deviceList.remove(bluetoothDevice);
// }
// break;
// }
// j++;
// }
// if(isSkip){
// continue;
// }
// i++;
// }
// }
@Override
public boolean isConnected(BluetoothDevice device) {//是否連接
if(mBluetoothA2dp!=null&&mBluetoothA2dp.getConnectionState(device) == BluetoothA2dp.STATE_CONNECTED){
Log.d(TAG,"isConnected name="+device.getName());
// removeA2dpMacEqual();
List<BluetoothDevice> bluetoothDeviceList=mBluetoothA2dp.getConnectedDevices();
if(bluetoothDeviceList!=null&&bluetoothDeviceList.size()>0){
for(BluetoothDevice bluetoothDevice:bluetoothDeviceList){
if(!TextUtils.isEmpty(device.getAddress())&&device.getAddress().equals(bluetoothDevice.getAddress())){
return true;
}
}
}
}
if(mBluetoothHeadset!=null&&mBluetoothHeadset.getConnectionState(device) == BluetoothHeadset.STATE_CONNECTED){
Log.d(TAG,"isConnected name="+device.getName());
// removeHeadsetMacEqual();
List<BluetoothDevice> bluetoothDeviceList=mBluetoothHeadset.getConnectedDevices();
if(bluetoothDeviceList!=null&&bluetoothDeviceList.size()>0){
for(BluetoothDevice bluetoothDevice:bluetoothDeviceList){
if(!TextUtils.isEmpty(device.getAddress())&&device.getAddress().equals(bluetoothDevice.getAddress())){
return true;
}
}
}
}
return false;
}
@Override
public boolean setDiscoverableTimeout(int timeout) {
try {//得到指定的類中的方法
// Method method = BluetoothAdapter.class.getMethod("setDiscoverableTimeout", int.class);
// method.setAccessible(true);
// method.invoke(mBluetoothadapter, timeout);//根據測試,發現這一函數的參數無論傳遞什麼值,都是永久可見的
Method setDiscoverableTimeout = BluetoothAdapter.class.getMethod("setDiscoverableTimeout",int.class);
setDiscoverableTimeout.setAccessible(true);
Method setScanMode =BluetoothAdapter.class.getMethod("setScanMode",int.class,int.class);
setScanMode.setAccessible(true);setDiscoverableTimeout.invoke(mBluetoothadapter,timeout);
setScanMode.invoke(mBluetoothadapter,BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE,timeout);
return true;
} catch (Exception e) {
Log.d(TAG,"setDiscoverableTimeout msg="+e.getMessage());
e.printStackTrace();
}
return false;
}
@Override
public void setBTStateListener(IBTStateListener btStateListener) {
mBTStateListener=btStateListener;
}
@Override
public void setBTScanListener(IBTScanListener btScanListener) {
mBTScanListener=btScanListener;
}
@Override
public void setBTBoudListener(IBTBoudListener btBoudListener) {
mBTBoudListener=btBoudListener;
}
@Override
public void setBTConnectListener(IBTConnectListener btConnectListener) {
mBTConnectListener=btConnectListener;
}
//A2dp
private BluetoothProfile.ServiceListener mProfileServiceListener=new BluetoothProfile.ServiceListener() {
@Override
public void onServiceConnected(int profile, BluetoothProfile proxy) {
Log.i(TAG, "onServiceConnected profile="+profile);
if(profile == BluetoothProfile.A2DP){//播放音樂
mBluetoothA2dp = (BluetoothA2dp) proxy; //轉換
isA2dpComplete=true;
}else if(profile == BluetoothProfile.HEADSET){//打電話
mBluetoothHeadset = (BluetoothHeadset) proxy;
isHeadsetComplete=true;
}
if(isA2dpComplete&&isHeadsetComplete&&isBackConDev&&mBTConnectListener!=null){
List<BluetoothDevice> devices=new ArrayList<>();
if(mBluetoothA2dp!=null){
// removeA2dpMacEqual();
List<BluetoothDevice> deviceList=mBluetoothA2dp.getConnectedDevices();
if(deviceList!=null&&deviceList.size()>0){
devices.addAll(deviceList);
}
}
if(mBluetoothHeadset!=null){
// removeHeadsetMacEqual();
List<BluetoothDevice> deviceList=mBluetoothHeadset.getConnectedDevices();
if(deviceList!=null&&deviceList.size()>0){
devices.addAll(deviceList);
}
}
mBTConnectListener.onConnectedDevice(devices);
}
// else if(profile == BluetoothProfile.HEALTH){//健康
// mBluetoothHealth = (BluetoothHealth) proxy;
// }
}
@Override
public void onServiceDisconnected(int profile) {
Log.i(TAG, "onServiceDisconnected profile="+profile);
if(profile == BluetoothProfile.A2DP){
mBluetoothA2dp = null;
}else if(profile == BluetoothProfile.HEADSET){
mBluetoothHeadset = null;
}
// else if(profile == BluetoothProfile.HEALTH) {
// mBluetoothHealth = null;
// }
}
};
private BroadcastReceiver mBluetoothReceiver=new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice dev;
int state;
if (action == null) {
return;
}
switch (action) {
/**
* 藍牙開關狀態
* int STATE_OFF = 10; //藍牙關閉
* int STATE_ON = 12; //藍牙打開
* int STATE_TURNING_OFF = 13; //藍牙正在關閉
* int STATE_TURNING_ON = 11; //藍牙正在打開
*/
case BluetoothAdapter.ACTION_STATE_CHANGED:
state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
if(mBTStateListener!=null){
mBTStateListener.onStateChange(state);
}
break;
/**
* 藍牙開始搜索
*/
case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
Log.i(TAG, "藍牙開始搜索");
if(mBTScanListener!=null){
mBTScanListener.onScanStart();
}
break;
/**
* 藍牙搜索結束
*/
case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
Log.i(TAG, "藍牙掃描結束");
if(mBTScanListener!=null){
mBTScanListener.onScanStop(null);
}
break;
/**
* 發現新設備
*/
case BluetoothDevice.ACTION_FOUND:
dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// short rssi = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI,(short)0);//信號強度
if(mBTScanListener!=null){
mBTScanListener.onFindDevice(dev);
}
break;
/**
* 設備配對狀態改變
* int BOND_NONE = 10; //配對沒有成功
* int BOND_BONDING = 11; //配對中
* int BOND_BONDED = 12; //配對成功
*/
case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if(mBTBoudListener!=null){
mBTBoudListener.onBondStateChange(dev);
}
Log.i(TAG, "設備配對狀態改變:" + dev.getBondState());
break;
/**
* 設備建立連接
* int STATE_DISCONNECTED = 0; //未連接
* int STATE_CONNECTING = 1; //連接中
* int STATE_CONNECTED = 2; //連接成功
*/
case BluetoothDevice.ACTION_ACL_CONNECTED:
dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.i(TAG, "設備建立連接:" + dev.getBondState());
// mCallback.onConnect(dev);
break;
/**
* 設備斷開連接
*/
case BluetoothDevice.ACTION_ACL_DISCONNECTED:
dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// mCallback.onConnect(dev.getBondState(), dev);
break;
/**
* 本地藍牙適配器
* BluetoothAdapter連接狀態
*/
case BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED:
dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.i(TAG, "Adapter STATE: " + intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, 0));
Log.i(TAG, "BluetoothDevice: " + dev.getName() + ", " + dev.getAddress());
break;
/**
* 提供用於手機的藍牙耳機支持
* BluetoothHeadset連接狀態
*/
case BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED:
dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
Log.i(TAG, "Headset STATE: " + intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, 0));
Log.i(TAG, "BluetoothDevice: " + dev.getName() + ", " + dev.getAddress());
switch (intent.getIntExtra(BluetoothHeadset.EXTRA_STATE, -1)) {
case BluetoothHeadset.STATE_CONNECTING://連接中
if(mBTConnectListener!=null){
mBTConnectListener.onConnecting(dev);
}
break;
case BluetoothHeadset.STATE_CONNECTED://已連接
if(mBTConnectListener!=null){
mBTConnectListener.onConnected(dev);
}
break;
case BluetoothHeadset.STATE_DISCONNECTED://斷開
if(mBTConnectListener!=null){
mBTConnectListener.onDisConnect(dev);
}
break;
case BluetoothHeadset.STATE_DISCONNECTING://斷開中
if(mBTConnectListener!=null){
mBTConnectListener.onDisConnecting(dev);
}
break;
}
break;
/**
* 定義高質量音頻可以從一個設備通過藍牙連接傳輸到另一個設備
* BluetoothA2dp連接狀態
*/
case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
dev = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
switch (intent.getIntExtra(BluetoothA2dp.EXTRA_STATE, -1)) {
case BluetoothA2dp.STATE_CONNECTING:
Log.i(TAG,"A2dp device: " + dev.getName() + " connecting");
if(mBTConnectListener!=null){
mBTConnectListener.onConnecting(dev);
}
break;
case BluetoothA2dp.STATE_CONNECTED:
Log.i(TAG,"A2dp device: " + dev.getName() + " connected");
if(mBTConnectListener!=null){
mBTConnectListener.onConnected(dev);
}
break;
case BluetoothA2dp.STATE_DISCONNECTING:
Log.i(TAG,"A2dp device: " + dev.getName() + " disconnecting");
if(mBTConnectListener!=null){
mBTConnectListener.onDisConnecting(dev);
}
break;
case BluetoothA2dp.STATE_DISCONNECTED:
Log.i(TAG,"A2dp device: " + dev.getName() + " disconnected");
if(mBTConnectListener!=null){
mBTConnectListener.onDisConnect(dev);
}
break;
default:
break;
}
default:
break;
}
}
};
}
最後給出demo的下載地址