diff --git a/android/build.gradle b/android/build.gradle
index 082a0fea..5efe38d2 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -18,7 +18,7 @@ rootProject.allprojects {
}
apply plugin: 'com.android.library'
android {
- compileSdkVersion 30
+ compileSdkVersion 33
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index 3b5ff2f0..70f0eb8d 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -1,7 +1,12 @@
-
-
-
+
+
+
+
+
+
+
diff --git a/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java b/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java
index 0b9686b4..00dc300b 100644
--- a/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java
+++ b/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java
@@ -6,6 +6,7 @@
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
+import android.bluetooth.BluetoothClass;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -16,6 +17,7 @@
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
+import android.os.Build;
import android.util.Log;
import android.util.SparseArray;
import android.os.AsyncTask;
@@ -268,7 +270,7 @@ public void onReceive(Context context, Intent intent) {
switch (action) {
case BluetoothDevice.ACTION_FOUND:
final BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- //final BluetoothClass deviceClass = intent.getParcelableExtra(BluetoothDevice.EXTRA_CLASS); // @TODO . !BluetoothClass!
+ // final BluetoothClass deviceClass = intent.getParcelableExtra(BluetoothDevice.EXTRA_CLASS); // @TODO . !BluetoothClass!
//final String extraName = intent.getStringExtra(BluetoothDevice.EXTRA_NAME); // @TODO ? !EXTRA_NAME!
final int deviceRSSI = intent.getShortExtra(BluetoothDevice.EXTRA_RSSI, Short.MIN_VALUE);
@@ -276,12 +278,13 @@ public void onReceive(Context context, Intent intent) {
discoveryResult.put("address", device.getAddress());
discoveryResult.put("name", device.getName());
discoveryResult.put("type", device.getType());
- //discoveryResult.put("class", deviceClass); // @TODO . it isn't my priority for now !BluetoothClass!
+ // discoveryResult.put("class", deviceClass); // @TODO . it isn't my priority for now !BluetoothClass!
discoveryResult.put("isConnected", checkIsDeviceConnected(device));
discoveryResult.put("bondState", device.getBondState());
discoveryResult.put("rssi", deviceRSSI);
+ discoveryResult.put("deviceClass", device.getBluetoothClass().getDeviceClass());
- Log.d(TAG, "Discovered " + device.getAddress());
+ Log.d(TAG, "Discovered " + device.getAddress() + " (deviceClass: " + device.getBluetoothClass().getDeviceClass() + ")");
if (discoverySink != null) {
discoverySink.success(discoveryResult);
}
@@ -444,15 +447,35 @@ private interface EnsurePermissionsCallback {
EnsurePermissionsCallback pendingPermissionsEnsureCallbacks = null;
private void ensurePermissions(EnsurePermissionsCallback callbacks) {
- if (
+ boolean permissionGranted = (
ContextCompat.checkSelfPermission(activity,
Manifest.permission.ACCESS_COARSE_LOCATION)
- != PackageManager.PERMISSION_GRANTED
- || ContextCompat.checkSelfPermission(activity,
+ == PackageManager.PERMISSION_GRANTED
+ && ContextCompat.checkSelfPermission(activity,
Manifest.permission.ACCESS_FINE_LOCATION)
- != PackageManager.PERMISSION_GRANTED) {
+ == PackageManager.PERMISSION_GRANTED);
+
+ String[] requestString = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,
+ Manifest.permission.ACCESS_FINE_LOCATION};
+
+ Log.e(TAG,"request permission");
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
+ Log.e(TAG,"request scan permission");
+ permissionGranted = (
+ ContextCompat.checkSelfPermission(activity,
+ Manifest.permission.BLUETOOTH_SCAN)
+ == PackageManager.PERMISSION_GRANTED
+ && ContextCompat.checkSelfPermission(activity,
+ Manifest.permission.BLUETOOTH_CONNECT)
+ == PackageManager.PERMISSION_GRANTED);
+ requestString = new String[]{Manifest.permission.BLUETOOTH_SCAN,
+ Manifest.permission.BLUETOOTH_CONNECT};
+ }
+
+ if (!permissionGranted) {
ActivityCompat.requestPermissions(activity,
- new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
+ requestString,
REQUEST_COARSE_LOCATION_PERMISSIONS);
pendingPermissionsEnsureCallbacks = callbacks;
@@ -481,7 +504,6 @@ static private boolean checkIsDeviceConnected(BluetoothDevice device) {
}
}
-
/// Helper wrapper class for `BluetoothConnection`
private class BluetoothConnectionWrapper extends BluetoothConnection {
private final int id;
@@ -549,6 +571,7 @@ protected void onDisconnected(boolean byRemote) {
private class FlutterBluetoothSerialMethodCallHandler implements MethodCallHandler {
/// Provides access to the plugin methods
+ @SuppressLint("MissingPermission")
@Override
public void onMethodCall(MethodCall call, Result result) {
if (bluetoothAdapter == null) {
@@ -580,9 +603,16 @@ public void onMethodCall(MethodCall call, Result result) {
case "requestEnable":
if (!bluetoothAdapter.isEnabled()) {
- pendingResultForActivityResult = result;
- Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
- ActivityCompat.startActivityForResult(activity, intent, REQUEST_ENABLE_BLUETOOTH, null);
+ ensurePermissions(granted -> {
+ if (!granted) {
+ result.error("no_permissions", "Enabling bluetooth requires bluetooth permission", null);
+ return;
+ }
+
+ pendingResultForActivityResult = result;
+ Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
+ ActivityCompat.startActivityForResult(activity, intent, REQUEST_ENABLE_BLUETOOTH, null);
+ });
} else {
result.success(true);
}
@@ -590,8 +620,15 @@ public void onMethodCall(MethodCall call, Result result) {
case "requestDisable":
if (bluetoothAdapter.isEnabled()) {
+ ensurePermissions(granted -> {
+ if (!granted) {
+ result.error("no_permissions", "Enabling bluetooth requires bluetooth permission", null);
+ return;
+ }
+
bluetoothAdapter.disable();
result.success(true);
+ });
} else {
result.success(false);
}
@@ -606,7 +643,11 @@ public void onMethodCall(MethodCall call, Result result) {
break;
case "getAddress": {
- String address = bluetoothAdapter.getAddress();
+ String address = "02:00:00:00:00:00";
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
+ address = bluetoothAdapter.getAddress();
+ }
if (address.equals("02:00:00:00:00:00")) {
Log.w(TAG, "Local Bluetooth MAC address is hidden by system, trying other options...");
@@ -907,6 +948,8 @@ public void onReceive(Context context, Intent intent) {
entry.put("type", device.getType());
entry.put("isConnected", checkIsDeviceConnected(device));
entry.put("bondState", BluetoothDevice.BOND_BONDED);
+ entry.put("deviceClass", device.getBluetoothClass().getDeviceClass());
+ Log.d(TAG, "Discovered " + device.getAddress() + " (deviceClass: " + device.getBluetoothClass().getDeviceClass() + ")");
list.add(entry);
}
@@ -919,6 +962,7 @@ public void onReceive(Context context, Intent intent) {
break;
case "startDiscovery":
+ Log.d(TAG,"Starting discovery 22");
ensurePermissions(granted -> {
if (!granted) {
result.error("no_permissions", "discovering other devices requires location access permission", null);
@@ -1067,4 +1111,4 @@ public void onReceive(Context context, Intent intent) {
}
}
-}
+}
\ No newline at end of file
diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle
index 4b7eba10..944c38e3 100644
--- a/example/android/app/build.gradle
+++ b/example/android/app/build.gradle
@@ -15,7 +15,7 @@ apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
- compileSdkVersion 30
+ compileSdkVersion 33
lintOptions {
disable 'InvalidPackage'
}
@@ -23,7 +23,7 @@ android {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "io.github.edufolly.flutterbluetoothserialexample"
minSdkVersion 19
- targetSdkVersion 30
+ targetSdkVersion 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
index bae56f3b..c0a23034 100644
--- a/example/android/app/src/main/AndroidManifest.xml
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -21,6 +21,7 @@
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density"
android:hardwareAccelerated="true"
+ android:exported="true"
android:windowSoftInputMode="adjustResize">
diff --git a/example/android/build.gradle b/example/android/build.gradle
index c9e3db0a..cab8f601 100644
--- a/example/android/build.gradle
+++ b/example/android/build.gradle
@@ -24,6 +24,6 @@ subprojects {
project.evaluationDependsOn(':app')
}
-task clean(type: Delete) {
+tasks.register("clean", Delete) {
delete rootProject.buildDir
}
diff --git a/example/android/gradle.properties b/example/android/gradle.properties
index 53ae0ae4..d2964be7 100644
--- a/example/android/gradle.properties
+++ b/example/android/gradle.properties
@@ -1,3 +1,9 @@
-android.enableJetifier=true
+org.gradle.jvmargs=-Xmx1536M \
+--add-exports=java.base/sun.nio.ch=ALL-UNNAMED \
+--add-opens=java.base/java.lang=ALL-UNNAMED \
+--add-opens=java.base/java.lang.reflect=ALL-UNNAMED \
+--add-opens=java.base/java.io=ALL-UNNAMED \
+--add-exports=jdk.unsupported/sun.misc=ALL-UNNAMED
android.useAndroidX=true
-org.gradle.jvmargs=-Xmx1536M
+android.enableJetifier=true
+android.enableR8=true
\ No newline at end of file
diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties
index c732f9e0..7c8bab40 100644
--- a/example/android/gradle/wrapper/gradle-wrapper.properties
+++ b/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
diff --git a/example/lib/BluetoothDeviceListEntry.dart b/example/lib/BluetoothDeviceListEntry.dart
index a94afc07..9cb19004 100644
--- a/example/lib/BluetoothDeviceListEntry.dart
+++ b/example/lib/BluetoothDeviceListEntry.dart
@@ -12,8 +12,7 @@ class BluetoothDeviceListEntry extends ListTile {
onTap: onTap,
onLongPress: onLongPress,
enabled: enabled,
- leading:
- Icon(Icons.devices), // @TODO . !BluetoothClass! class aware icon
+ leading: Icon(getIcon(device.deviceClass)), // @TODO . !BluetoothClass! class aware icon
title: Text(device.name ?? ""),
subtitle: Text(device.address.toString()),
trailing: Row(
@@ -44,6 +43,29 @@ class BluetoothDeviceListEntry extends ListTile {
),
);
+ static IconData getIcon(BluetoothDeviceClass deviceClass) {
+ switch (deviceClass) {
+ case BluetoothDeviceClass.PERIPHERAL_KEYBOARD:
+ return Icons.keyboard;
+ case BluetoothDeviceClass.AUDIO_VIDEO_WEARABLE_HEADSET:
+ return Icons.headphones;
+ case BluetoothDeviceClass.AUDIO_VIDEO_HEADPHONES:
+ return Icons.headphones;
+ case BluetoothDeviceClass.AUDIO_VIDEO_HANDSFREE:
+ return Icons.headphones;
+ case BluetoothDeviceClass.AUDIO_VIDEO_LOUDSPEAKER:
+ return Icons.speaker;
+ case BluetoothDeviceClass.PHONE_SMART:
+ return Icons.smartphone;
+ case BluetoothDeviceClass.COMPUTER_DESKTOP:
+ return Icons.computer;
+ case BluetoothDeviceClass.COMPUTER_LAPTOP:
+ return Icons.laptop;
+ default:
+ return Icons.devices;
+ }
+ }
+
static TextStyle _computeTextStyle(int rssi) {
/**/ if (rssi >= -35)
return TextStyle(color: Colors.greenAccent[700]);
diff --git a/example/lib/SelectBondedDevicePage.dart b/example/lib/SelectBondedDevicePage.dart
index 7acb033c..5ccbcf6d 100644
--- a/example/lib/SelectBondedDevicePage.dart
+++ b/example/lib/SelectBondedDevicePage.dart
@@ -17,7 +17,6 @@ class SelectBondedDevicePage extends StatefulWidget {
}
enum _DeviceAvailability {
- no,
maybe,
yes,
}
@@ -27,7 +26,7 @@ class _DeviceWithAvailability {
_DeviceAvailability availability;
int? rssi;
- _DeviceWithAvailability(this.device, this.availability, [this.rssi]);
+ _DeviceWithAvailability(this.device, this.availability);
}
class _SelectBondedDevicePage extends State {
diff --git a/example/lib/helpers/LineChart.dart b/example/lib/helpers/LineChart.dart
index a81bf0dd..8ca30fde 100644
--- a/example/lib/helpers/LineChart.dart
+++ b/example/lib/helpers/LineChart.dart
@@ -162,9 +162,9 @@ class LineChart extends StatelessWidget {
values: values,
valuesLabels: valuesLabels,
horizontalLabelsTextStyle:
- horizontalLabelsTextStyle ?? Theme.of(context).textTheme.caption,
+ horizontalLabelsTextStyle ?? Theme.of(context).textTheme.bodySmall,
verticalLabelsTextStyle:
- verticalLabelsTextStyle ?? Theme.of(context).textTheme.caption,
+ verticalLabelsTextStyle ?? Theme.of(context).textTheme.bodySmall,
horizontalLinesPaint: horizontalLinesPaint,
verticalLinesPaint: verticalLinesPaint,
additionalMinimalHorizontalLabelsInterval:
@@ -510,7 +510,7 @@ class _LineChartPainter extends CustomPainter {
Iterator argument = arguments.iterator;
while (value.moveNext()) {
argument.moveNext();
- if (value.current == null || value.current == double.nan) continue;
+ if (value.current == null) continue;
if (argument.current < argumentsOffset) continue;
final double xOffset = padding.left +
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index 9c0ab0ce..9074c8d4 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -1,8 +1,6 @@
name: flutter_bluetooth_serial_example
version: 0.4.0
description: Demonstrates how to use the `flutter_bluetooth_serial` plugin.
-authors:
- - Patryk Ludwikowski
homepage: https://github.com/edufolly/flutter_bluetooth_serial/tree/master/example/
environment:
diff --git a/lib/BluetoothConnection.dart b/lib/BluetoothConnection.dart
index 5ffffb25..82a77281 100644
--- a/lib/BluetoothConnection.dart
+++ b/lib/BluetoothConnection.dart
@@ -17,6 +17,7 @@ class BluetoothConnection {
//
/// This ID identifies real full `BluetoothConenction` object on platform side code.
+ // ignore: unused_field
final int? _id;
final EventChannel _readChannel;
diff --git a/lib/BluetoothDevice.dart b/lib/BluetoothDevice.dart
index 5c6e527d..339b7333 100644
--- a/lib/BluetoothDevice.dart
+++ b/lib/BluetoothDevice.dart
@@ -12,7 +12,7 @@ class BluetoothDevice {
final BluetoothDeviceType type;
/// Class of the device.
- //final BluetoothClass bluetoothClass // @TODO . !BluetoothClass!
+ //final category category // @TODO . !category!
/// Describes is device connected.
final bool isConnected;
@@ -20,6 +20,9 @@ class BluetoothDevice {
/// Bonding state of the device.
final BluetoothBondState bondState;
+ /// Broadcasted friendly clas of the device.
+ final BluetoothDeviceClass deviceClass;
+
/// Tells whether the device is bonded (ready to secure connect).
@Deprecated('Use `isBonded` instead')
bool get bonded => bondState.isBonded;
@@ -34,6 +37,7 @@ class BluetoothDevice {
this.type = BluetoothDeviceType.unknown,
this.isConnected = false,
this.bondState = BluetoothBondState.unknown,
+ this.deviceClass = BluetoothDeviceClass.UNCATEGORIZED,
});
/// Creates `BluetoothDevice` from map.
@@ -41,16 +45,18 @@ class BluetoothDevice {
/// Internally used to receive the object from platform code.
factory BluetoothDevice.fromMap(Map map) {
return BluetoothDevice(
- name: map["name"],
- address: map["address"]!,
- type: map["type"] != null
- ? BluetoothDeviceType.fromUnderlyingValue(map["type"])
- : BluetoothDeviceType.unknown,
- isConnected: map["isConnected"] ?? false,
- bondState: map["bondState"] != null
- ? BluetoothBondState.fromUnderlyingValue(map["bondState"])
- : BluetoothBondState.unknown,
- );
+ name: map["name"],
+ address: map["address"]!,
+ type: map["type"] != null
+ ? BluetoothDeviceType.fromUnderlyingValue(map["type"])
+ : BluetoothDeviceType.unknown,
+ isConnected: map["isConnected"] ?? false,
+ bondState: map["bondState"] != null
+ ? BluetoothBondState.fromUnderlyingValue(map["bondState"])
+ : BluetoothBondState.unknown,
+ deviceClass: map["deviceClass"] != null
+ ? (map['deviceClass'] as int).getBluetoothDeviceClassFromValue
+ : BluetoothDeviceClass.UNCATEGORIZED);
}
/// Creates map from `BluetoothDevice`.
@@ -60,6 +66,7 @@ class BluetoothDevice {
"type": this.type.toUnderlyingValue(),
"isConnected": this.isConnected,
"bondState": this.bondState.toUnderlyingValue(),
+ 'deviceClass': this.deviceClass.value,
};
/// Compares for equality of this and other `BluetoothDevice`.
diff --git a/lib/BluetoothDeviceClass.dart b/lib/BluetoothDeviceClass.dart
new file mode 100644
index 00000000..c6a57e91
--- /dev/null
+++ b/lib/BluetoothDeviceClass.dart
@@ -0,0 +1,99 @@
+part of flutter_bluetooth_serial;
+
+enum BluetoothDeviceClass {
+ // Audio and Video Devices
+ AUDIO_VIDEO_CAMCORDER(1076),
+ AUDIO_VIDEO_CAR_AUDIO(1056),
+ AUDIO_VIDEO_HANDSFREE(1032),
+ AUDIO_VIDEO_HEADPHONES(1048),
+ AUDIO_VIDEO_HIFI_AUDIO(1064),
+ AUDIO_VIDEO_LOUDSPEAKER(1044),
+ AUDIO_VIDEO_MICROPHONE(1040),
+ AUDIO_VIDEO_PORTABLE_AUDIO(1052),
+ AUDIO_VIDEO_SET_TOP_BOX(1060),
+ AUDIO_VIDEO_UNCATEGORIZED(1024),
+ AUDIO_VIDEO_VCR(1068),
+ AUDIO_VIDEO_VIDEO_CAMERA(1072),
+ AUDIO_VIDEO_VIDEO_CONFERENCING(1088),
+ AUDIO_VIDEO_VIDEO_DISPLAY_AND_LOUDSPEAKER(1084),
+ AUDIO_VIDEO_VIDEO_GAMING_TOY(1096),
+ AUDIO_VIDEO_VIDEO_MONITOR(1080),
+ AUDIO_VIDEO_WEARABLE_HEADSET(1028),
+
+ // Computer Devices
+ COMPUTER_DESKTOP(260),
+ COMPUTER_HANDHELD_PC_PDA(272),
+ COMPUTER_LAPTOP(268),
+ COMPUTER_PALM_SIZE_PC_PDA(276),
+ COMPUTER_SERVER(264),
+ COMPUTER_UNCATEGORIZED(256),
+ COMPUTER_WEARABLE(280),
+
+ // Health Devices
+ HEALTH_BLOOD_PRESSURE(2308),
+ HEALTH_DATA_DISPLAY(2332),
+ HEALTH_GLUCOSE(2320),
+ HEALTH_PULSE_OXIMETER(2324),
+ HEALTH_PULSE_RATE(2328),
+ HEALTH_THERMOMETER(2312),
+ HEALTH_UNCATEGORIZED(2304),
+ HEALTH_WEIGHING(2316),
+
+ // Peripheral Devices
+ PERIPHERAL_KEYBOARD(1344),
+ PERIPHERAL_KEYBOARD_POINTING(1472),
+ PERIPHERAL_NON_KEYBOARD_NON_POINTING(1280),
+ PERIPHERAL_POINTING(1408),
+
+ // Phone Devices
+ PHONE_CELLULAR(516),
+ PHONE_CORDLESS(520),
+ PHONE_ISDN(532),
+ PHONE_MODEM_OR_GATEWAY(528),
+ PHONE_SMART(524),
+ PHONE_UNCATEGORIZED(512),
+
+ // Toy Devices
+ TOY_CONTROLLER(2064),
+ TOY_DOLL_ACTION_FIGURE(2060),
+ TOY_GAME(2068),
+ TOY_ROBOT(2052),
+ TOY_UNCATEGORIZED(2048),
+ TOY_VEHICLE(2056),
+
+ // Wearable Devices
+ WEARABLE_GLASSES(1812),
+ WEARABLE_HELMET(1808),
+ WEARABLE_JACKET(1804),
+ WEARABLE_PAGER(1800),
+ WEARABLE_UNCATEGORIZED(1792),
+ WEARABLE_WRIST_WATCH(1796),
+
+ // Major Class Devices
+ IMAGING(1536),
+ MISC(0),
+ UNCATEGORIZED(7936),
+ NETWORKING(768);
+
+ const BluetoothDeviceClass(this.value);
+
+ final int value;
+}
+
+extension BluetoothDeviceClassEnum on int {
+ BluetoothDeviceClass get getBluetoothDeviceClassFromValue {
+ for (BluetoothDeviceClass enumValue in BluetoothDeviceClass.values) {
+ if (enumValue.value == this) {
+ return enumValue;
+ }
+ }
+ // Handle the case where the integer value doesn't match any enum value.
+ // Default value or handle as needed.
+ return BluetoothDeviceClass.UNCATEGORIZED;
+ }
+}
+
+extension BluetoothDeviceClassName on BluetoothDeviceClass {
+ // Get readable name of the bluetooth class
+ String get name => this.toString().replaceAll('BluetoothDeviceClass.', '');
+}
diff --git a/lib/flutter_bluetooth_serial.dart b/lib/flutter_bluetooth_serial.dart
index d3eefdc5..1c84cab3 100644
--- a/lib/flutter_bluetooth_serial.dart
+++ b/lib/flutter_bluetooth_serial.dart
@@ -1,7 +1,6 @@
library flutter_bluetooth_serial;
import 'dart:async';
-import 'dart:typed_data';
import 'dart:convert';
import 'package:flutter/services.dart';
@@ -14,3 +13,4 @@ part './BluetoothPairingRequest.dart';
part './BluetoothDiscoveryResult.dart';
part './BluetoothConnection.dart';
part './FlutterBluetoothSerial.dart';
+part './BluetoothDeviceClass.dart';
diff --git a/pubspec.yaml b/pubspec.yaml
index 5d0a7195..2790fd80 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,12 +1,12 @@
name: flutter_bluetooth_serial
-version: 0.4.0
+version: 0.4.1
description: Flutter basic implementation for Classical Bluetooth (only RFCOMM for now).
homepage: https://github.com/edufolly/flutter_bluetooth_serial
repository: https://github.com/edufolly/flutter_bluetooth_serial
issue_tracker: https://github.com/edufolly/flutter_bluetooth_serial/issues
environment:
- sdk: '>=2.12.0 <3.0.0'
+ sdk: '>=2.17.0 <3.0.0'
flutter: ">=1.17.0"
dependencies: