最近要做Android手机通过蓝牙跟硬件通过互通数据,实现操控硬件的效果。
1.蓝牙权限的打开
//用于蓝牙之间传输数据的权限
<uses-permission android:name="android.permission.BLUETOOTH"/>
//设备被检测到
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
还有一个点要注意:要使用蓝牙4.0,必须要求手机 API 18以上。
2.开始查找设备
你买的硬件的蓝牙模块在默认情况下是处于被检测的状态,所以手机直接连接就好。
手机端查找蓝牙设备的方式有两种:
(1)通过给bluetoothAdapter.startLeScanBluet方法设置LeScanCallback回调来进行(我就是用的这种方式,感觉这种方式最靠谱)
//获取BluetoothManager
final BluetoothManager bluetoothManager =(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
//获取adapter
BluetoothAdapter mBluetoothAdapter = bluetoothManager.getAdapter();
//这种可以实现不弹对话框打开蓝牙
if (!mBluetoothAdapter.isEnabled()) {
//若没打开则打开蓝牙
mBluetoothAdapter.enable();
}
//该方法为查找设备的方法
private void scanLeDevice(final boolean enable) {
if (enable) {
// Stops scanning after a pre-defined scan period.
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
mScanning = false; mBluetoothAdapter.stopLeScan(mLeScanCallback);
invalidateOptionsMenu();
}
}, SCAN_PERIOD);
mScanning = true;
mBluetoothAdapter.startLeScan(mLeScanCallback);
} else {
mScanning = false;
mBluetoothAdapter.stopLeScan(mLeScanCallback);
}
}
//查找到设备后的回调
// Device scan callback.
private BluetoothAdapter.LeScanCallback mLeScanCallback =new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
runOnUiThread(new Runnable() {
@Override
public void run() {
//这里我用一个list来存储所搜索到的设备
mLeDeviceListAdapter.addDevice(device); mLeDeviceListAdapter.notifyDataSetChanged();
}
});
}
};
(2)通过startDiscovery+BroadcastReceiver来实现(这种方式有时候搜索不到)
这种方式需要 Build.VERSION.SDK_INT >= 23 并且添加相应的权限
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
// 寻找蓝牙设备,android会将查找到的设备以广播形式发出去
adapter.startDiscovery();
//广播接收
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
System.out.println(device.getName());
}
}
}
3.开始连接设备并实现相互通信
这里我用了一个service+broadcast来实现的。service的主要作用是去连接蓝牙并实现数据的交互。broadcast主要用于更新UI。
代码比较长我就贴主要的,全部代码在demo里面
//连接设备的方法
public boolean connect(final String address) {
if (mBluetoothAdapter == null || address == null) {
Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
return false;
}
// Previously connected device. Try to reconnect.
if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
&& mBluetoothGatt != null) {
Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
if (mBluetoothGatt.connect()) {
mConnectionState = STATE_CONNECTING;
return true;
} else {
return false;
}
}
final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
if (device == null) {
Log.w(TAG, "Device not found. Unable to connect.");
return false;
}
// We want to directly connect to the device, so we are setting the autoConnect
// parameter to false.
mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
Log.d(TAG, "Trying to create a new connection.");
mBluetoothDeviceAddress = address;
mConnectionState = STATE_CONNECTING;
return true;
}
//设备状态的接口回调
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
@Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
String intentAction;
if (newState == BluetoothProfile.STATE_CONNECTED) {
intentAction = ACTION_GATT_CONNECTED;
mConnectionState = STATE_CONNECTED;
broadcastUpdate(intentAction);
Log.i(TAG, "Connected to GATT server.");
// Attempts to discover services after successful connection.
Log.i(TAG, "Attempting to start service discovery:" +
mBluetoothGatt.discoverServices());
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
intentAction = ACTION_GATT_DISCONNECTED;
mConnectionState = STATE_DISCONNECTED;
Log.i(TAG, "Disconnected from GATT server.");
broadcastUpdate(intentAction);
}
}