android 蓝牙ble设备开发
2016-04-14 10:05
891 查看
由于最近项目需要使用了bluetooth ble开发,所以把蓝牙连接ble设备摸索了一遍,希望能帮到各位开发者,有个提示也好。 先说说整体思路 一 打开蓝牙 BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE); if (bluetoothManager == null || bluetoothManager.getAdapter() == null) { ToastUtil.showToast(mContext, "对不起 ,您的机器不具备蓝牙功能"); } if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { //必须是4.3系统以上才支持蓝牙ble设备 Toast.makeText(mContext, “不支持ble设备”, Toast.LENGTH_SHORT).show(); } bluetoothAdapter = bluetoothManager.getAdapter(); if (!bluetoothAdapter.isEnabled()) { // 蓝牙没有打开 if (bluetoothAdapter.enable()) { // 蓝牙打开成功 } else { Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); ((Activity) mContext).startActivityForResult(enableIntent, BlueToothUtils.BLUE_OPEN_REQUESTCODE); } } else { // 已经打开蓝牙 } 二 搜索蓝牙设备 //打开蓝牙之后就需要搜索设备了 @SuppressWarnings("deprecation") public void scanLeDevice(final boolean enable) { if (bluetoothAdapter != null) { if (enable) { //控制搜索蓝牙时间 mHandler.postDelayed(new Runnable() { @Override public void run() { if (mScanning) { mScanning = false; bluetoothAdapter.stopLeScan(mLeScanCallback); // 发送设备搜索完成 mHandler.sendEmptyMessage(BLUETOOTH_SEARCHE_END); } } }, 5*1000); mScanning = true; bluetoothAdapter.startLeScan(mLeScanCallback); LogUtils.d("开始搜索设备"); } else { LogUtils.d("关闭搜索设备"); mScanning = false; bluetoothAdapter.stopLeScan(mLeScanCallback); } } } 三 连接蓝牙服务并且监听蓝牙服务 //连接服务 public void startConnectThread(BluetoothDevice device) { cnntThread = new ConnectThread(device, true); cnntThread.start(); } class ConnectThread extends Thread { public ConnectThread(BluetoothDevice device, boolean secure) { try { if (device != null) { mBluetoothGatt = device.connectGatt(mContext, false, mGattCallback); } } catch (Exception e) { LogUtils.e("error: " + e); } } @Override public void run() { try { if (bluetoothAdapter != null && bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); } if (mBluetoothGatt != null) { boolean isConnect = mBluetoothGatt.connect(); LogUtils.d("ConnectThread中run方法mBluetoothGatt的连接状态" + isConnect); } } catch (Exception e) { LogUtils.e(e); return; } } public void cancel() { if (mBluetoothGatt != null) mBluetoothGatt.close(); } } private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { LogUtils.d("onCharacteristicWrite;status=" + status); } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { // 获取蓝牙ble设备返回给你的信息 } @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { // 当连接状态发生改变的时候 LogUtils.d("onConnectionStateChange;status=" + newState); if (BluetoothProfile.STATE_CONNECTED == newState) { boolean discoverServicesFlag = mBluetoothGatt.discoverServices(); LogUtils.d("发现服务" + discoverServicesFlag); } else if (BluetoothProfile.STATE_DISCONNECTED == newState) { // 连接失败 closeBlueTooth(); mHandler.sendEmptyMessage(BLUETOOTH_ERROR); LogUtils.d("onConnectionStateChange;连接服务失败" + newState); } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { // 当发现服务的时候 LogUtils.d("onServicesDiscovered;status=" + status); // 这里判断服务是否连接成功,然后设置监听是否成功,然后再判断与蓝牙设备是否连接成功 if (status == BluetoothGatt.GATT_SUCCESS) { boolean openListenServiceFlag = openListenService(); if (openListenServiceFlag) { mHandler.sendEmptyMessage(BLUETOOTH_CONNECTED_SUCCESS); } else { closeBlueTooth(); mHandler.sendEmptyMessage(BLUETOOTH_ERROR); ToastUtil.showToast(mContext, "监听服务失败,请重试"); } } else { closeBlueTooth(); mHandler.sendEmptyMessage(BLUETOOTH_ERROR); //ToastUtil.showToast(mContext, "发现服务失败,请重试"); } } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { LogUtils.d("onCharacteristicRead;status=" + status); } }; /*** * 打开监听服务 * * @return */ private boolean openListenService() { try { if (mBluetoothGatt != null) { String serviceUUID = "0000ffe0-0000-1000-8000-00805f9b34fb"; String characterUUID = "0000ffe4-0000-1000-8000-00805f9b34fb"; BluetoothGattService serv = mBluetoothGatt.getService(UUID.fromString(serviceUUID)); if (serv != null) { BluetoothGattCharacteristic charcter = serv.getCharacteristic(UUID.fromString(characterUUID)); // 指定当bluetoothGattCharacteristic发生改变的时候,发出通知 boolean isSucess = mBluetoothGatt.setCharacteristicNotification(charcter, true); return isSucess; } } } catch (Exception e) { LogUtils.e(e); } return false; } 四 发送指令,获取ble设备返回的指令信息 // 监听server的UUID和character的UUID,这个是需要跟硬件设备开发人员商量的 private String servUUID = "0000ffe5-0000-1000-8000-00805f9b34fb"; private String CharacterUUID = "0000ffe9-0000-1000-8000-00805f9b34fb"; //获取指令byte[] private void sendCommand(){ /** *这里的byte[]比如 *byte[] bytes = new bytes[] bytes[0] = (byte) getDecode("0xBB"); */ byte[] value = BlueToothUtils.entryValue(userPhone); runCommandWithUUID(value); }/*** * 将字符串转化成16进制 * * @param str * @return */ public static int getDecode(String str) { return Integer.decode(str); } /*** * 发送指令 * * @param servUUID * @param CharacterUUID * @param value */ private boolean runCommandWithUUID(byte[] value) { if (mBluetoothGatt != null) { BluetoothGattService serv = mBluetoothGatt.getService(UUID.fromString(servUUID)); BluetoothGattCharacteristic charcter = serv.getCharacteristic(UUID.fromString(CharacterUUID)); boolean isSetSucess = charcter.setValue(value); boolean isWriteSucess = mBluetoothGatt.writeCharacteristic(charcter); if (!isWriteSucess) { isWriteSucess = mBluetoothGatt.writeCharacteristic(charcter); } // 发送指令完成 LogUtils.d("发送指令完成isSetSucess=" + isSetSucess + ";isWriteSucess=" + isWriteSucess); if (isWriteSucess) { //这里应该反馈给mainActivity中 mHandler.sendEmptyMessage(BLUETOOTH_SEND_VALUE_SUCCESS); return true; } } return false; } //蓝牙通知广播,仅作参考 IntentFilter bluetoothFilter = new IntentFilter(); bluetoothFilter.addAction(tBluetoothAdapter.ACTION_STATE_CHANGED);// 蓝牙状态改变的广播 bluetoothFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);// 蓝牙扫描模式广播 bluetoothFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);// 蓝牙搜索状态广播 bluetoothFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);// 蓝牙搜索中广播 bluetoothFilter.addAction(BluetoothDevice.ACTION_FOUND);// 蓝牙搜索广播 bluetoothFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);// 蓝牙绑定状态广播 getActivity().registerReceiver(mBluetoothStateReciver, bluetoothFilter);
//广播接受者 private BroadcastReceiver mBluetoothStateReciver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action == BluetoothAdapter.ACTION_STATE_CHANGED) { int blueToothState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.STATE_OFF); showToastBlueToothState(blueToothState); } else if (action == BluetoothAdapter.ACTION_DISCOVERY_FINISHED) { // 表示搜索结束 MyProcessDialog.closeDialog(); }else if(action == BluetoothDevice.ACTION_FOUND){ BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); System.out.println("搜索到的蓝牙名称是:"+device.getName()); } } };
这里说明一下进制转换,因为android发送指令是16进制的byte[],所以字符串转成byte搞得特别头疼,只能怪自己数学没认真学啊。
首先说明几个函数
1 Integer.decode(String str)这个函数是将十进制/十六进制/八进制的字符串转成整型,如果要按照byte发送的话,还需要强转成byte,也就是Integer.decode(String str).byteValue().
2 Integer.toHexString(i)将int转成16进制的字符串
另外在说一说基础,以免忘记,byte表示1个字节,1个字节是8bit,也就是8个二进制数,
低八位和高八位,例如十进制的12345678,1234表示高4位,5678表示低4位,如果一个16进制数,1111000010101010中11110000表示高八位10101010表示低八位
前面如果有0x就表示16进制,&是一个按位与符号,Integer.toHexString(int i)&0xFF解释:"ff”是一个16进制数化成二进制数就是(11111111)
当一个32位二进制数与一个8位二进制数11111111按位与时,这个32位二进制数的高24位都会变成0,低8位会保持原来的数值(因为高24位中的每一位都是与0相与, 当然都是0了,而低8位都是与1相与,所以会保持原值)
计算校验和
private static String getCheckAndStr(byte[] bytes) {
int value = 0;
for (int i = 1; i < bytes.length; i++) {
value += bytes[i];
}
//将int转成16进制字符串
String valueStr = Integer.toHexString(value);
int vl = valueStr.length();
// 获取低八位 16进制
String codeStr = valueStr.substring(vl - 2, vl);
return codeStr;
}
相关文章推荐
- Android studio 使用 Genymotion问题集锦
- Android热补丁动态修复技术(三)—— 使用Javassist注入字节码,完成热补丁框架雏形(可使用)
- Android 使用命令模拟sdcard相关行文
- Android FrameWork——Activity启动过程详解
- 2.1 Android进程间通信(IPC)----Binder机制的简单介绍
- Android Studio简单设置
- 通过移动设备访问邮件
- Android onSaveInstanceState和onRestoreInstanceState触发的时机
- [Learn Android Studio 汉化教程]第一章 : Android Studio 介绍
- mac版android studio 2.0正式版
- Ubuntu下调试android设备
- 收集android国内资源
- Android Studio 2.0的闪电编译的设置
- Android Pingpong漏洞解析
- Android Mediacodec硬解H264并显示
- Android上传头像代码,相机,相册,裁剪
- android:screenOrientation属性
- Android中Parcelable接口用法
- android stdio 2
- Android 限制EditText仅仅能输入数字、限制输入类型、限制输入长度的小技巧