Adroid简单使用蓝牙开发(1)
程序员文章站
2024-03-24 23:14:28
...
Android简单使用蓝牙开发
虽然蓝牙传输速度很慢,但是在手机应用中使用得还是比较广泛的,由于蓝牙使用不需要网络等特点,它在智能家居中使用还是比较广泛的,比如说小区的门禁,很多门禁都会有蓝牙开锁的功能。蓝牙每次数据传输最多传送20个字节,相对其他传输协议,蓝牙传输是很慢的,它需要将许许多多的20个字节拼接成一个完整的包。不多说上下代码吧!推荐博客(https://blog.csdn.net/dingjikerbo/article/category/5889559)
[TOC]
1、先请求搜索蓝牙,获取到蓝牙列表
1.1、搜索蓝牙,设置搜索结果回调对象
private void startSearchBlueDevices() {
SearchRequest request = new SearchRequest.Builder().searchBluetoothLeDevice(5000, 2).build();
ClientManager.getClient().search(request, mSearchResponse);
}
1.2、回调对象实现代码
private final SearchResponse mSearchResponse = new SearchResponse() {
@Override
public void onSearchStarted() {
mInfoTextView.setText(R.string.blue_searching);
mDevicesList.clear();
}
@Override
public void onDeviceFounded(SearchResult device) {
if (device != null && !StringUtil.isNull(device.getName())) {
if (device.getName().startsWith("SN:")) {
if (!mDevicesList.contains(device)) {
mDevicesList.add(device);
mBlueDeviceAdapter.notifyNewData(mDevicesList);
}
}
}
}
@Override
public void onSearchStopped() {
mInfoTextView.setText(R.string.blue_device_list);
}
@Override
public void onSearchCanceled() {
mInfoTextView.setText(R.string.blue_device_list);
}
};
2、有了蓝牙列表就可以设置蓝牙点击事件了
2.1、设置蓝牙列表点击事件,并选择注册对应的蓝牙监听或取消蓝牙监听
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
switch (parent.getId()) {
case R.id.blue_device_gridView :
if (mDevicesList != null && mDevicesList.size() > position) {
if(!mIsConnected || (mBluetoothDevice != null && !mBluetoothDevice.getAddress().equalsIgnoreCase(mDevicesList.get(position).getAddress()))) {
if(mIsConnected){
mIsConnected = false;
if(mBluetoothDevice != null) {
ClientManager.getClient().disconnect(mBluetoothDevice.getAddress());
ClientManager.getClient().unregisterConnectStatusListener(mBluetoothDevice.getAddress(), mConnectStatusListener);
}
}
mBluetoothDevice = BluetoothUtils.getRemoteDevice(mDevicesList.get(position).getAddress());
if (mBluetoothDevice != null) {
ClientManager.getClient().registerConnectStatusListener(mBluetoothDevice.getAddress(), mConnectStatusListener);
connectDeviceIfNeeded();
}
}
}
break;
default:
break;
}
}
2.2、通过点击蓝牙列表,触发蓝牙通讯并获取(获取蓝牙的mac地址、CharacterUuid、ServiceUuid这些信息是用来蓝牙间进行通讯,传递数据的)
private void connectDeviceIfNeeded(){
Log.e(TAG, "enter connectDeviceIfNeeded");
if (!mIsConnected && !mIsEnterSatelliteActivity) {
mBluetoothDetailInfo = null;
showConnectDialog();
connectDevice();
}
}
private void connectDevice() {
BleConnectOptions options = new BleConnectOptions.Builder().setConnectRetry(3).setConnectTimeout(10000).setServiceDiscoverRetry(3)
.setServiceDiscoverTimeout(10000).build();
ClientManager.getClient().connect(mBluetoothDevice.getAddress(), options, new BleConnectResponse() {
@Override
public void onResponse(int code, BleGattProfile profile) {
if (code == REQUEST_SUCCESS) {
mBluetoothDetailInfo = null;
//mCustomToast.ShowToast(R.string.connect_success);
if(mHandler != null && profile != null){
List<BleGattService> services = profile.getServices();
for (BleGattService service : services) {
if(Constant.BULETOOTH_SERVICE_UUID.equalsIgnoreCase(service.getUUID().toString())) {
List<BleGattCharacter> characters = service.getCharacters();
for (BleGattCharacter character : characters) {
if(Constant.BULETOOTH_CHARACTER_UUID.equalsIgnoreCase(character.getUuid().toString())){
mBluetoothDetailInfo = new BluetoothDetailInfo();
mBluetoothDetailInfo.setBlueName(mBluetoothDevice.getName());
mBluetoothDetailInfo.setBlueMac(mBluetoothDevice.getAddress());
mBluetoothDetailInfo.setType(BluetoothDetailInfo.TYPE_CHARACTER);
mBluetoothDetailInfo.setCharacterUuid(character.getUuid());
mBluetoothDetailInfo.setServiceUuid(service.getUUID());
break;
}
}
break;
}
}
// mHandler.sendEmptyMessage(ENTER_SATELLITE_ACTIVITY);
mHandler.sendEmptyMessage(OPEN_BLUETOOTH_NOTIFY);
}
}else{
hideConnectDialog();
mCustomToast.ShowToast(R.string.connect_failed);
}
}
});
}
3、使用mac地址、serviceUuid、characterUuid来打开蓝牙通讯,并设置接收数据回调对象
3.1、打开蓝牙通讯
private void openNotify() {
if (StringUtil.isNull(mBluetoothDetailInfo.getBlueMac()) || mBluetoothDetailInfo.getServiceUuid() == null) {
return;
}
ClientManager.getClient().notify(mBluetoothDetailInfo.getBlueMac(), mBluetoothDetailInfo.getServiceUuid(), mBluetoothDetailInfo.getCharacterUuid(), mOpenNotifyCallBack);
}
3.2、接收数据回调对象代码(蓝牙传输带宽有限,每次传输数据最多20字节,最后一次发送不一定满20字节,下面的代码包含如何将数据拼接成一个完整的包)
private final BleNotifyResponse mOpenNotifyCallBack = new BleNotifyResponse() {
@Override
public void onNotify(UUID service, UUID character, byte[] data) {
if (service.equals(mBluetoothDetailInfo.getServiceUuid()) && character.equals(mBluetoothDetailInfo.getCharacterUuid())) {
String str = ByteUtils.byteToString(data);
if (str != null) {
str = str.replaceAll(" ", "");
str = str.replace("\n", "");
str = str.replaceAll("\t", "");
if (!TextUtils.isEmpty(str)) {
String receiveStr = ByteUtils.byteToString(data);
if (mReceiveLength <= 0) {
Log.e(TAG, " str : " + 2);
getBufferSize(receiveStr);
}
if (mReceiveLength > 0 && mReceiveStr.length() <= mReceiveLength - 20) {
Log.e(TAG, " str : " + 5);
mReceiveStr += receiveStr;
} else if (mReceiveLength > 0
&& (mReceiveStr.length() > mReceiveLength - 20)
&& mReceiveStr.length() < mReceiveLength) {
Log.e(TAG, " str : " + 6);
int end = mReceiveLength - mReceiveStr.length();
String subStr = receiveStr.substring(0, end);
mReceiveStr += subStr;
/**
* substring(168,168) == "" not Exception
*/
mLastReceiveStr = receiveStr.substring(end, receiveStr.length());
}
if (mReceiveLength > 0 && (mReceiveStr.length() == mReceiveLength)) {
judgeEnterActivity(mReceiveStr);
}
}
}
}
}
4、蓝牙的接收数据方法准备好后,再来弄蓝牙发送数据
4.1、蓝牙发送数据每次最多只能发送20字节,因此需要截包
public static Queue<AppSendDataInfo> splitPacketFor20Byte(byte[] data) {
Queue<AppSendDataInfo> dataInfoList = new LinkedList<>();
if (data != null) {
int index = 0;
do {
byte[] surplusData = new byte[data.length - index];
byte[] currentData;
System.arraycopy(data, index, surplusData, 0, data.length - index);
if (surplusData.length <= 20) {
currentData = new byte[surplusData.length];
System.arraycopy(surplusData, 0, currentData, 0, surplusData.length);
index += surplusData.length;
} else {
currentData = new byte[20];
System.arraycopy(data, index, currentData, 0, 20);
index += 20;
}
AppSendDataInfo dataInfo = new AppSendDataInfo();
dataInfo.setData(currentData);
dataInfoList.offer(dataInfo);
} while (index < data.length);
}
return dataInfoList;
}
4.2、包分切完毕后发送
@Override
public void run() {
doService();
}
public void doService() {
try {
if (mAppSendDataInfoQueue != null && mAppSendDataInfoQueue.size() > 0) {
mCountDownLatch = new CountDownLatch(mAppSendDataInfoQueue.size());
long time = System.currentTimeMillis();
while (mAppSendDataInfoQueue.peek() != null){
AppSendDataInfo appSendDataInfo = mAppSendDataInfoQueue.poll();
final byte[] sendData = appSendDataInfo.getData();
if(appSendDataInfo != null) {
cachedThreadPool.execute(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
sendPackageToMeter(sendData);
mCountDownLatch.countDown();
}
});
Thread.sleep(timeout);
}else{
mCountDownLatch.countDown();
}
}
mCountDownLatch.await();
if (mHandler != null) {
Message message = new Message();
message.obj = time;
message.what = mMsgWhat;
mHandler.sendMessage(message);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private void sendPackageToMeter(byte[] data) {
if (data == null || data.length <= 0) {
return;
}
if (StringUtil.isNull(mMacAddr) || mServiceUUid == null) {
return;
}
ClientManager.getClient().write(mMacAddr, mServiceUUid, mCharacterUUid, data, new BleWriteResponse() {
@Override
public void onResponse(int code) {
if (code == REQUEST_SUCCESS) {
}
}
});
}
5、当你数据数据传输结束后,不使用蓝牙的时候,需要将其关闭通讯,关闭蓝牙连接
5.1、关闭蓝牙通讯
private void closeNotify() {
if (StringUtil.isNull(mBluetoothDetailInfo.getBlueMac()) || mBluetoothDetailInfo.getServiceUuid() == null) {
return;
}
ClientManager.getClient().unnotify(mBluetoothDetailInfo.getBlueMac(), mBluetoothDetailInfo.getServiceUuid(), mBluetoothDetailInfo.getCharacterUuid(), mCloseNotifyCallBack);
}
5.2、关闭蓝牙连接
@Override
protected void onDestroy() {
super.onDestroy();
if(mBluetoothDevice != null) {
ClientManager.getClient().disconnect(mBluetoothDevice.getAddress());
ClientManager.getClient().unregisterConnectStatusListener(mBluetoothDevice.getAddress(), mConnectStatusListener);
}
if(mHandler != null){
mHandler.removeCallbacksAndMessages(null);
mHandler = null;
}
// closeNotify();
UpgradeApi.cancelCheckUpgradeRequest();
UpgradeApi.cancelDownloadApkRequest();
}
6、总结
6.1、蓝牙连接的大致过程为,首先调用蓝牙少扫描方法,获取到附近的蓝牙列表(重点是蓝牙的mac地址),通过蓝牙的mac地址来进行蓝牙连接,连接后会获得serviceUuid和characterUuid这些东西是用来与蓝牙进行通讯的验证。通讯设置完成后,通过ClientManager.getClient().write方法向另一端写数据,如果另一端有返回数据的话,数据会返回到onNotify回调方法中。最后不需要通讯的时候,关闭通讯ClientManager.getClient().unnotify,关闭蓝牙连接ClientManager.getClient().disconnect。
6.1、这篇文章只是,大致描述怎么怎么简单使用蓝牙通讯,也许我们使用的api不相同,调用的方法也会有所差异。但是蓝牙通讯的大致过程和我上面描述的差不多,希望这篇文章对您有说帮助。如果您想更深入的学习蓝牙推荐博客(https://blog.csdn.net/dingjikerbo/article/category/5889559)
上一篇: 蓝牙BLE 的几个坑与心得!
下一篇: 命名空间的理解