A rough explanation of the communication between Android and Bluetooth Ble, android Bluetooth ble
First, briefly introduce ble features (Note: Bluetooth 4.0 is only supported by Android 4.3 or later)
1. BLE (Bluetooth Low Energy) is the core profile of Bluetooth 4.0. It features fast search, fast connection, ultra-Low power persistence and data transmission. Disadvantages: Low data transmission rate, because of its low power consumption, it is often used in wearable devices.
2. About BLE data transmission:
A. profile can be understood as a standard communication protocol, which is stored in mobile phones. The Bluetooth organization defines some standard profiles: hid over gatt and anti-throttling devices, each profile contains multiple services.
B. A service can be understood as a service. There are multiple services in the BLE slave machine, such as power information and system service information. Each service contains multiple characteristic feature values, each specific characteristic feature value is the subject of BLE communication.
C. characteristic feature value: the BLE host communicates with each other through characteristic. It can be understood as a tag through which relevant information can be read or written.
D. UUID (uniform ID code): the unique UUID is required for both service and characteristic identification.
E. here I think you should know the roles and responsibilities, that is, the central device and the peripheral device (GATT server. GATT client .), however, here I will not talk about this. In fact, I do not quite understand the official saying. I simply and rudely use the communication between the ble app and the ble device, when the app finds the ble device, the app will receive information from ble, such as power, you don't need to know how to get it. It must be in a standardized object. (You don't need to know what the object is because I don't know either, the official name is characteristic, which is the feature value mentioned above. On the contrary, our app can also write some information to this object (characteristic) and send it to the device, after the device receives the message, it will execute the action we want it to do. In fact, it is the same as our object assignment (setValue ("fuzhi"), but the method is different. One is set and the other is write.
Finally, let's give an example to explain: in fact, the characteristic feature value is like a team of players. The service is like the name of this team. The profile should be a country, if we want to find a player, we need to know which country is the first in so many countries in the world. Second, we need to know which team is the first to know the player, only in this way can we get some information about the player (like getting information from the ble device ), on the contrary, you only need to find the player and tell the player how to play the game (similar to setting information for the ble device ). The example is hard to understand. If you understand it, it means that you graduated from elementary school just like me. If you don't understand it, you can simply read the code. Because I graduated from elementary school, I don't know much about it, and I can't turn my head too fast, afraid of turning the car ,,,
/*************************************** ************************** ***************************
1. permissions and related attributes are the most basic.
<Uses-featureandroid: name = "android. hardware. javasth_le" android: required = "true"/>
<Uses-permissionandroid: name = "android. permission. BLUETOOTH"/>
<Uses-permissionandroid: name = "android. permission. effecth_admin"/>
2. initialize Bluetooth. This method can generally be written in the startup activity of the project. Otherwise, you may not need to manually open the Bluetooth after writing the ble code and find it is difficult to experience the project, of course, as long as you are happy, you can write or not write.
Private void initBluetooth (){
Effecthmanager mblustmthmanager = (effecthmanager) this. getSystemService (Context. effecth_service );
If (mblustmthmanager! = Null ){
Descrithadapter mblustmthadapter = mblustmthmanager. getAdapter ();
If (mblustmthadapter! = Null ){
If (! Mblustmthadapter. isEnabled ()){
Mblustmthadapter. enable (); // enable Bluetooth
}
}
}
}
3. Obtain the local ble object (thinkthadapter), which corresponds to the bluetooth module of the local Android device. It may be called a local ble object, but I am happy to call it this. From this code segment, you can write the code related to ble communication to a class as a ble tool class, so that the code can be clearly viewed and conveniently called. The tool class is BleManager.
Private effecthadapter mblustmthadapter;
Private effecthdevice mblustmthdevice;
Private effecthgatt mblustmthgatt;
Private boolean isScanning = false;
// The objects defined above are useful in the following methods. (We recommend that you read the articles no matter who you are reading, first, we should familiarize ourselves with the meaning and basic functions of the above or some Bluetooth objects ).
Private BleManager (Context context ){
This. mContext = context;
Required thmanager required thmanager = (required thmanager) context. getSystemService (Context. Required th_service); // required thmanager only has
If (effecthmanager = null ){
TLog. e (TAG, "Unable to initialize thmanager .");
Return;
}
Mblustmthadapter = descrithmanager. getAdapter ();
}
4. Now that you have obtained the javasthadapter object, you can search for the ble device. In this case, you need to use the startLeScan () method of javasthadapter.
Public void startLeScan (){
If (mblustmthadapter = null ){
Return;
}
If (isScanning ){
Return;
}
IsScanning = true;
Mblustmthadapter. startLeScan (mLeScanCallback); // This mLeScanCallback is the callback function.
MHandler. sendEmptyMessageDelayed (STOP_LESCAN, 10000); // This search will take 10 seconds. If it cannot be found, it will stop searching.
}
APIS earlier than 4.3 process some events that occur during the search by registering broadcasts, while new APIs supporting ble process events by callback, mLeScanCallback is an interface object.
Private LeScanCallback mLeScanCallback = new LeScanCallback (){
@ Override
Public void onLeScan (effecthdevice device, int arg1, byte [] arg2 ){
TLog. I (TAG, "onLeScan () DeviceName ------>" + device. getName (); // you can use the device object to obtain the searched ble device name and related information.
If (device. getName () = null ){
Return;
}
If (device. getName (). contains ("Ble_Name") {// determines whether the ble device you need is found.
TLog. I (TAG, "onLeScan () DeviceAddress ------>" + device. getAddress ());
Mblustmthdevice = device; // obtain the peripheral device.
StopLeScan (); // 1. Immediately stop scanning when the corresponding device is found. 2. Do not search devices cyclically and set appropriate time limits for each search. Avoid continuous scanning and power consumption when the device is out of the available range.
Connect (); // connect
}
}
};
//
Private Handler mHandler = new Handler (){
Public void handleMessage (android. OS. Message msg ){
Switch (msg. what ){
Case STOP_LESCAN:
T. showLong (mContext, mContext. getResources (). getString (R. string. msg_connect_failed ));
Mblustmthadapter. stopLeScan (mLeScanCallback );
BroadcastUpdate (Config. ACTION_GATT_DISCONNECTED );
IsScanning = false;
TLog. I (TAG, "Scan time is up ");
Break;
}
};
};
5. Of course the connection is found, and the connect () method above is used.
Public boolean connect (){
If (mblustmthdevice = null ){
TLog. I (TAG, "effecthdevice is null .");
Return false;
}
// Two devices need to establish a GATT connection to communicate with each other through BLE. Here we are talking about connecting the Android device as the client to the GATT Server.
Mblustmthgatt = mblustmthdevice. connectGatt (mContext, false, mGattCallback); // mGattCallback is the callback Interface
If (mblustmthgatt! = Null ){
If (mbluw.thgatt. connect ()){
TLog. d (TAG, "Connect succeed .");
Return true;
} Else {
TLog. d (TAG, "Connect fail .");
Return false;
}
} Else {
TLog. d (TAG, "effecthgatt null .");
Return false;
}
}
Private final implements thgattcallback mGattCallback = new implements thgattcallback (){
@ Override
Public void onConnectionStateChange (effecthgatt gatt, int status, int newState ){
If (newState = maid. STATE_CONNECTED ){
Gatt. discoverServices (); // The Bluetooth connection is successful.
TLog. I (TAG, "Connected to GATT server .");
} Else if (newState = descrithprofile. STATE_DISCONNECTED ){
If (mblustmthdevice! = Null ){
TLog. I (TAG, "reconnect ");
Connect ();
} Else {
TLog. I (TAG, "Disconnected from GATT server .");
}
}
}
Public void onServicesDiscovered (descrithgatt gatt, int status ){
If (status = descrithgatt. GATT_SUCCESS ){
TLog. I (TAG, "onServicesDiscovered ");
GetBatteryLevel (); // get power
} Else {
TLog. I (TAG, "onServicesDiscovered status ------>" + status );
}
}
@ Override
Public void onCharacteristicRead (BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status ){
TLog. d (TAG, "onCharacteristicRead ------>" + Utils. bytesToHexString (characteristic. getValue ()));
// Determine whether the UUID is equal
If (Values. UUID_KEY_BATTERY_LEVEL_CHARACTERISTICS.equals (characteristic. getUuid (). toString ())){
}
}
@ Override
Public void onCharacteristicChanged (BluetoothGatt gatt, BluetoothGattCharacteristic characteristic ){
TLog. d (TAG, "onCharacteristicChanged ------>" + Utils. bytesToHexString (characteristic. getValue ()));
// Determine whether the UUID is equal
If (Values. UUID_KEY_BATTERY_LEVEL_CHARACTERISTICS.equals (characteristic. getUuid (). toString ())){
}
}
// Receives Characteristic write notifications. After receiving data from the bluetooth module, onCharacteristicWrite is triggered.
@ Override
Public void onCharacteristicWrite (BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status ){
TLog. d (TAG, "status =" + status );
TLog. d (TAG, "onCharacteristicWrite ------>" + Utils. bytesToHexString (characteristic. getValue ()));
}
};
Public void getBatteryLevel (){
Descrithgattcharacteristic batteryLevelGattC = getCharcteristic (
Values. UUID_KEY_BATTERY_LEVEL_SERVICE, Values. UUID_KEY_BATTERY_LEVEL_CHARACTERISTICS );
If (batteryLevelGattC! = Null ){
ReadCharacteristic (batteryLevelGattC );
SetCharacteristicNotification (batteryLevelGattC, true); // set to send a notification when the specified characteristic value changes.
}
}
6. obtain services and features
// A. Obtain the service
Public incluthgattservice getService (UUID uuid ){
If (mblustmthadapter = null | mblustmthgatt = null ){
TLog. e (TAG, "incluthadapter not initialized ");
Return null;
}
Return mbluw.thgatt. getService (uuid );
}
// B. Obtain features
Private incluthgattcharacteristic getCharcteristic (String serviceUUID, String characteristicUUID ){
// Get the service object
Export thgattservice service = getService (UUID. fromString (serviceUUID); // call the method for obtaining the service above
If (service = null ){
TLog. e (TAG, "Can not find 'your thgattservice '");
Return null;
}
// Obtain the Characteristic object under the service node
Final initialize thgattcharacteristic gattCharacteristic = service. getCharacteristic (UUID. fromString (characteristicUUID ));
If (gattCharacteristic! = Null ){
Return gattCharacteristic;
} Else {
TLog. e (TAG, "Can not find 'your thgattcharacteristic '");
Return null;
}
}
// Obtain data
Public void readCharacteristic (BluetoothGattCharacteristic characteristic ){
If (mblustmthadapter = null | mblustmthgatt = null ){
TLog. e (TAG, "incluthadapter not initialized ");
Return;
}
Mbluw.thgatt. readCharacteristic (characteristic );
}
Public boolean setCharacteristicNotification (optional thgattcharacteristic characteristic, boolean enabled ){
If (mblustmthadapter = null | mblustmthgatt = null ){
TLog. e (TAG, "incluthadapter not initialized ");
Return false;
}
Return mblustmthgatt. setCharacteristicNotification (characteristic, enabled );
}
7. Write data. In the above method, we have obtained the characteristic feature in the device service and service, so we can write or assign a value to this feature.
Public void write (byte [] data) {// generally, bytes are transmitted.
// Obtain the writeable characteristic Utils. isAIRPLANE (mContext )&&
If (! MBleManager. isEnabled ()){
TLog. e (TAG, "writeCharacteristic enable flight mode ");
// Closedomainthgatt ();
IsGattConnected = false;
BroadcastUpdate (Config. ACTION_GATT_DISCONNECTED );
Return;
}
Export thgattcharacteristic writeCharacteristic = getCharcteristic (Values. UUID_KEY_SERVICE, Values. UUID_KEY_WRITE); // This UUID is based on the uuid of the protocol number.
If (writeCharacteristic = null ){
TLog. e (TAG, "Write failed. GattCharacteristic is null .");
Return;
}
WriteCharacteristic. setValue (data); // assign a value to characteristic
WriteCharacteristicWrite (writeCharacteristic );
}
Public void writeCharacteristicWrite (descrithgattcharacteristic characteristic ){
If (mblustmthadapter = null | mblustmthgatt = null ){
TLog. e (TAG, "incluthadapter not initialized ");
Return;
}
TLog. e (TAG, "BluetoothAdapter writes data ");
Boolean isBoolean = false;
IsBoolean = mbluw.thgatt. writeCharacteristic (characteristic );
TLog. e (TAG, "effecthadapter_writecharacteristic =" + isBoolean); // If isBoolean returns true, the write is successful.
}
8. It is almost the same as writing it here. In the end, it is called in the activity. In fact, you can directly call startLeScan () to search for a Bluetooth activity, the searched results are also displayed in this method. The corresponding device name is found and then connected. For a series of callback functions in the middle, both success and failure are based on the actual project requirements of your elders. You can use a broadcast to send the callback information to the activity, tell activity what to do ........
A simple example:
Call the Bluetooth Search Method in MainActivity
Public class MainActivity extends Activity {
Private BleManager manager;
@ Override
Protected void onCreate (Bundle savedInstanceState ){
Super. onCreate (savedInstanceState );
Manager = new BleManager (this); // this is a context, as long as the above BleManager tool class defines a parameter.
Manager. startLeScan (); // call this method. If a device is found, it is connected to it. When the device is connected, the callback function mGattCallback is called back, if the connection succeeds, you can send a broadcast to remind the user that the bluetooth device is connected successfully.
}
After the search is successful, you can write information as needed. To put it simply, you call the above write (byte [] byte) method in a button event. For the parameter byte in it, it is based on the byte you set, whether the write is successful or not depends on whether the return value of writeCharacteristicWrite is true or false. true indicates that the write is successful.
9. Summary: I have just been in touch with Bluetooth, and I have read some articles. Then, I will combine some of my summary, I have written such an article for primary school students (I also want to add some impressions to myself). I would like to ask the elders to better understand it. If any of you can't see it or think it's wrong, please advise me, don't keep cainiao wrong. Thank you!