本文简单结合两篇文章

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 plaincopyprint?
  1. public class DeviceScanActivity extends ListActivity {  
  2.     private final static String TAG = DeviceScanActivity.class.getSimpleName();  
  3.     private final static String UUID_KEY_DATA = "0000ffe1-0000-1000-8000-00805f9b34fb";  
  4.   
  5.     private LeDeviceListAdapter mLeDeviceListAdapter;  
  6.     /**搜索BLE终端*/  
  7.     private BluetoothAdapter mBluetoothAdapter;  
  8.     /**读写BLE终端*/  
  9.     private BluetoothLeClass mBLE;  
  10.     private boolean mScanning;  
  11.     private Handler mHandler;  
  12.   
  13.     // Stops scanning after 10 seconds.  
  14.     private static final long SCAN_PERIOD = 10000;  
  15.   
  16.     @Override  
  17.     public void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         getActionBar().setTitle(R.string.title_devices);  
  20.         mHandler = new Handler();  
  21.   
  22.         // Use this check to determine whether BLE is supported on the device.  Then you can  
  23.         // selectively disable BLE-related features.  
  24.         if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {  
  25.             Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();  
  26.             finish();  
  27.         }  
  28.   
  29.         // Initializes a Bluetooth adapter.  For API level 18 and above, get a reference to  
  30.         // BluetoothAdapter through BluetoothManager.  
  31.         final BluetoothManager bluetoothManager =  
  32.                 (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);  
  33.         mBluetoothAdapter = bluetoothManager.getAdapter();  
  34.           
  35.         // Checks if Bluetooth is supported on the device.  
  36.         if (mBluetoothAdapter == null) {  
  37.             Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();  
  38.             finish();  
  39.             return;  
  40.         }  
  41.         //开启蓝牙  
  42.         mBluetoothAdapter.enable();  
  43.           
  44.         mBLE = new BluetoothLeClass(this);  
  45.         if (!mBLE.initialize()) {  
  46.             Log.e(TAG, "Unable to initialize Bluetooth");  
  47.             finish();  
  48.         }  
  49.         //发现BLE终端的Service时回调  
  50.         mBLE.setOnServiceDiscoverListener(mOnServiceDiscover);  
  51.         //收到BLE终端数据交互的事件  
  52.         mBLE.setOnDataAvailableListener(mOnDataAvailable);  
  53.     }  
  54.   
  55.   
  56.     @Override  
  57.     protected void onResume() {  
  58.         super.onResume();  
  59.   
  60.         // Initializes list view adapter.  
  61.         mLeDeviceListAdapter = new LeDeviceListAdapter(this);  
  62.         setListAdapter(mLeDeviceListAdapter);  
  63.         scanLeDevice(true);  
  64.     }  
  65.   
  66.     @Override  
  67.     protected void onPause() {  
  68.         super.onPause();  
  69.         scanLeDevice(false);  
  70.         mLeDeviceListAdapter.clear();  
  71.         mBLE.disconnect();  
  72.     }  
  73.   
  74.     @Override  
  75.     protected void onStop() {  
  76.         super.onStop();  
  77.         mBLE.close();  
  78.     }  
  79.       
  80.     @Override  
  81.     protected void onListItemClick(ListView l, View v, int position, long id) {  
  82.         final BluetoothDevice device = mLeDeviceListAdapter.getDevice(position);  
  83.         if (device == nullreturn;  
  84.         if (mScanning) {  
  85.             mBluetoothAdapter.stopLeScan(mLeScanCallback);  
  86.             mScanning = false;  
  87.         }  
  88.           
  89.         mBLE.connect(device.getAddress());  
  90.     }  
  91.   
  92.     private void scanLeDevice(final boolean enable) {  
  93.         if (enable) {  
  94.             // Stops scanning after a pre-defined scan period.  
  95.             mHandler.postDelayed(new Runnable() {  
  96.                 @Override  
  97.                 public void run() {  
  98.                     mScanning = false;  
  99.                     mBluetoothAdapter.stopLeScan(mLeScanCallback);  
  100.                     invalidateOptionsMenu();  
  101.                 }  
  102.             }, SCAN_PERIOD);  
  103.   
  104.             mScanning = true;  
  105.             mBluetoothAdapter.startLeScan(mLeScanCallback);  
  106.         } else {  
  107.             mScanning = false;  
  108.             mBluetoothAdapter.stopLeScan(mLeScanCallback);  
  109.         }  
  110.         invalidateOptionsMenu();  
  111.     }  
  112.   
  113.     /** 
  114.      * 搜索到BLE终端服务的事件 
  115.      */  
  116.     private BluetoothLeClass.OnServiceDiscoverListener mOnServiceDiscover = new OnServiceDiscoverListener(){  
  117.   
  118.         @Override  
  119.         public void onServiceDiscover(BluetoothGatt gatt) {  
  120.             displayGattServices(mBLE.getSupportedGattServices());  
  121.         }  
  122.           
  123.     };  
  124.       
  125.     /** 
  126.      * 收到BLE终端数据交互的事件 
  127.      */  
  128.     private BluetoothLeClass.OnDataAvailableListener mOnDataAvailable = new OnDataAvailableListener(){  
  129.   
  130.         /** 
  131.          * BLE终端数据被读的事件 
  132.          */  
  133.         @Override  
  134.         public void onCharacteristicRead(BluetoothGatt gatt,  
  135.                 BluetoothGattCharacteristic characteristic, int status) {  
  136.             if (status == BluetoothGatt.GATT_SUCCESS)   
  137.                 Log.e(TAG,"onCharRead "+gatt.getDevice().getName()  
  138.                         +" read "  
  139.                         +characteristic.getUuid().toString()  
  140.                         +" -> "  
  141.                         +Utils.bytesToHexString(characteristic.getValue()));  
  142.         }  
  143.           
  144.         /** 
  145.          * 收到BLE终端写入数据回调 
  146.          */  
  147.         @Override  
  148.         public void onCharacteristicWrite(BluetoothGatt gatt,  
  149.                 BluetoothGattCharacteristic characteristic) {  
  150.             Log.e(TAG,"onCharWrite "+gatt.getDevice().getName()  
  151.                     +" write "  
  152.                     +characteristic.getUuid().toString()  
  153.                     +" -> "  
  154.                     +new String(characteristic.getValue()));  
  155.         }  
  156.     };  
  157.   
  158.     // Device scan callback.  
  159.     private BluetoothAdapter.LeScanCallback mLeScanCallback =  
  160.             new BluetoothAdapter.LeScanCallback() {  
  161.   
  162.         @Override  
  163.         public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {  
  164.             runOnUiThread(new Runnable() {  
  165.                 @Override  
  166.                 public void run() {  
  167.                     mLeDeviceListAdapter.addDevice(device);  
  168.                     mLeDeviceListAdapter.notifyDataSetChanged();  
  169.                 }  
  170.             });  
  171.         }  
  172.     };  
  173.   
  174.     private void displayGattServices(List gattServices) {  
  175.         if (gattServices == nullreturn;  
  176.   
  177.         for (BluetoothGattService gattService : gattServices) {  
  178.             //-----Service的字段信息-----//  
  179.             int type = gattService.getType();  
  180.             Log.e(TAG,"-->service type:"+Utils.getServiceType(type));  
  181.             Log.e(TAG,"-->includedServices size:"+gattService.getIncludedServices().size());  
  182.             Log.e(TAG,"-->service uuid:"+gattService.getUuid());  
  183.               
  184.             //-----Characteristics的字段信息-----//  
  185.             List gattCharacteristics =gattService.getCharacteristics();  
  186.             for (final BluetoothGattCharacteristic  gattCharacteristic: gattCharacteristics) {  
  187.                 Log.e(TAG,"---->char uuid:"+gattCharacteristic.getUuid());  
  188.                   
  189.                 int permission = gattCharacteristic.getPermissions();  
  190.                 Log.e(TAG,"---->char permission:"+Utils.getCharPermission(permission));  
  191.                   
  192.                 int property = gattCharacteristic.getProperties();  
  193.                 Log.e(TAG,"---->char property:"+Utils.getCharPropertie(property));  
  194.   
  195.                 byte[] data = gattCharacteristic.getValue();  
  196.                 if (data != null && data.length > 0) {  
  197.                     Log.e(TAG,"---->char value:"+new String(data));  
  198.                 }  
  199.   
  200.                 //UUID_KEY_DATA是可以跟蓝牙模块串口通信的Characteristic  
  201.                 if(gattCharacteristic.getUuid().toString().equals(UUID_KEY_DATA)){                    
  202.                     //测试读取当前Characteristic数据,会触发mOnDataAvailable.onCharacteristicRead()  
  203.                     mHandler.postDelayed(new Runnable() {  
  204.                         @Override  
  205.                         public void run() {  
  206.                             mBLE.readCharacteristic(gattCharacteristic);  
  207.                         }  
  208.                     }, 500);  
  209.                       
  210.                     //接受Characteristic被写的通知,收到蓝牙模块的数据后会触发mOnDataAvailable.onCharacteristicWrite()  
  211.                     mBLE.setCharacteristicNotification(gattCharacteristic, true);  
  212.                     //设置数据内容  
  213.                     gattCharacteristic.setValue("send data->");  
  214.                     //往蓝牙模块写入数据  
  215.                     mBLE.writeCharacteristic(gattCharacteristic);  
  216.                 }  
  217.                   
  218.                 //-----Descriptors的字段信息-----//  
  219.                 List gattDescriptors = gattCharacteristic.getDescriptors();  
  220.                 for (BluetoothGattDescriptor gattDescriptor : gattDescriptors) {  
  221.                     Log.e(TAG, "-------->desc uuid:" + gattDescriptor.getUuid());  
  222.                     int descPermission = gattDescriptor.getPermissions();  
  223.                     Log.e(TAG,"-------->desc permission:"+ Utils.getDescPermission(descPermission));  
  224.                       
  225.                     byte[] desData = gattDescriptor.getValue();  
  226.                     if (desData != null && desData.length > 0) {  
  227.                         Log.e(TAG, "-------->desc value:"new String(desData));  
  228.                     }  
  229.                  }  
  230.             }  
  231.         }//  
  232.   
  233.     }  
  234. }  



更多相关文章

  1. 一句话锁定MySQL数据占用元凶
  2. 【Android(安卓)Developers Training】 101. 显示快速联系人挂件
  3. Android版本更新时对SQLite数据库升级或者降级遇到的问题
  4. 【Android(安卓)Developers Training】 99. 获取联系人详细信息
  5. ContentProvider讲解与实例应用
  6. Android(安卓)BLE开发入门教程
  7. android之ListView的Adapter使用
  8. Android面试题(数据存储、view篇)
  9. android实现数据库和UI同步更新

随机推荐

  1. N字符在Sql Server字段类型中的重要性概
  2. SQL2000中的默认sa帐号的修改与删除方法
  3. SQL SERVER 利用存储过程查看角色和用户
  4. SQLSERVER的版本信息和SP补丁信息查看方
  5. SQL Server设置主键自增长列(使用sql语句
  6. 常用SQL语句(嵌套子查询/随机等等)详细整
  7. SQL语句的各个关键字的解析过程详细总结
  8. 存储过程实现(可带查询条件/万能分页/通
  9. 获取数据库中两个时间字段的相差天数及AB
  10. 向数据库中插入数据并返回当前插入的行数