An easy-to-use Bluetooth development framework for the Android platform.
This framework is already in production. After several iterations, it has been relatively stable and reliable. I have been engaged in Android Bluetooth related app development for a long time, studied the Bluetooth protocol stack under Android, and also worked on the firmware development of Bluetooth chip. This framework was developed to increase the ease of use and stability of using the Android Bluetooth API.
- Support BLE devices for basic operations such as scanning, connect, read, write, notification subscription and cancellation.
- Support custom scan mode (power saving, balance, power consumption), foreground background scanning mode, filtering rules, etc.
- Support for periodic scanning function.
- Support connection retry feature to increase connection success probability.
- Support Bluetooth command timeout feature.
- Supports Bluetooth command cache, priority features, multiple devices connected to execute commands more stable.
dependencies {
implementation 'cn.bingerz.android:flipble:0.7.8'
}
- As the name suggests, Bluetooth is a master-slave device. For example, the use of mobile phones and sports bracelets, the mobile phone is central, the bracelet is peripheral; FlipBLE only supports mobile phones that are Central's working mode and do not support working mode as a peripheral.
\\ Given the lifecycle of CentralManager, it is best to use the Application Context
\\ Can be initialized in the Activity and Service onCreate() method
CentralManager.getInstance().init(getApplicationContext());
CentralManager.getInstance()
.enableLog(true) //Enable ble log
.setOperateTimeout(5000) //Set the timeout period for Read and Write operations
.setMaxConnectCount(7); //Set max number of connections, Default value:7
//This is the maximum value defined in the Bluetooth protocol doc.
List<ScanFilterConfig> scanFilterConfigs = new ArrayList<>();
ScanFilterConfig.Builder filterBuilder = new ScanFilterConfig.Builder();
filterBuilder.setDeviceMac(mac); //Mac address you want to filter
filterBuilder.setDeviceName(name); //The deviceName you want to filter
filterBuilder.setServiceUUID(uuid); //The ServiceUuid you want to filter
scanFilterConfigs.add(filterBuilder.build());
ScanRuleConfig mScanRuleConfig = new ScanRuleConfig.Builder()
.setScanFilterConfigs(scanFilterConfigs) // Scan only the specified device, optional
.setScanMode(ScanRuleConfig.SCAN_MODE_BALANCED) // Scan mode, optional Default: low interval scan
.setScanDuration(6000) // Scan duration, optional
.setScanInterval(6000) // Scan interval, optional
.build();
//Start scanning
//The first parameter of startScan, indicating whether this is a single or periodic scan
CentralManager.getInstance().startScan(false, mScanRuleConfig, new ScanCallback() {
@Override
public void onScanStarted() {
//Processing start of scanning
}
@Override
public void onScanning(ScanDevice device) {
//Handling scanned new devices
}
@Override
public void onScanFinished(List<ScanDevice> scanResultList) {
//Scan completed, return to the list of scanned devices
}
});
//Stop scanning
CentralManager.getInstance().stopScan();
Mark: 1、The ScanInterval configuration is only relevant for periodic scans (CycledScanner) and does not work for a single scan of OnceScanner.
//Get the connection status of a Bluetooth device
CentralManager.getInstance()isBLEConnected(String macAddress);
//Get the connection status of a group of Bluetooth devices
CentralManager.getInstance()isBLEConnected(String[] macAddress);
Mark: Controlling the frequency of concurrent calls may cause ANR(Android internal Binder Method)
//Get the device group that has been paired and bound in the system settings
Set<BluetoothDevice> deviceSet = CentralManager.getInstance().getBondedDevices();
Peripheral peripheral = new Peripheral(scanDevice);
//isAutoConnect performs autoConnect connection,
// for which you can refer to the official Android documentation.
//
peripheral.connect(isAutoConnect, new ConnectStateCallback() {
@Override
public void onStartConnect() {
// Processing of connecting devices
}
@Override
public void onConnectFail(BLEException exception) {
// Connection failure processing
}
@Override
public void onConnectSuccess(Peripheral peripheral, int status) {
//Handling the connection successfully
}
@Override
public void onDisConnected(boolean isActiveDisConnected, Peripheral peripheral, int status) {
//Processing device disconnected
}
});
peripheral.disconnect() // Disconnect peripherals
Regarding the AutoConnect parameters, according to the interpretation of the Bluetooth core protocol, the following distinction can be made simply. This concurrency talks about the problem of the Bluetooth channel communication protocol level. AutoConnect=false Connection procedures cannot be concurrent. AutoConnect=true Connection procedures can be concurrent.
Example: The APP initialization is completed. It is known to connect to the Mac address of a device, obtain the peripheral through the CentralManager method, and then perform the autoConnect connection.
Peripheral peripheral = CentralManager.getInstance().retrievePeripheral(address);
peripheral.connect(true, new ConnectStateCallback(){
/*someCode*/
});
After the system is connected to the device, the ConnectStateCallback method is called back. Tips:The lower Android version connection completion time is slower, and the higher version will increase the connection speed.
Call the following method, Bluetooth operation will be executed immediately.
public void notify(String serviceUUID, String notifyUUID, NotifyCallback callback) {
/*someCode*/
});
public boolean stopNotify(String serviceUUID, String notifyUUID) {
/*someCode*/
});
public void indicate(String serviceUUID, String indicateUUID, IndicateCallback callback) {
/*someCode*/
});
public boolean stopIndicate(String serviceUUID, String indicateUUID) {
/*someCode*/
});
public void write(String serviceUUID, String writeUUID, byte[] data, WriteCallback callback) {
/*someCode*/
});
public void read(String serviceUUID, String readUUID, ReadCallback callback) {
/*someCode*/
});
public void readRssi(RssiCallback callback) {
/*someCode*/
});
public void setMtu(int mtu, MtuChangedCallback callback) {
/*someCode*/
});
Call the method, the operation supports priority and cache characteristics, and executes according to the set priority order. The cache instruction is determined according to whether all currently connected peripherals are busy, and execution is delayed.
public void notify(Command command) {
/*someCode*/
});
public void indicate(Command command) {
/*someCode*/
});
public void write(Command command) {
/*someCode*/
});
public void read(Command command) {
/*someCode*/
});
public void readRssi(Command command) {
/*someCode*/
});
public void setMtu(Command command) {
/*someCode*/
});
- Bug fixs
- Add getBoundDevices();
- Add Protocol Test Tool;
- Add isBLEConnected(String[]);
- Bug fixs
- Support AndroidX;
- Adapt to Android12;
- Bug fixs
- Improve scanner handle;
- Bug fixs
- Add Bluetooth command cache feature;
- Improve instruction concurrency stability;
- Increase the priority of instruction execution;
- Add exception type
- Bug fixs
- Bug fixs
- Bug fixs
- Remove scan config's background mode
- Init First Commit
-
Some APIs must be paired, used in order, if they do not appear in pairs, causing Crash, resource usage exceptions, and internal state exceptions. As a result, the device cannot be scanned and the device cannot be connected. In severe cases, the phone needs to be restarted before it can be restored.
startScan() & stopScan()
connectGatt() & close()
Tips: You can call disconnect() first, wait for the callback to be disconnected (onConnectionStateChange), and then execute close().
-
The BluetoothGatt class's read/write XXX set XXX and other APIs, when calling these methods, to determine the completion of the previous operation, and then execute the next call, while executing two, will cause the execution to fail.
-
BluetoothGatt method call, consider adding a retry operation, because the Android Bluetooth API is internally executed by mDeviceBusy for a limited time. If an execution error occurs, you can delay the attempt again.
-
The implementation of BluetoothGatt's readRemoteRssi method too frequently (such as a few hundred milliseconds) will cause DeadObjects to be abnormal.
-
For Android6.0 and above, you must authorize ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permission before calling startLeScan.Otherwise, the Android Bluetooth interface calls an exception that occurs directly inside the call and is not thrown. The phenomenon is to start scanning but does not return to the scanned device.
-
Call startLeScan and stopLeScan, make sure that Bluetooth is turned on, otherwise it will crash directly on some models.
-
Android8.1 and above to enable Bluetooth scanning, you must specify serviceUuid, or you will not be able to scan the device if you lock the screen.
-
Do not perform read, write, notify, etc. operations in callbacks such as onServicesDiscovered, and put them on the main thread to execute.