Flutter Blue Background allows you to implement Bluetooth Low Energy (BLE) functionality in the background for both Android and iOS platforms. This package is designed to facilitate BLE communication tasks, such as connecting to devices, reading from and writing to device, all while your Flutter application is running in the background.
- Integrate BLE (Bluetooth Low Energy) operations in the background smoothly with Flutter applications.
- Connect to BLE devices and perform read and write operations on characteristics.
- Supports both Android and iOS platforms.
- The functionality works on Android even when the app is fully terminated.
- On Android, direct data retrieval isn't possible after the application terminates. Therefore, data retrieval is facilitated through SharedPreferences.
flutter_blue_background is compatible with compileSdkVersion version 34 and minSdkVersion 21. Therefore, change this in android/app/build.gradle:
android {
compileSdkVersion 34
defaultConfig {
minSdkVersion: 21
Add the corresponding permissions, service, and receiver to your android/app/src/main/AndroidManifest.xml file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!--Add this Permissions-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_..." />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC"/>
<uses-feature android:name="android.hardware.bluetooth" android:required="true"/>
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.BLUETOOTH_SCAN"
android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
<uses-permission android:name="android.permission.BLUETOOTH_STACK" />
<uses-permission android:name="android.permission.BLUETOOTH_USE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<!--end-->
<application
android:label="flutter_blue_background_example"
android:name="${applicationName}"
android:icon="@mipmap/ic_launcher">
<activity
android:name=".MainActivity"
android:exported="true"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<!--Add this -->
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="FLUTTER_NOTIFICATION_CLICK"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<!--End this -->
</activity>
<!-- Do not delete the meta data below.This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<!--Add this -->
<service
android:name="com.dexterous.flutterlocalnotifications.ForegroundService"
android:exported="false"
android:stopWithTask="false"/>
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ActionBroadcastReceiver" />
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
<receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
</intent-filter>
</receiver>
<!--End this -->
</application>
</manifest>
WARNING:
- BEFORE STARTING THE SERVICE, MAKE SURE ALL REQUIRED PERMISSIONS ARE GRANTED.
- Utilize the permission_handler and location packages to obtain user permissions. In case you encounter any difficulties, you can refer to the example folder for assistance.
- The functionality is limited to working only when the iOS app is in minimized state.
- Service stops when the user terminates the app.
In the ios/Runner/Info.plist let’s add:
<dict>
<key>NSBluetoothAlwaysUsageDescription</key>
<string>App needs Bluetooth permission</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>Need BLE permission</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>App needs location permission</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>App needs location permission</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>App needs location permission</string>
<!-- Add other necessary keys and descriptions as per your application requirements -->
To start the background service for BLE operations, use the startFlutterBackgroundService
method. Provide a callback function inside it where you can execute your background tasks.
await FlutterBlueBackground.startFlutterBackgroundService(() {
// Your background tasks here
});
Use connectToDevice
method to connect to a BLE device in the background. Provide the device name, service UUID, and characteristic UUID to identify the specific device and characteristic.
await FlutterBlueBackground.connectToDevice(
deviceName: 'DeviceName',
serviceUuid: 'ServiceUUID',
characteristicUuid: 'CharacteristicUUID',
);
To read data from a characteristic, use readData
method. Provide the service UUID and characteristic UUID.
String? data = await FlutterBlueBackground.readData(
serviceUuid: 'ServiceUUID',
characteristicUuid: 'CharacteristicUUID',
);
await preferences.setStringList('getReadData', log);
In Android, to retrieve previously stored data when reopening the application, access the values from SharedPreferences as follows:
SharedPreferences preferences = await SharedPreferences.getInstance();
await preferences.reload();
// Retrieve the stored data from SharedPreferences
final log = preferences.getStringList('getReadData') ?? <String>[];
To write data to a characteristic, use writeData
method. Provide the service UUID, characteristic UUID, and the data to be written.
await FlutterBlueBackground.writeData(
serviceUuid: 'ServiceUUID',
characteristicUuid: 'CharacteristicUUID',
data: 'DataToWrite',
);
await FlutterBlueBackground.stopFlutterBackgroundService();
await FlutterBlueBackground.clearReadStorage();
await FlutterBlueBackground.startFlutterBackgroundService(() {
//
await FlutterBlueBackground.connectToDevice(
deviceName: 'DeviceName',
serviceUuid: 'ServiceUUID',
characteristicUuid: 'CharacteristicUUID',
);
// Write value on specific characteristic
await FlutterBlueBackground.writeData(
serviceUuid: 'ServiceUUID',
characteristicUuid: 'CharacteristicUUID',
data: 'DataToWrite',
);
// Read value
String? data = await FlutterBlueBackground.readData(
serviceUuid: 'ServiceUUID',
characteristicUuid: 'CharacteristicUUID',
);
print("Data in main is $data");
print("Executing function in the background");
});
If you encounter any issues or have suggestions for improvements, feel free to open an issue on GitHub. Contributions are also welcome through pull requests.
The MIT License
Copyright (c) Sparkleo Technologies https://www.sparkleo.io/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.