App 和设备通过蓝牙连接收发数据
来源:互联网 发布:软件如何脱壳 编辑:程序博客网 时间:2024/05/31 13:16
一、Android 中进行蓝牙开发需要用到的类和执行过程
1,使用BluetoothAdapter.startLeScance来扫描设备
2,在扫描到设备的回调函数中的得到BluetoothDevice 对象,并使用Bluetooth.stopLeScan停止扫描
3,使用BluetoothDevice.connectGatt来获取到BluetoothGatt对象
4,执行BluetoothGatt.discoverServices,这个方法是异步操作,在回调函数onServicesDiscovered中得到status,通过判断status是否等于BluetoothGatt.GATT_SUCCESS来 判断查找Service是否成功
5,如果成功了,则通过BluetoothGatt.getService来获取BluetoothGattService
6,接着通过BluetoothGattService.getCharacteristic获取BluetoothGattCharacteristic
7,然后通过BluetoothGattCharacteristic.getDescriptor获取BluetoothGattDescriptor
二、收发数据
收发数据是通过GATT,GATT是通过蓝牙收发数据的一种协议,包含Characteristic,Descriptor,Service 三个属性值,BLE 分为三个部分Service , Characteristic ,Descriptor 这三个部分都是由UUID做为唯一的标识符,一个蓝牙终端可以包含多个Service ,一个Service 可以包含多个Characteristic ,一个Characteristic 包含一个Value 和多个Descriptor,一个Descriptor包含一个Value
三、上代码(有些工具类是在其他文件里面,我这里没有在改了,直接复制上来了)
MainActivice.java:
BluetoothManager bluetoothManager;BluetoothAdapter mBluetoothAdapter;
Intent intentBluetoothLeService = new Intent();
//低功耗蓝牙的文件名public static String BLUETOOTHSERVICE = "com.boe.navapp.remote.BluetoothLeService";
bluetoothManager = (BluetoothManager) MainActivity.this .getSystemService(Context.BLUETOOTH_SERVICE);mBluetoothAdapter = bluetoothManager.getAdapter();if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) { if (!(CommonUtil.isServiceRunning(MainActivity.this, Constants.BLUETOOTHSERVICE))) { intentBluetoothLeService = new Intent(MainActivity.this, BluetoothLeService.class); startService(intentBluetoothLeService); }}
// 判断当前服务是否启动public static boolean isServiceRunning(Context mContext, String className) { boolean isRunning = false; ActivityManager activityManager = (ActivityManager) mContext .getSystemService(Context.ACTIVITY_SERVICE); List<ActivityManager.RunningServiceInfo> serviceList = activityManager .getRunningServices(70); if (!(serviceList.size() > 0)) { return false; } for (int i = 0; i < serviceList.size(); i++) { if (serviceList.get(i).service.getClassName().equals(className) == true) { isRunning = true; break; } } return isRunning;}
BluetoothLeService.java:(這里我讲下主要代码,文件我会传上去)
public final static String REMOTE_CONNECT_STATUS = "REMOTE_CONNECT_STATUS";// 当前选择的遥控器连接状态
public final static String REMOTE_CONNECTED_DEVICES = "REMOTECONNECTEDDEVICES";// 存储已经连接的设备列表
public final static String REMOTE_DEVICE_INFO = "REMOTEDEVICEINFO";
public final static String REMOTE_CURR_ADDR = "REMOTECURRADDR";// 当前连接设备的地址
public final static String ACTION_GATT_REMOTESEVEN_DISCONNECTED = "com.infisight.hudprojector.bluetooth.le.ACTION_GATT_REMOTESEVEN_DISCONNECTED";
private static final String SP_NAME = "address";
@Overridepublic void onCreate() { super.onCreate(); LogTools.i(TAG, "BluetoothLeService onCreate"); prefs = PreferenceManager.getDefaultSharedPreferences(this); telMgr = (TelephonyManager) getSystemService(TELEPHONY_SERVICE); prefs.edit().putBoolean(Constants.REMOTE_CONNECT_STATUS, false) .commit(); LogTools.i(TAG, "BluetoothLeService before SaveUtils.loadArray"); addressList = SaveUtils.loadArray(this, SP_NAME); //存放连接的地址 GetDeviceInfo(); LogTools.i(TAG, "BluetoothLeService GetDeviceInfo");}
/** * 获取设备信息 lstNeedConnectDevices */private void GetDeviceInfo() { String connectedinfo = prefs.getString( Constants.REMOTE_CONNECTED_DEVICES, ""); if (!connectedinfo.equals("")) { Gson gson = new Gson(); try { lstNeedConnectDevices = gson.fromJson(connectedinfo, new TypeToken<List<BleConnectDevice>>() { }.getType()); for (BleConnectDevice bleconnectdevice : lstNeedConnectDevices) { if (!lstNeedConnectAddress.contains(bleconnectdevice .getAddress())) lstNeedConnectAddress .add(bleconnectdevice.getAddress()); } } catch (Exception e) { } }}
public boolean initialize() { // 获取蓝牙管理 if (mBluetoothManager == null) { mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); if (mBluetoothManager == null) { return false; } } // 获取适配器 mBluetoothAdapter = mBluetoothManager.getAdapter(); return mBluetoothAdapter != null;}
@Overridepublic int onStartCommand(Intent intent, int flags, int startId) { LogTools.d(TAG, "onStartCommand:flags=" + flags + ",startId=" + startId); if (mBluetoothManager == null) { if (!initialize()) { LogTools.i(TAG, "Unable to initialize Bluetooth"); } } if (isFirstRun) { try { handler.postDelayed(runnable, 2000); } catch (Exception e) { } } else { LogTools.i(TAG, "Constants.REMOTE_DEVICE_INFO:"); String address = getSharedPreferences(Constants.REMOTE_DEVICE_INFO, 0).getString(Constants.REMOTE_CURR_ADDR, "0"); connect(address); } isFirstRun = false; return START_STICKY;}
/** * 启动连接线程 */Runnable runnable = new Runnable() { @Override public void run() { // 在这里启动连接,如果连接失败,就再重新试图连接 LogTools.i(TAG, "try connect runnable"); try { mBluetoothAdapter.stopLeScan(mLeScanCallback); mBluetoothAdapter.startLeScan(mLeScanCallback); //扫描低功耗蓝牙设备 } catch (Exception e) { // TODO Auto-generated catch block LogTools.i(TAG, "try connect runnable failed:" + e.getMessage()); e.printStackTrace(); } handler.postDelayed(this, 10000); }};
// 设备查找回调得到BluetoothDevice对象LeScanCallback mLeScanCallback = new LeScanCallback() { @Override public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) { LogTools.d(TAG, "device.getName:" + device.getName() + ",device.address:" + device.getAddress()); if ("KeyCtrl".equals(device.getName())) { close(mGattMap.get(device.getAddress())); //获取BluetoothGatt 对象 BluetoothGatt mBluetoothGatt = device.connectGatt( BluetoothLeService.this, false, mGattCallback); mGattMap.put(device.getAddress(), mBluetoothGatt); } else if ("infisight_r".equals(device.getName()))//对蓝牙OBD功能进行连接 { try { close(mGattMap.get(device.getAddress())); BluetoothGatt mBluetoothGatt = device.connectGatt( BluetoothLeService.this, false, mGattCallback); mGattMap.put(device.getAddress(), mBluetoothGatt); } catch (Exception e) { LogTools.e(TAG, "mBluetoothGatt failed:" + e.getMessage()); } } }};
private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { // 连接状态发生变更 String intentAction = Constants.ACTION_GATT_REMOTESEVEN_DISCONNECTED; LogTools.e(TAG, "onConnectionStateChange:name:" + gatt.getDevice().getName() + "Addr:" + gatt.getDevice().getAddress() + ",newState:" + newState); if (newState == BluetoothProfile.STATE_CONNECTED) { hmIsConnected.put(gatt.getDevice().getAddress(), true); SaveUtils.saveArray(BluetoothLeService.this, SP_NAME, addressList); if ("KeyCtrl".equals(gatt.getDevice().getName())) { intentAction = Constants.ACTION_GATT_REMOTE_CONNECTED; } else if ("infisight_r".equals(gatt.getDevice().getName())) { LogTools.e(TAG, "ble ACTION_GATT_REMOTE_CONNECTED"); intentAction = Constants.ACTION_GATT_REMOTESEVEN_CONNECTED; } prefs.edit().putBoolean(Constants.REMOTE_CONNECT_STATUS, true) .commit(); broadcastUpdate(intentAction); LogTools.e(TAG, "ble gatt.discoverServices"); gatt.discoverServices(); SaveDeviceInfo(gatt.getDevice()); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { LogTools.d(TAG, "BluetoothProfile.STATE_DISCONNECTED"); // 开启线程,不断时的试图连接设备 hmIsConnected.put(gatt.getDevice().getAddress(), false); if ("KeyCtrl".equals(gatt.getDevice().getName())) { intentAction = Constants.ACTION_GATT_REMOTE_DISCONNECTED; } else if ("infisight_r".equals(gatt.getDevice().getName())) { LogTools.d(TAG, "BLE BluetoothProfile.STATE_DISCONNECTED"); intentAction = Constants.ACTION_GATT_REMOTESEVEN_DISCONNECTED; } prefs.edit().putBoolean(Constants.REMOTE_CONNECT_STATUS, false) .commit();// close(gatt); disconnect(gatt); broadcastUpdate(intentAction); } } //通过status 是否等于BluetoothGatt.GATT_SUCCESS来判断查找Service是否成功 @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { // 发现服务的广播 LogTools.e(TAG, "onServicesDiscovered:" + gatt.getDevice().getAddress()); if (status == BluetoothGatt.GATT_SUCCESS) { displayGattServices(getSupportedGattServices(gatt), gatt); broadcastUpdate(Constants.ACTION_GATT_SERVICES_DISCOVERED); } } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { LogTools.d(TAG, "onCharacteristicRead"); if (status == BluetoothGatt.GATT_SUCCESS) { broadcastUpdate(Constants.ACTION_DATA_AVAILABLE, gatt, characteristic); } } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { LogTools.d(TAG, "onCharacteristicChanged"); broadcastUpdate(Constants.ACTION_DATA_AVAILABLE, gatt, characteristic); } @Override public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { } };
public static boolean saveArray(Context context, String spname, ArrayList<String> list) { mySharedPreferences = context.getSharedPreferences(spname, Context.MODE_PRIVATE); Editor edit = mySharedPreferences.edit(); edit.putInt("Status_size", list.size()); /*sKey is an array*/ for (int i = 0; i < list.size(); i++) { edit.putString("Status_" + i, list.get(i) + ""); }// LogTools.i("saveArray", list+""); return edit.commit(); }
private void broadcastUpdate(final String action) { final Intent intent = new Intent(action); sendBroadcast(intent); }
/** * 保存设备信息 */ private void SaveDeviceInfo(BluetoothDevice bluetoothdevice) { List<BleConnectDevice> lstConnectDevices = new ArrayList<BleConnectDevice>(); String connectedinfo = prefs.getString( Constants.REMOTE_CONNECTED_DEVICES, ""); Gson gson = new Gson(); if (!connectedinfo.equals("")) { try { lstConnectDevices = gson.fromJson(connectedinfo, new TypeToken<List<BleConnectDevice>>() { }.getType()); } catch (Exception e) { } } if (!lstNeedConnectAddress.contains(bluetoothdevice.getAddress())) { lstNeedConnectAddress.add(bluetoothdevice.getAddress()); BleConnectDevice bledevice = new BleConnectDevice(); //保存设备的信息 bledevice.setAddress(bluetoothdevice.getAddress()); bledevice.setName(bluetoothdevice.getName()); lstConnectDevices.add(bledevice); try { String newaddr = gson.toJson(lstConnectDevices); prefs.edit() .putString(Constants.REMOTE_CONNECTED_DEVICES, newaddr) .commit(); } catch (Exception e) { } } else if ("KeyCtrl".equals(bluetoothdevice.getName())) { mTypeMap.put(bluetoothdevice.getAddress(), "remote");// }else if (bluetoothdevice.getName().contains("BLE"))//对蓝牙OBD功能进行连接 } else if ("infisight_r".equals(bluetoothdevice.getName()))//对蓝牙OBD功能进行连接 { mTypeMap.put(bluetoothdevice.getAddress(), "remote"); } }
public boolean connect(final String address) { // 确认已经获取到适配器并且地址不为空 if (mBluetoothAdapter == null || address == null || address.equals("0")) { return false; } final BluetoothDevice device = mBluetoothAdapter .getRemoteDevice(address); // 通过设备地址获取设备 if (device == null) { LogTools.e(TAG, "Device not found. Unable to connect."); return false; } // LogTools.i(TAG, "device.connectGatt(this, false, mGattCallback)"); if (mGattMap.keySet().contains(address)) { BluetoothGatt mBluetoothGatt = mGattMap.get(address); if (mBluetoothGatt != null) { // close(mBluetoothGatt); disconnect(mBluetoothGatt); } } BluetoothGatt mBluetoothGatt = device.connectGatt(this, false, mGattCallback); mGattMap.put(address, mBluetoothGatt); addressList.add(address);// mConnectionState = STATE_CONNECTING; return true; }
public void disconnect(BluetoothGatt mBluetoothGatt) { // LogTools.i("LIFECYCLE", "disconnect"); if (mBluetoothAdapter == null || mBluetoothGatt == null) { LogTools.e(TAG, "BluetoothAdapter not initialized disconnect"); return; } mBluetoothGatt.disconnect(); // 断开连接}
// 从特征中分析返回的数据并表示为action后进行广播 private void broadcastUpdate(final String action, BluetoothGatt gatt, final BluetoothGattCharacteristic characteristic) { if ("KeyCtrl".equals(gatt.getDevice().getName())) { final byte[] data = characteristic.getValue(); if (data != null && data.length > 0) { final StringBuilder stringBuilder = new StringBuilder(data.length); for (byte byteChar : data) stringBuilder.append(String.format("%02X ", byteChar)); if (stringBuilder.toString().trim().equals("01")) { // 上 int operFlag = 1; Message msg = sendKeyHandler.obtainMessage(operFlag); msg.what = operFlag; msg.sendToTarget(); LogTools.i(TAG, "keys01"); } else if (stringBuilder.toString().trim().equals("02")) { LogTools.i(TAG, "isPhoneIng:"+ProcessMsgService.isPhoneIng); if(ProcessMsgService.isPhoneIng == true) { try { PhoneUtils.getITelephony(telMgr) .answerRingingCall(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { LogTools.i(TAG, "error:"+e.getMessage()); CommonUtil.answerRingingCall(this); } return; } // 确定 int operFlag = 5; Message msg = sendKeyHandler.obtainMessage(operFlag); msg.what = operFlag; msg.sendToTarget();// ProcessBroadcast(Constants.GESTURE_INFO,// Constants.GESTURE_SINGLETAP); LogTools.i(TAG, "keys02"); } else if (stringBuilder.toString().trim().equals("04")) { // 唤醒 MainActivity.svr.controlToWake(true); LogTools.i(TAG, "keys04"); } else if (stringBuilder.toString().trim().equals("08")) { LogTools.i(TAG, "isPhoneIng:"+ProcessMsgService.isPhoneIng); LogTools.i(TAG, "keys08"); if(ProcessMsgService.isPhoneIng == true) { try { PhoneUtils.getITelephony(telMgr).endCall(); } catch (Exception e) { e.printStackTrace(); } return; } // 返回 int operFlag = 0; Message msg = sendKeyHandler.obtainMessage(operFlag); msg.what = operFlag; msg.sendToTarget();// ProcessBroadcast(Constants.GESTURE_INFO,// Constants.GETSTURE_BACK); LogTools.i(TAG, "keys08"); } else if (stringBuilder.toString().trim().equals("10")) { // 下 int operFlag = 2; Message msg = sendKeyHandler.obtainMessage(operFlag); msg.what = operFlag; msg.sendToTarget();// ProcessBroadcast(Constants.GESTURE_INFO,// Constants.GESTURE_TODOWN); LogTools.i(TAG, "keys10"); } // intent.putExtra(EXTRA_DATA, new String(data) + "\n" + // stringBuilder.toString()); }// }else if (gatt.getDevice().getName().contains("BLE")) } else if ("infisight_r".equals(gatt.getDevice().getName())) { final byte[] data = characteristic.getValue(); if (data != null && data.length > 0) { final StringBuilder stringBuilder = new StringBuilder(data.length); for (byte byteChar : data) stringBuilder.append(String.format("%02X ", byteChar)); if (stringBuilder.toString().trim().equals("15")) { // 上 int operFlag = 1; Message msg = sendKeyHandler.obtainMessage(operFlag); msg.what = operFlag; msg.sendToTarget(); } else if (stringBuilder.toString().trim().equals("12")) { //如果在通话中,接听电话 if(ProcessMsgService.isPhoneIng == true) { try { PhoneUtils.getITelephony(telMgr) .answerRingingCall(); } catch (RemoteException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (Exception e) { CommonUtil.answerRingingCall(this); } return; } // 确定 int operFlag = 5; Message msg = sendKeyHandler.obtainMessage(operFlag); msg.what = operFlag; msg.sendToTarget();// ProcessBroadcast(Constants.GESTURE_INFO,// Constants.GESTURE_SINGLETAP); } else if (stringBuilder.toString().trim().equals("14")) { // 唤醒 MainActivity.svr.controlToWake(true); } else if (stringBuilder.toString().trim().equals("16")) { //如果已经在通话中,直接挂断电话 LogTools.i(TAG, "key:16"); LogTools.i(TAG, "isPhoneIng:"+ProcessMsgService.isPhoneIng); if(ProcessMsgService.isPhoneIng == true) { try { PhoneUtils.getITelephony(telMgr).endCall(); } catch (Exception e) { e.printStackTrace(); } return; } // 返回 int operFlag = 0; Message msg = sendKeyHandler.obtainMessage(operFlag); msg.what = operFlag; msg.sendToTarget();// ProcessBroadcast(Constants.GESTURE_INFO,// Constants.GETSTURE_BACK); } else if (stringBuilder.toString().trim().equals("11")) { // 下 int operFlag = 2; Message msg = sendKeyHandler.obtainMessage(operFlag); msg.what = operFlag; msg.sendToTarget();// ProcessBroadcast(Constants.GESTURE_INFO,// Constants.GESTURE_TODOWN); } else if (stringBuilder.toString().trim().equals("13")) { // 左 int operFlag = 3; Message msg = sendKeyHandler.obtainMessage(operFlag); msg.what = operFlag; msg.sendToTarget();// ProcessBroadcast(Constants.GESTURE_INFO,// Constants.GESTURE_TOLEFT); } else if (stringBuilder.toString().trim().equals("17")) { // 右 int operFlag = 4; Message msg = sendKeyHandler.obtainMessage(operFlag); msg.what = operFlag; msg.sendToTarget();// ProcessBroadcast(Constants.GESTURE_INFO,// Constants.GESTURE_TORIGHT); } } } }BluetoothService 下载地址http://download.csdn.net/detail/pigseesunset/9690371
1 0
- App 和设备通过蓝牙连接收发数据
- android 通过蓝牙和设备通信 收发数据
- IOS BLE4.0蓝牙和外设连接和收发数据的流程
- IOS BLE4.0蓝牙和外设连接和收发数据的流程
- IOS BLE4.0蓝牙和外设连接和收发数据的流程
- 自己的APP检测系统的蓝牙连接状态和连接的设备名字
- 开发低功耗蓝牙4.0血压计连接与收发数据
- 通过蓝牙调试(穿戴设备app) - 开发文档翻译
- Android 蓝牙设备的查找和连接
- Android 蓝牙设备的查找和连接
- Android 蓝牙设备的查找和连接
- 蓝牙设备的查找和连接
- [iOS蓝牙]蓝牙连接并通过特征CBCharacteristic读写数据
- 蓝牙设备端只能与指定APP连接
- 编写安卓app程序连接指定的蓝牙设备
- android app与蓝牙设备之间连接与通讯
- IOS app蓝牙连接硬件设备 自动断开问题
- android蓝牙开发 蓝牙设备的查找和连接
- 侧滑栏: SlideMenu
- 按周统计数据,并获取本周第一天与本周最后一天
- java多线程与线程间通信
- 难以区分的三个注解
- Linux环境下搭建Jenkins三种方式
- App 和设备通过蓝牙连接收发数据
- 详细的vsftpd配置文件讲解(4)
- JS实现excel表头字母和数字的转换
- Tomcat的性能优化及部署时的参数调整
- 用筛法求之N内的素数。
- ViewPager的介绍以及使用
- 基于 SailingEase WinForm Framework 开发优秀的客户端应用程序(2:开始搭建模块化的程序框架)
- App开发:智慧北京day01
- 云计算的三种服务模式:IaaS,PaaS和SaaS