Android 蓝牙BLE (蓝牙成长之路)3
2015-11-30 15:35
525 查看
关于蓝牙BLE最重要的 还是 service这块了(关于数据的传递,我也找到了一些demo 稍后为我们这些刚涉蓝牙BLE的菜鸟来个科普),我现在也是一知半解 先科普下(PS:我也是菜鸟中的菜鸟。。。写这个纯属加深印象。。。)下面的也是我翻遍了几乎网上少少半关于BLE的资料 整理下的(PS:网上关于BLE详解的 不多。。。个人觉的 还是要自己手打一遍 不要老是粘贴复制(PS:我通常都是ctrl+c ctrl+v))
在BLE协议中,有两个角色,周边(Periphery)和中央(Central),一个中央可以同时连接多个周边,但是一个周边某一时刻只能连接一个中央。但是不管是Periphery还是Central都是可以实现 GATT server 和 GATT client去传输数据,但是无法同时都是。
BLE分为三部分Service、Characteristic、Descriptor,这三部分都由UUID作为唯一标示符。一个蓝牙4.0的终端可以包含多个Service,一个Service可以包含多个Characteristic,一个Characteristic包含一个Value和多个Descriptor,一个Descriptor包含一个Value。
废话不多说,最最关键的部分来了(PS:网上找的 个人没有写过 加深下印象吧) import android.app.Service; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.IBinder; import android.util.Log; import java.util.List; import java.util.UUID; /** * Service for managing connection and data communication with a GATT server * hosted on a given Bluetooth LE device. */ @SuppressLint("NewApi") public class BLEService extends Service { private final static String TAG = BLEService.class.getSimpleName(); private BluetoothManager mBluetoothManager; private BluetoothAdapter mBluetoothAdapter; private String mBluetoothDeviceAddress; private BluetoothGatt mBluetoothGatt; private int mConnectionState = STATE_DISCONNECTED; private static final int STATE_DISCONNECTED = 0; private static final int STATE_CONNECTING = 1; private static final int STATE_CONNECTED = 2; public final static String ACTION_GATT_CONNECTED = "com.example.bledemo.ACTION_GATT_CONNECTED"; public final static String ACTION_GATT_DISCONNECTED = "com.example.bledemo.ACTION_GATT_DISCONNECTED"; public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.example.bledemo.ACTION_GATT_SERVICES_DISCOVERED"; public final static String ACTION_DATA_AVAILABLE = "com.example.bledemo.ACTION_DATA_AVAILABLE"; public final static String EXTRA_DATA = "com.example.bledemo.EXTRA_DATA"; public final static UUID UUID_HEART_RATE_MEASUREMENT = UUID .fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT); // Implements callback methods for GATT events that the app cares about. For // example, // connection change and services discovered. // 实现了GATT事件的回调方法,应用关心。例如,连接变化和服务发现 private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { String intentAction; System.out.println("=======status:" + status); if (newState == BluetoothProfile.STATE_CONNECTED) { intentAction = ACTION_GATT_CONNECTED; mConnectionState = STATE_CONNECTED; broadcastUpdate(intentAction); Log.i(TAG, "Connected to GATT server."); // Attempts to discover services after successful connection. Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt.discoverServices()); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { intentAction = ACTION_GATT_DISCONNECTED; mConnectionState = STATE_DISCONNECTED; Log.i(TAG, "Disconnected from GATT server."); broadcastUpdate(intentAction); } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED); } else { Log.w(TAG, "onServicesDiscovered received: " + status); } } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { System.out.println("onCharacteristicRead"); if (status == BluetoothGatt.GATT_SUCCESS) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); } } @Override public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) { System.out.println("onDescriptorWriteonDescriptorWrite = " + status + ", descriptor =" + descriptor.getUuid().toString()); } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); if (characteristic.getValue() != null) { System.out.println(characteristic.getStringValue(0)); } System.out.println("--------onCharacteristicChanged-----"); } @Override public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { System.out.println("rssi = " + rssi); } public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { System.out.println("--------write success----- status:" + status); }; }; private void broadcastUpdate(final String action) { final Intent intent = new Intent(action); sendBroadcast(intent); } private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) { final Intent intent = new Intent(action); // This is special handling for the Heart Rate Measurement profile. Data // parsing is // carried out as per profile specifications: // http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) { int flag = characteristic.getProperties(); int format = -1; if ((flag & 0x01) != 0) { format = BluetoothGattCharacteristic.FORMAT_UINT16; Log.d(TAG, "Heart rate format UINT16."); } else { format = BluetoothGattCharacteristic.FORMAT_UINT8; Log.d(TAG, "Heart rate format UINT8."); } final int heartRate = characteristic.getIntValue(format, 1); System.out.println("Received heart rate: %d" + heartRate); Log.d(TAG, String.format("Received heart rate: %d", heartRate)); intent.putExtra(EXTRA_DATA, String.valueOf(heartRate)); } else { // For all other profiles, writes the data formatted in HEX. 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)); System.out.println("ppp" + new String(data) + "\n" + stringBuilder.toString()); intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString()); } } sendBroadcast(intent); } public class LocalBinder extends Binder { BLEService getService() { return BLEService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public boolean onUnbind(Intent intent) { // After using a given device, you should make sure that // BluetoothGatt.close() is called // such that resources are cleaned up properly. In this particular // example, close() is // invoked when the UI is disconnected from the Service. close(); return super.onUnbind(intent); } private final IBinder mBinder = new LocalBinder(); /** * Initializes a reference to the local Bluetooth adapter. * * @return Return true if the initialization is successful. */ public boolean initialize() { // For API level 18 and above, get a reference to BluetoothAdapter // through // BluetoothManager. if (mBluetoothManager == null) { mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); if (mBluetoothManager == null) { Log.e(TAG, "Unable to initialize BluetoothManager."); return false; } } mBluetoothAdapter = mBluetoothManager.getAdapter(); if (mBluetoothAdapter == null) { Log.e(TAG, "Unable to obtain a BluetoothAdapter."); return false; } return true; } /** * Connects to the GATT server hosted on the Bluetooth LE device. * * @param address * The device address of the destination device. * * @return Return true if the connection is initiated successfully. The * connection result is reported asynchronously through the * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)} * callback. */ public boolean connect(final String address) { if (mBluetoothAdapter == null || address == null) { Log.w(TAG, "BluetoothAdapter not initialized or unspecified address."); return false; } // Previously connected device. Try to reconnect. (先前连接的设备。 尝试重新连接) if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress) && mBluetoothGatt != null) { Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection."); if (mBluetoothGatt.connect()) { mConnectionState = STATE_CONNECTING; return true; } else { return false; } } final BluetoothDevice device = mBluetoothAdapter .getRemoteDevice(address); if (device == null) { Log.w(TAG, "Device not found. Unable to connect."); return false; } // We want to directly connect to the device, so we are setting the // autoConnect // parameter to false. mBluetoothGatt = device.connectGatt(this, false, mGattCallback); Log.d(TAG, "Trying to create a new connection."); mBluetoothDeviceAddress = address; mConnectionState = STATE_CONNECTING; return true; } /** * Disconnects an existing connection or cancel a pending connection. The * disconnection result is reported asynchronously through the * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)} * callback. */ public void disconnect() { if (mBluetoothAdapter == null || mBluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } mBluetoothGatt.disconnect(); } /** * After using a given BLE device, the app must call this method to ensure * resources are released properly. */ public void close() { if (mBluetoothGatt == null) { return; } mBluetoothGatt.close(); mBluetoothGatt = null; } public void wirteCharacteristic(BluetoothGattCharacteristic characteristic) { if (mBluetoothAdapter == null || mBluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } mBluetoothGatt.writeCharacteristic(characteristic); } /** * Request a read on a given {@code BluetoothGattCharacteristic}. The read * result is reported asynchronously through the * {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)} * callback. * * @param characteristic * The characteristic to read from. */ public void readCharacteristic(BluetoothGattCharacteristic characteristic) { if (mBluetoothAdapter == null || mBluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } mBluetoothGatt.readCharacteristic(characteristic); } /** * Enables or disables notification on a give characteristic. * * @param characteristic * Characteristic to act on. * @param enabled * If true, enable notification. False otherwise. */ public void setCharacteristicNotification( BluetoothGattCharacteristic characteristic, boolean enabled) { if (mBluetoothAdapter == null || mBluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID .fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG)); if (descriptor != null) { System.out.println("write descriptor"); descriptor .setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mBluetoothGatt.writeDescriptor(descriptor); } /* * // This is specific to Heart Rate Measurement. if * (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) { * System * .out.println("characteristic.getUuid() == "+characteristic.getUuid * ()+", "); BluetoothGattDescriptor descriptor = * characteristic.getDescriptor * (UUID.fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG)); * descriptor * .setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); * mBluetoothGatt.writeDescriptor(descriptor); } */ } /** * Retrieves a list of supported GATT services on the connected device. This * should be invoked only after {@code BluetoothGatt#discoverServices()} * completes successfully. * * @return A {@code List} of supported services. */ public List<BluetoothGattService> getSupportedGattServices() { if (mBluetoothGatt == null) return null; return mBluetoothGatt.getServices(); } /** * Read the RSSI for a connected remote device. * */ public boolean getRssiVal() { if (mBluetoothGatt == null) return false; return mBluetoothGatt.readRemoteRssi(); } }
再加上一个 演示的类的源代码
import java.util.HashMap; /** * This class includes a small subset of standard GATT attributes for demonstration purposes. * 这个类包括一小部分标准GATT属性用于演示目的 */ public class SampleGattAttributes { private static HashMap<String, String> attributes = new HashMap(); public static String HEART_RATE_MEASUREMENT = "0000C004-0000-1000-8000-00805f9b34fb"; public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb"; static { // Sample Services. attributes.put("0000fff00000-1000-8000-00805f9b34fb", "Heart Rate Service"); attributes.put("0000180a-0000-1000-8000-00805f9b34fb", "Device Information Service"); // Sample Characteristics. attributes.put(HEART_RATE_MEASUREMENT, "Heart Rate Measurement"); attributes.put("00002a29-0000-1000-8000-00805f9b34fb", "Manufacturer Name String"); } public static String lookup(String uuid, String defaultName) { String name = attributes.get(uuid); return name == null ? defaultName : name; } }
相关文章推荐
- Android 蓝牙BLE (蓝牙成长之路)1
- Android 蓝牙BLE (蓝牙成长之路)2
- Android蓝牙BLE之RSSI读写(2)
- Android蓝牙BLE之RSSI数据的读写(1)
- Android 蓝牙BLE (蓝牙成长之路)5
- Android 蓝牙BLE (蓝牙成长之路)4
- Android 5.0 API新增和改进
- Android 一键锁屏实现
- Android短信----接收流程---框架层(Frameworks)
- Fragment的startActivityForResult详细解决方案
- AndroidStudio更改字体颜色和大小
- Android编程实现基于BitMap获得图片像素数据的方法
- android 控件ImageView的常用属性说明
- android canvas save和restore
- Android Activity的加载模式和onActivityResult方法之间的冲突
- java 线程间数据共享和android 线程间数据共享异同
- GitHub 优秀的 Android 开源项目
- Android JPush(极光推送)的使用教程
- android 开机自启动脚本