android 蓝牙4.0

    xiaoxiao2025-06-19  2

    本文简单结合两篇文章

    http://blog.csdn.net/hellogv/article/details/24267685

    http://blog.csdn.net/jimoduwu/article/details/21604215

    在BLE协议中,有两个角色,周边(Periphery)和中央(Central),一个中央可以同时连接多个周边,但是一个周边某一时刻只能连接一个中央。但是不管是Periphery还是Central都是可以实现 GATT server 和 GATT client去传输数据,但是无法同时都是。

    大概了解了概念后,看看Android BLE SDK的四个关键类(class):

    a) BluetoothGattServer作为周边来提供数据;BluetoothGattServerCallback返回周边的状态。

    b) BluetoothGatt作为中央来使用和处理数据;BluetoothGattCallback返回中央的状态和周边提供的数据。

    因为我们讨论的是Android的BLE SDK,下面所有的BluetoothGattServer代表周边,BluetoothGatt代表中央。

              

    一.创建一个周边(虽然目前周边API在Android手机上不工作,但还是看看)

     a)先看看周边用到的class,蓝色椭圆

    b)说明:

    每一个周边BluetoothGattServer,包含多个服务Service,每一个Service包含多个特征Characteristic。

    1.new一个特征:character = new BluetoothGattCharacteristic( UUID.fromString(characteristicUUID), BluetoothGattCharacteristic.PROPERTY_NOTIFY, BluetoothGattCharacteristic.PERMISSION_READ);

    2.new一个服务:service = new BluetoothGattService(UUID.fromString(serviceUUID), BluetoothGattService.SERVICE_TYPE_PRIMARY);

    3.把特征添加到服务:service.addCharacteristic(character);

    4.获取BluetoothManager:manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

    5.获取/打开周边:BluetoothGattServer server = manager.openGattServer(this, new BluetoothGattServerCallback(){...}); 

    6.把service添加到周边:server.addService(service);

    7.开始广播service:Google还没有广播Service的API,等吧!!!!!所以目前我们还不能让一个Android手机作为周边来提供数据。

    二.创建一个中央(这次不会让你失望,可以成功创建并且连接到周边的)

    a)先看看中央用到的class,蓝色椭圆

    b)说明:

    为了拿到中央BluetoothGatt,可要爬山涉水十八弯:

    1.先拿到BluetoothManager:bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

    2.再拿到BluetoothAdapt:btAdapter = bluetoothManager.getAdapter();

    3.开始扫描:btAdapter.startLeScan( BluetoothAdapter.LeScanCallback);

    4.从LeScanCallback中得到BluetoothDevice:public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {.....}

    5.用BluetoothDevice得到BluetoothGatt:gatt = device.connectGatt(this, true, gattCallback);

    终于拿到中央BluetoothGatt了,它有一堆方法(查API吧),调用这些方法,你就可以通过BluetoothGattCallback和周边BluetoothGattServer交互了。

    官方有给出BLE 通信的sample ,下面是牛人简化了代码,简化得简单明了

    本文来自http://blog.csdn.net/hellogv/ ,引用必须注明出处!

    最近穿戴设备发展得很火,把相关技术也带旺了,其中一项是BLE(Bluetooth Low Energy)。BLE是蓝牙4.0的核心Profile,主打功能是快速搜索,快速连接,超低功耗保持连接和传输数据,弱点是数据传输速率低,由于BLE的低功耗特点,因此普遍用于穿戴设备。Android 4.3才开始支持BLE API,所以请各位客官把本文代码运行在蓝牙4.0和Android 4.3及其以上的系统,另外本文所用的BLE终端是一个蓝牙4.0的串口蓝牙模块。

    PS:我的i9100刷了4.4系统后,竟然也能跟BLE蓝牙模块通信。

    BLE分为三部分Service、Characteristic、Descriptor,这三部分都由UUID作为唯一标示符。一个蓝牙4.0的终端可以包含多个Service,一个Service可以包含多个Characteristic,一个Characteristic包含一个Value和多个Descriptor,一个Descriptor包含一个Value。一般来说,Characteristic是手机与BLE终端交换数据的关键,Characteristic有较多的跟权限相关的字段,例如PERMISSION和PROPERTY,而其中最常用的是PROPERTY,本文所用的BLE蓝牙模块竟然没有标准的Characteristic的PERMISSION。Characteristic的PROPERTY可以通过位运算符组合来设置读写属性,例如READ|WRITE、READ|WRITE_NO_RESPONSE|NOTIFY,因此读取PROPERTY后要分解成所用的组合(本文代码已含此分解方法)。

    本文代码改自Android 4.3 Sample的BluetoothLeGatt,把冗余代码去掉,获取的BLE设备信息都通过Log,还有一些必要的读写蓝牙方法,应该算是简化到大家一看就可以懂了。本文代码可以到http://download.csdn.net/detail/hellogv/7228819下载。接下来贴出本文运行的结果,首先是连接BLE设备后,枚举出设备所有Service、Characteristic、Descriptor,并且手机会往Characteristic uuid=0000ffe1-0000-1000-8000-00805f9b34fb写入“send data->”字符串,BLE终端收到数据通过串口传到PC串口助手(见PC串口助手的截图):

    04-21 18:28:25.465: E/DeviceScanActivity(12254): -->service type:PRIMARY 04-21 18:28:25.465: E/DeviceScanActivity(12254): -->includedServices size:0 04-21 18:28:25.465: E/DeviceScanActivity(12254): -->service uuid:00001800-0000-1000-8000-00805f9b34fb 04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char uuid:00002a00-0000-1000-8000-00805f9b34fb 04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char permission:UNKNOW 04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char property:READ 04-21 18:28:25.465: E/DeviceScanActivity(12254): ---->char uuid:00002a01-0000-1000-8000-00805f9b34fb 04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char permission:UNKNOW 04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char property:READ 04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char uuid:00002a02-0000-1000-8000-00805f9b34fb 04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char permission:UNKNOW 04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char property:READ|WRITE| 04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char uuid:00002a03-0000-1000-8000-00805f9b34fb 04-21 18:28:25.470: E/DeviceScanActivity(12254): ---->char permission:UNKNOW 04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char property:READ|WRITE| 04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char uuid:00002a04-0000-1000-8000-00805f9b34fb 04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char permission:UNKNOW 04-21 18:28:25.475: E/DeviceScanActivity(12254): ---->char property:READ 04-21 18:28:25.475: E/DeviceScanActivity(12254): -->service type:PRIMARY 04-21 18:28:25.475: E/DeviceScanActivity(12254): -->includedServices size:0 04-21 18:28:25.475: E/DeviceScanActivity(12254): -->service uuid:00001801-0000-1000-8000-00805f9b34fb 04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char uuid:00002a05-0000-1000-8000-00805f9b34fb 04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char permission:UNKNOW 04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char property:INDICATE 04-21 18:28:25.480: E/DeviceScanActivity(12254): -------->desc uuid:00002902-0000-1000-8000-00805f9b34fb 04-21 18:28:25.480: E/DeviceScanActivity(12254): -------->desc permission:UNKNOW 04-21 18:28:25.480: E/DeviceScanActivity(12254): -->service type:PRIMARY 04-21 18:28:25.480: E/DeviceScanActivity(12254): -->includedServices size:0 04-21 18:28:25.480: E/DeviceScanActivity(12254): -->service uuid:0000ffe0-0000-1000-8000-00805f9b34fb 04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char uuid:0000ffe1-0000-1000-8000-00805f9b34fb 04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char permission:UNKNOW 04-21 18:28:25.480: E/DeviceScanActivity(12254): ---->char property:READ|WRITE_NO_RESPONSE|NOTIFY| 04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc uuid:00002902-0000-1000-8000-00805f9b34fb 04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc permission:UNKNOW 04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc uuid:00002901-0000-1000-8000-00805f9b34fb 04-21 18:28:25.490: E/DeviceScanActivity(12254): -------->desc permission:UNKNOW 04-21 18:28:26.025: E/DeviceScanActivity(12254): onCharRead BLE DEVICE read 0000ffe1-0000-1000-8000-00805f9b34fb -> 00

    这里红字是由BluetoothGattCallback的onCharacteristicRead()回调而打出Log

    以下Log是PC上的串口工具通过BLE模块发送过来,由BluetoothGattCallback的 onCharacteristicChanged()打出Log 04-21 18:30:18.260: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone 04-21 18:30:18.745: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone 04-21 18:30:19.085: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone 04-21 18:30:19.350: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone 04-21 18:30:19.605: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone 04-21 18:30:19.835: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone 04-21 18:30:20.055: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone 04-21 18:30:20.320: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone 04-21 18:30:20.510: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone 04-21 18:30:20.735: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone 04-21 18:30:21.000: E/DeviceScanActivity(12254): onCharWrite BLE DEVICE write 0000ffe1-0000-1000-8000-00805f9b34fb -> send data to phone

    接下来贴出本文核心代码:

    [java] view plaincopy public class DeviceScanActivity extends ListActivity {       private final static String TAG = DeviceScanActivity.class.getSimpleName();       private final static String UUID_KEY_DATA = "0000ffe1-0000-1000-8000-00805f9b34fb";          private LeDeviceListAdapter mLeDeviceListAdapter;       /**搜索BLE终端*/       private BluetoothAdapter mBluetoothAdapter;       /**读写BLE终端*/       private BluetoothLeClass mBLE;       private boolean mScanning;       private Handler mHandler;          // Stops scanning after 10 seconds.       private static final long SCAN_PERIOD = 10000;          @Override       public void onCreate(Bundle savedInstanceState) {           super.onCreate(savedInstanceState);           getActionBar().setTitle(R.string.title_devices);           mHandler = new Handler();              // Use this check to determine whether BLE is supported on the device.  Then you can           // selectively disable BLE-related features.           if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {               Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();               finish();           }              // Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to           // BluetoothAdapter through BluetoothManager.           final BluetoothManager bluetoothManager =                   (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);           mBluetoothAdapter = bluetoothManager.getAdapter();                      // Checks if Bluetooth is supported on the device.           if (mBluetoothAdapter == null) {               Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();               finish();               return;           }           //开启蓝牙           mBluetoothAdapter.enable();                      mBLE = new BluetoothLeClass(this);           if (!mBLE.initialize()) {               Log.e(TAG, "Unable to initialize Bluetooth");               finish();           }           //发现BLE终端的Service时回调           mBLE.setOnServiceDiscoverListener(mOnServiceDiscover);           //收到BLE终端数据交互的事件           mBLE.setOnDataAvailableListener(mOnDataAvailable);       }             @Override       protected void onResume() {           super.onResume();              // Initializes list view adapter.           mLeDeviceListAdapter = new LeDeviceListAdapter(this);           setListAdapter(mLeDeviceListAdapter);           scanLeDevice(true);       }          @Override       protected void onPause() {           super.onPause();           scanLeDevice(false);           mLeDeviceListAdapter.clear();           mBLE.disconnect();       }          @Override       protected void onStop() {           super.onStop();           mBLE.close();       }              @Override       protected void onListItemClick(ListView l, View v, int position, long id) {           final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);           if (device == nullreturn;           if (mScanning) {               mBluetoothAdapter.stopLeScan(mLeScanCallback);               mScanning = false;           }                      mBLE.connect(device.getAddress());       }          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);           }           invalidateOptionsMenu();       }          /**       * 搜索到BLE终端服务的事件       */       private BluetoothLeClass.OnServiceDiscoverListener mOnServiceDiscover = new OnServiceDiscoverListener(){              @Override           public void onServiceDiscover(BluetoothGatt gatt) {               displayGattServices(mBLE.getSupportedGattServices());           }                  };              /**       * 收到BLE终端数据交互的事件       */       private BluetoothLeClass.OnDataAvailableListener mOnDataAvailable = new OnDataAvailableListener(){              /**           * BLE终端数据被读的事件           */           @Override           public void onCharacteristicRead(BluetoothGatt gatt,                   BluetoothGattCharacteristic characteristic, int status) {               if (status == BluetoothGatt.GATT_SUCCESS)                    Log.e(TAG,"onCharRead "+gatt.getDevice().getName()                           +" read "                           +characteristic.getUuid().toString()                           +" -> "                           +Utils.bytesToHexString(characteristic.getValue()));           }                      /**           * 收到BLE终端写入数据回调           */           @Override           public void onCharacteristicWrite(BluetoothGatt gatt,                   BluetoothGattCharacteristic characteristic) {               Log.e(TAG,"onCharWrite "+gatt.getDevice().getName()                       +" write "                       +characteristic.getUuid().toString()                       +" -> "                       +new String(characteristic.getValue()));           }       };          // 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() {                       mLeDeviceListAdapter.addDevice(device);                       mLeDeviceListAdapter.notifyDataSetChanged();                   }               });           }       };          private void displayGattServices(List<BluetoothGattService> gattServices) {           if (gattServices == nullreturn;              for (BluetoothGattService gattService : gattServices) {               //-----Service的字段信息-----//               int type = gattService.getType();               Log.e(TAG,"-->service type:"+Utils.getServiceType(type));               Log.e(TAG,"-->includedServices size:"+gattService.getIncludedServices().size());               Log.e(TAG,"-->service uuid:"+gattService.getUuid());                              //-----Characteristics的字段信息-----//               List<BluetoothGattCharacteristic> gattCharacteristics =gattService.getCharacteristics();               for (final BluetoothGattCharacteristic  gattCharacteristic: gattCharacteristics) {                   Log.e(TAG,"---->char uuid:"+gattCharacteristic.getUuid());                                      int permission = gattCharacteristic.getPermissions();                   Log.e(TAG,"---->char permission:"+Utils.getCharPermission(permission));                                      int property = gattCharacteristic.getProperties();                   Log.e(TAG,"---->char property:"+Utils.getCharPropertie(property));                      byte[] data = gattCharacteristic.getValue();                   if (data != null && data.length > 0) {                       Log.e(TAG,"---->char value:"+new String(data));                   }                      //UUID_KEY_DATA是可以跟蓝牙模块串口通信的Characteristic                   if(gattCharacteristic.getUuid().toString().equals(UUID_KEY_DATA)){                                         //测试读取当前Characteristic数据,会触发mOnDataAvailable.onCharacteristicRead()                       mHandler.postDelayed(new Runnable() {                           @Override                           public void run() {                               mBLE.readCharacteristic(gattCharacteristic);                           }                       }, 500);                                              //接受Characteristic被写的通知,收到蓝牙模块的数据后会触发mOnDataAvailable.onCharacteristicWrite()                       mBLE.setCharacteristicNotification(gattCharacteristic, true);                       //设置数据内容                       gattCharacteristic.setValue("send data->");                       //往蓝牙模块写入数据                       mBLE.writeCharacteristic(gattCharacteristic);                   }                                      //-----Descriptors的字段信息-----//                   List<BluetoothGattDescriptor> gattDescriptors = gattCharacteristic.getDescriptors();                   for (BluetoothGattDescriptor gattDescriptor : gattDescriptors) {                       Log.e(TAG, "-------->desc uuid:" + gattDescriptor.getUuid());                       int descPermission = gattDescriptor.getPermissions();                       Log.e(TAG,"-------->desc permission:"+ Utils.getDescPermission(descPermission));                                              byte[] desData = gattDescriptor.getValue();                       if (desData != null && desData.length > 0) {                           Log.e(TAG, "-------->desc value:"new String(desData));                       }                    }               }           }//          }   }  
    转载请注明原文地址: https://ju.6miu.com/read-1300095.html
    最新回复(0)