在调用蓝牙方面,接触最多的可能是BluetoothAdapter,很多操作蓝牙的方法多在此类中有接口,哪怕很多接口是不公开的,也可以通过反射的方式使用,如设置蓝牙永久可见和关闭可见的函数;而开启蓝牙大体逻辑为:
- 开启蓝牙权限
- 注册蓝牙广播
- 初始化BluetoothAdapter实例
- 开启蓝牙
- 设置可见或不可见
Bluetooth权限
AndroidManifest.xml 中注册
<!-- 允许程序连接到已配对的蓝牙设备 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- 允许程序发现和配对蓝牙设备 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
Bluetooth广播注册
if (mReceiver == null) { //蓝牙广播注册
mReceiver = new CustomBroadcastReceiver();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(mReceiver, intentFilter);
}
Bluetooth 广播Receiver
在启动蓝牙搜索时,系统会发送3个 action
BluetoothAdapter.ACTION_DISCOVERY_STARTED //启动蓝牙搜索
BluetoothDevice.ACTION_FOUND //查找到的结果
BluetoothAdapter.ACTION_DISCOVERY_FINISHED //结束蓝牙搜索
在自定义BroadcastReceiver中接受处理action; 这里需要注意的是:
@1开启蓝牙
@2接收ACTION_STATE_CHANGED广播
@3蓝牙状态是打开状态 (BluetoothAdapter.getState() == BluetoothAdapter.STATE_ON)
@4 设置蓝牙永久可见 setDiscoverableTimeout(0);
- 这个顺序执行才能让你的蓝牙可以打开和可见
以下是搜索蓝牙的具体方法:
private class CustomBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_STARTED)) {
Log.d(TAG, "正在扫描设备,请稍候...");
} else if (action.equals(BluetoothDevice.ACTION_FOUND)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getBondState() == BluetoothDevice.BOND_BONDED) { //TODO 可使用
} else { //TODO 可配对
}
} else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
Log.d(TAG, "扫描结束");
}
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
Log.d(TAG, "--------打开蓝牙-----------");
setDiscoverableTimeout(0); //蓝牙可见
} else if (mBluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
Log.d(TAG, "--------关闭蓝牙-----------");
}
}
}
}
Android6.0蓝牙搜索需要定位权限,具体博文请看Android6.0权限详解, 蓝牙搜索使用的权限申请方法如下:
private void mayRequestLocation(){
Log.d(TAG, "mayRequestLocation: androidSDK--" + Build.VERSION.SDK_INT);
if(Build.VERSION.SDK_INT >= 23){
//6.0以上设备
int checkCallPhonePermission = checkSelfPermission(Manifest.permission.
ACCESS_COARSE_LOCATION);
if(checkCallPhonePermission != PackageManager.PERMISSION_GRANTED) {
Log.d(TAG, "mayRequestLocation: 请求粗略定位的权限");
requestPermissions(new String[]{Manifest.permission.
ACCESS_COARSE_LOCATION}, REQUEST_PERMISSION_LOCATION);
return;
}
}
}
Bluetooth的适配器实例化和开启bluetooth
BluetoothAdapter 自身定义静态函数,获取适配器对象
public static synchronized BluetoothAdapter getDefaultAdapter()
if (!mBluetoothAdapter.isEnabled()) { //检测是否开启
mBluetoothAdapter.enable(); //打开蓝牙
}
Bluetooth 的可见和不可见
可见:
通过系统setting强制开启,直接从后台开启蓝牙可见,但会一直可见下去,直到蓝牙关闭。
private void setDiscoverableTimeout(int timeout) {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
try {
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(adapter, timeout);
setScanMode.invoke(adapter, BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE, timeout);
} catch (Exception e) {
e.printStackTrace();
}
}
不可见:
关闭了蓝牙可见性。
private void closeDiscoverableTimeout() {
BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
try {
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(adapter, 1);
setScanMode.invoke(adapter, BluetoothAdapter.SCAN_MODE_CONNECTABLE, 1);
} catch (Exception e) {
e.printStackTrace();
}
}
另
BluetoothAdapter的常用方法
getAddress() //获取本地蓝牙地址
getDefaultAdapter() //获取默认BluetoothAdapter,实际上,也只有这一种方法获取BluetoothAdapter
getName() //获取本地蓝牙名称
getRemoteDevice(String address) //根据蓝牙地址获取远程蓝牙设备
getState() //获取本地蓝牙适配器当前状态(感觉可能调试的时候更需要)
isDiscovering() //判断当前是否正在查找设备,是返回true
isEnabled() //判断蓝牙是否打开,已打开返回true,否则,返回false
listenUsingRfcommWithServiceRecord(String name,UUID uuid) //根据名称,UUID创建并返回
BluetoothServerSocket,这是创建BluetoothSocket服务器端的第一步
startDiscovery() //开始搜索,这是搜索的第一步
BluetoothAdapter里的方法很多,常用的有以下几个:
cancelDiscovery() //根据字面意思,是取消发现,也就是说当我们正在搜索设备的时候调用这个方法将不再继续搜索
disable() //关闭蓝牙
enable() //打开蓝牙,这个方法打开蓝牙不会弹出提示