From 1b249accbffd817fc3749714ffdca216fcedb301 Mon Sep 17 00:00:00 2001 From: miladev2022 Date: Wed, 26 Jul 2023 13:10:13 +0330 Subject: [PATCH 01/14] support android 12 --- android/build.gradle | 2 +- android/src/main/AndroidManifest.xml | 10 +++- .../FlutterBluetoothSerialPlugin.java | 57 +++++++++++++++---- example/android/app/build.gradle | 6 +- pubspec.yaml | 2 +- 5 files changed, 59 insertions(+), 18 deletions(-) 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..ab6dbe54 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,7 +1,11 @@ - - - + + + + + + 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..3900d921 100644 --- a/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java +++ b/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java @@ -16,6 +16,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; @@ -444,15 +445,32 @@ 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}; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + 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; @@ -549,6 +567,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 +599,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 +616,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 +639,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..."); @@ -1067,4 +1104,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..7209e62a 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" @@ -35,7 +35,7 @@ android { signingConfig signingConfigs.debug } } - buildToolsVersion '30.0.3' + buildToolsVersion '33.0.3' compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 diff --git a/pubspec.yaml b/pubspec.yaml index 5d0a7195..b5dd65b1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,5 +1,5 @@ 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 From da930912c6b53c9a036cf26034e9734a33ef772b Mon Sep 17 00:00:00 2001 From: miladev2022 Date: Wed, 26 Jul 2023 14:02:00 +0330 Subject: [PATCH 02/14] change bluetooth permission --- android/src/main/AndroidManifest.xml | 5 +++-- .../flutterbluetoothserial/FlutterBluetoothSerialPlugin.java | 3 +++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml index ab6dbe54..70f0eb8d 100644 --- a/android/src/main/AndroidManifest.xml +++ b/android/src/main/AndroidManifest.xml @@ -1,11 +1,12 @@ + android:targetSdkVersion="33" /> - + + 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 3900d921..6b76499b 100644 --- a/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java +++ b/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java @@ -456,7 +456,10 @@ private void ensurePermissions(EnsurePermissionsCallback callbacks) { String[] requestString = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}; + Log.e("TAG22","22222222222222222"); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + Log.e("TAG22","1111111111111111111111111111"); permissionGranted = ( ContextCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH_SCAN) From fbe9f76f813ac48ac70d4fb6b3ddd68657705ec6 Mon Sep 17 00:00:00 2001 From: miladev2022 Date: Wed, 26 Jul 2023 14:14:24 +0330 Subject: [PATCH 03/14] add logs --- .../flutterbluetoothserial/FlutterBluetoothSerialPlugin.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 6b76499b..8aa36fe4 100644 --- a/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java +++ b/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java @@ -456,10 +456,10 @@ private void ensurePermissions(EnsurePermissionsCallback callbacks) { String[] requestString = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}; - Log.e("TAG22","22222222222222222"); + Log.e(TAG,"request permission"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { - Log.e("TAG22","1111111111111111111111111111"); + Log.e(TAG,"request scan permission"); permissionGranted = ( ContextCompat.checkSelfPermission(activity, Manifest.permission.BLUETOOTH_SCAN) @@ -959,6 +959,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); From 92d5d6a05f7dd1e9a3b8e9e1addeb0ed74cbce96 Mon Sep 17 00:00:00 2001 From: Tegar Date: Mon, 18 Sep 2023 13:53:50 +0700 Subject: [PATCH 04/14] add result bluetooth device class --- .../FlutterBluetoothSerialPlugin.java | 8 +++++--- lib/BluetoothDevice.dart | 6 ++++++ 2 files changed, 11 insertions(+), 3 deletions(-) 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 3900d921..5d4624c3 100644 --- a/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java +++ b/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java @@ -269,7 +269,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); @@ -277,12 +277,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("bluetoothClass", device.getBluetoothClass()); - Log.d(TAG, "Discovered " + device.getAddress()); + Log.d(TAG, "Discovered " + device.getAddress() + " (bluetoothClass: " + device.getBluetoothClass() + ")"); if (discoverySink != null) { discoverySink.success(discoveryResult); } @@ -944,6 +945,7 @@ 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("bluetoothClass", device.getBluetoothClass()); list.add(entry); } diff --git a/lib/BluetoothDevice.dart b/lib/BluetoothDevice.dart index 5c6e527d..d9e40e18 100644 --- a/lib/BluetoothDevice.dart +++ b/lib/BluetoothDevice.dart @@ -20,6 +20,9 @@ class BluetoothDevice { /// Bonding state of the device. final BluetoothBondState bondState; + /// Broadcasted friendly clas of the device. + final String? bluetoothClass; + /// 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.bluetoothClass, }); /// Creates `BluetoothDevice` from map. @@ -50,6 +54,7 @@ class BluetoothDevice { bondState: map["bondState"] != null ? BluetoothBondState.fromUnderlyingValue(map["bondState"]) : BluetoothBondState.unknown, + bluetoothClass: map['bluetoothClass'] ); } @@ -60,6 +65,7 @@ class BluetoothDevice { "type": this.type.toUnderlyingValue(), "isConnected": this.isConnected, "bondState": this.bondState.toUnderlyingValue(), + 'bluetoothClass': this.bluetoothClass, }; /// Compares for equality of this and other `BluetoothDevice`. From 426d07f0b9a43f840c52704c932cb8f95e866635 Mon Sep 17 00:00:00 2001 From: Tegar Date: Mon, 18 Sep 2023 14:22:03 +0700 Subject: [PATCH 05/14] Remove device class --- .../FlutterBluetoothSerialPlugin.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 5d4624c3..22ef0cb9 100644 --- a/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java +++ b/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java @@ -269,7 +269,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); @@ -277,8 +277,8 @@ 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("isConnected", checkIsDeviceConnected(device)); + // 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("bluetoothClass", device.getBluetoothClass()); From 655676ba5bcccaea75f2e11e7253aa92039c823f Mon Sep 17 00:00:00 2001 From: Tegar Date: Mon, 18 Sep 2023 14:26:34 +0700 Subject: [PATCH 06/14] remove unused string --- .../flutterbluetoothserial/FlutterBluetoothSerialPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 22ef0cb9..261210f0 100644 --- a/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java +++ b/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java @@ -278,7 +278,7 @@ public void onReceive(Context context, Intent intent) { 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("isConnected"`, checkIsDeviceConnected(device)); + discoveryResult.put("isConnected", checkIsDeviceConnected(device)); discoveryResult.put("bondState", device.getBondState()); discoveryResult.put("rssi", deviceRSSI); discoveryResult.put("bluetoothClass", device.getBluetoothClass()); From d5083e986743b95cb0961823b8f3a7f1e24218a1 Mon Sep 17 00:00:00 2001 From: Tegar Date: Mon, 18 Sep 2023 14:32:50 +0700 Subject: [PATCH 07/14] convert result device.getBluetoothClass().getDeviceClass() to string --- .../flutterbluetoothserial/FlutterBluetoothSerialPlugin.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 261210f0..82115f9c 100644 --- a/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java +++ b/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java @@ -281,9 +281,9 @@ public void onReceive(Context context, Intent intent) { discoveryResult.put("isConnected", checkIsDeviceConnected(device)); discoveryResult.put("bondState", device.getBondState()); discoveryResult.put("rssi", deviceRSSI); - discoveryResult.put("bluetoothClass", device.getBluetoothClass()); + discoveryResult.put("bluetoothClass", device.getBluetoothClass().getDeviceClass().toString()); - Log.d(TAG, "Discovered " + device.getAddress() + " (bluetoothClass: " + device.getBluetoothClass() + ")"); + Log.d(TAG, "Discovered " + device.getAddress() + " (bluetoothClass: " + device.getBluetoothClass().getDeviceClass().toString() + ")"); if (discoverySink != null) { discoverySink.success(discoveryResult); } From c87b4c39b043bf70e45142906ba6dfd804811b40 Mon Sep 17 00:00:00 2001 From: Tegar Date: Mon, 18 Sep 2023 14:48:34 +0700 Subject: [PATCH 08/14] Change bluetooth class to integer --- .../flutterbluetoothserial/FlutterBluetoothSerialPlugin.java | 4 ++-- lib/BluetoothDevice.dart | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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 82115f9c..c3298f4f 100644 --- a/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java +++ b/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java @@ -281,9 +281,9 @@ public void onReceive(Context context, Intent intent) { discoveryResult.put("isConnected", checkIsDeviceConnected(device)); discoveryResult.put("bondState", device.getBondState()); discoveryResult.put("rssi", deviceRSSI); - discoveryResult.put("bluetoothClass", device.getBluetoothClass().getDeviceClass().toString()); + discoveryResult.put("bluetoothClass", device.getBluetoothClass().getDeviceClass()); - Log.d(TAG, "Discovered " + device.getAddress() + " (bluetoothClass: " + device.getBluetoothClass().getDeviceClass().toString() + ")"); + Log.d(TAG, "Discovered " + device.getAddress() + " (bluetoothClass: " + device.getBluetoothClass().getDeviceClass() + ")"); if (discoverySink != null) { discoverySink.success(discoveryResult); } diff --git a/lib/BluetoothDevice.dart b/lib/BluetoothDevice.dart index d9e40e18..804c7490 100644 --- a/lib/BluetoothDevice.dart +++ b/lib/BluetoothDevice.dart @@ -21,7 +21,7 @@ class BluetoothDevice { final BluetoothBondState bondState; /// Broadcasted friendly clas of the device. - final String? bluetoothClass; + final int? bluetoothClass; /// Tells whether the device is bonded (ready to secure connect). @Deprecated('Use `isBonded` instead') From 91f551ee4b2d51d07e587eba9b6387d4a195a1c0 Mon Sep 17 00:00:00 2001 From: Tegar Date: Mon, 18 Sep 2023 15:59:06 +0700 Subject: [PATCH 09/14] Fix getDeviceClass in getBondedDevices --- .../FlutterBluetoothSerialPlugin.java | 3 ++- example/android/app/build.gradle | 2 +- example/android/app/src/main/AndroidManifest.xml | 1 + example/android/build.gradle | 2 +- example/android/gradle.properties | 10 ++++++++-- .../android/gradle/wrapper/gradle-wrapper.properties | 2 +- 6 files changed, 14 insertions(+), 6 deletions(-) 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 c3298f4f..4ccf728f 100644 --- a/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java +++ b/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java @@ -945,7 +945,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("bluetoothClass", device.getBluetoothClass()); + entry.put("bluetoothClass", device.getBluetoothClass().getDeviceClass()); + Log.d(TAG, "Discovered " + device.getAddress() + " (bluetoothClass: " + device.getBluetoothClass().getDeviceClass() + ")"); list.add(entry); } diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle index 7209e62a..944c38e3 100644 --- a/example/android/app/build.gradle +++ b/example/android/app/build.gradle @@ -35,7 +35,7 @@ android { signingConfig signingConfigs.debug } } - buildToolsVersion '33.0.3' + buildToolsVersion '30.0.3' compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 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 From 0809569699bb18c16b5aabd0d0a27d47442b790d Mon Sep 17 00:00:00 2001 From: Tegar Date: Mon, 18 Sep 2023 16:29:29 +0700 Subject: [PATCH 10/14] Add support get bluetooth category --- .../FlutterBluetoothSerialPlugin.java | 39 +++++++++- lib/BluetoothDevice.dart | 10 +-- lib/BluetoothDeviceCategory.dart | 78 +++++++++++++++++++ lib/flutter_bluetooth_serial.dart | 1 + 4 files changed, 119 insertions(+), 9 deletions(-) create mode 100644 lib/BluetoothDeviceCategory.dart 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 4ccf728f..b383a5d0 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; @@ -281,9 +282,9 @@ public void onReceive(Context context, Intent intent) { discoveryResult.put("isConnected", checkIsDeviceConnected(device)); discoveryResult.put("bondState", device.getBondState()); discoveryResult.put("rssi", deviceRSSI); - discoveryResult.put("bluetoothClass", device.getBluetoothClass().getDeviceClass()); + discoveryResult.put("category", convertDeviceClass(device.getBluetoothClass().getDeviceClass())); - Log.d(TAG, "Discovered " + device.getAddress() + " (bluetoothClass: " + device.getBluetoothClass().getDeviceClass() + ")"); + Log.d(TAG, "Discovered " + device.getAddress() + " (category: " + convertDeviceClass(device.getBluetoothClass().getDeviceClass()) + ")"); if (discoverySink != null) { discoverySink.success(discoveryResult); } @@ -500,6 +501,36 @@ static private boolean checkIsDeviceConnected(BluetoothDevice device) { } } + static private String convertDeviceClass(int deviceClassInt) { + int majorDeviceClass = deviceClassInt & 0x1F00; // Mask to extract major device class + switch (majorDeviceClass) { + case BluetoothClass.Device.Major.MISC: + return "MISC"; + case BluetoothClass.Device.Major.COMPUTER: + return "COMPUTER"; + case BluetoothClass.Device.Major.PHONE: + return "PHONE"; + case BluetoothClass.Device.Major.NETWORKING: + return "NETWORKING"; + case BluetoothClass.Device.Major.AUDIO_VIDEO: + return "AUDIO_VIDEO"; + case BluetoothClass.Device.Major.PERIPHERAL: + return "PERIPHERAL"; + case BluetoothClass.Device.Major.IMAGING: + return "IMAGING"; + case BluetoothClass.Device.Major.WEARABLE: + return "WEARABLE"; + case BluetoothClass.Device.Major.TOY: + return "TOY"; + case BluetoothClass.Device.Major.HEALTH: + return "HEALTH"; + case BluetoothClass.Device.Major.UNCATEGORIZED: + return "UNCATEGORIZED"; + default: + return "UNKNOWN"; + } + } + /// Helper wrapper class for `BluetoothConnection` private class BluetoothConnectionWrapper extends BluetoothConnection { @@ -945,8 +976,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("bluetoothClass", device.getBluetoothClass().getDeviceClass()); - Log.d(TAG, "Discovered " + device.getAddress() + " (bluetoothClass: " + device.getBluetoothClass().getDeviceClass() + ")"); + entry.put("category", convertDeviceClass(device.getBluetoothClass().getDeviceClass())); + Log.d(TAG, "Discovered " + device.getAddress() + " (category: " + convertDeviceClass(device.getBluetoothClass().getDeviceClass()) + ")"); list.add(entry); } diff --git a/lib/BluetoothDevice.dart b/lib/BluetoothDevice.dart index 804c7490..a5e981ff 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; @@ -21,7 +21,7 @@ class BluetoothDevice { final BluetoothBondState bondState; /// Broadcasted friendly clas of the device. - final int? bluetoothClass; + final BluetoothDeviceCategory category; /// Tells whether the device is bonded (ready to secure connect). @Deprecated('Use `isBonded` instead') @@ -37,7 +37,7 @@ class BluetoothDevice { this.type = BluetoothDeviceType.unknown, this.isConnected = false, this.bondState = BluetoothBondState.unknown, - this.bluetoothClass, + this.category = BluetoothDeviceCategory.UNKNOWN, }); /// Creates `BluetoothDevice` from map. @@ -54,7 +54,7 @@ class BluetoothDevice { bondState: map["bondState"] != null ? BluetoothBondState.fromUnderlyingValue(map["bondState"]) : BluetoothBondState.unknown, - bluetoothClass: map['bluetoothClass'] + category: mapStringToDeviceCategory(map['category']) ); } @@ -65,7 +65,7 @@ class BluetoothDevice { "type": this.type.toUnderlyingValue(), "isConnected": this.isConnected, "bondState": this.bondState.toUnderlyingValue(), - 'bluetoothClass': this.bluetoothClass, + 'category': mapDeviceCategoryToString(this.category), }; /// Compares for equality of this and other `BluetoothDevice`. diff --git a/lib/BluetoothDeviceCategory.dart b/lib/BluetoothDeviceCategory.dart new file mode 100644 index 00000000..8dff58cc --- /dev/null +++ b/lib/BluetoothDeviceCategory.dart @@ -0,0 +1,78 @@ +part of flutter_bluetooth_serial; + +enum BluetoothDeviceCategory { + MISC, + COMPUTER, + PHONE, + NETWORKING, + AUDIO_VIDEO, + PERIPHERAL, + IMAGING, + WEARABLE, + TOY, + HEALTH, + UNCATEGORIZED, + UNKNOWN, +} + +BluetoothDeviceCategory mapStringToDeviceCategory(String deviceCategoryString) { + switch (deviceCategoryString) { + case "MISC": + return BluetoothDeviceCategory.MISC; + case "COMPUTER": + return BluetoothDeviceCategory.COMPUTER; + case "PHONE": + return BluetoothDeviceCategory.PHONE; + case "NETWORKING": + return BluetoothDeviceCategory.NETWORKING; + case "AUDIO_VIDEO": + return BluetoothDeviceCategory.AUDIO_VIDEO; + case "PERIPHERAL": + return BluetoothDeviceCategory.PERIPHERAL; + case "IMAGING": + return BluetoothDeviceCategory.IMAGING; + case "WEARABLE": + return BluetoothDeviceCategory.WEARABLE; + case "TOY": + return BluetoothDeviceCategory.TOY; + case "HEALTH": + return BluetoothDeviceCategory.HEALTH; + case "UNCATEGORIZED": + return BluetoothDeviceCategory.UNCATEGORIZED; + default: + return BluetoothDeviceCategory.UNKNOWN; + } +} + +String mapDeviceCategoryToString(BluetoothDeviceCategory category) { + switch (category) { + case BluetoothDeviceCategory.MISC: + return "MISC"; + case BluetoothDeviceCategory.COMPUTER: + return "COMPUTER"; + case BluetoothDeviceCategory.PHONE: + return "PHONE"; + case BluetoothDeviceCategory.NETWORKING: + return "NETWORKING"; + case BluetoothDeviceCategory.AUDIO_VIDEO: + return "AUDIO_VIDEO"; + case BluetoothDeviceCategory.PERIPHERAL: + return "PERIPHERAL"; + case BluetoothDeviceCategory.IMAGING: + return "IMAGING"; + case BluetoothDeviceCategory.WEARABLE: + return "WEARABLE"; + case BluetoothDeviceCategory.TOY: + return "TOY"; + case BluetoothDeviceCategory.HEALTH: + return "HEALTH"; + case BluetoothDeviceCategory.UNCATEGORIZED: + return "UNCATEGORIZED"; + default: + return "UNKNOWN"; + } +} + +extension BuildContextExtension on BluetoothDeviceCategory { + String get toStringValue => mapDeviceCategoryToString(this); +} diff --git a/lib/flutter_bluetooth_serial.dart b/lib/flutter_bluetooth_serial.dart index d3eefdc5..d3299dc5 100644 --- a/lib/flutter_bluetooth_serial.dart +++ b/lib/flutter_bluetooth_serial.dart @@ -14,3 +14,4 @@ part './BluetoothPairingRequest.dart'; part './BluetoothDiscoveryResult.dart'; part './BluetoothConnection.dart'; part './FlutterBluetoothSerial.dart'; +part './BluetoothDeviceCategory.dart'; From 16e31e9ffafa010f532aa4fc1fea7a17777cb315 Mon Sep 17 00:00:00 2001 From: Tegar Date: Mon, 18 Sep 2023 17:12:12 +0700 Subject: [PATCH 11/14] Separate categories for peripheral --- .../FlutterBluetoothSerialPlugin.java | 15 +++++++++++++- example/pubspec.yaml | 2 -- lib/BluetoothDeviceCategory.dart | 20 +++++++++++++++++++ lib/flutter_bluetooth_serial.dart | 1 - 4 files changed, 34 insertions(+), 4 deletions(-) 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 b383a5d0..2de3e0de 100644 --- a/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java +++ b/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java @@ -515,7 +515,20 @@ static private String convertDeviceClass(int deviceClassInt) { case BluetoothClass.Device.Major.AUDIO_VIDEO: return "AUDIO_VIDEO"; case BluetoothClass.Device.Major.PERIPHERAL: - return "PERIPHERAL"; + // Separate categories for barcode scanners, keyboards, and mice within "PERIPHERAL" + int minorDeviceClass = deviceClassInt & 0xFF; + switch (minorDeviceClass) { + case BluetoothClass.Device.PERIPHERAL_KEYBOARD: + return "PERIPHERAL_KEYBOARD"; + case BluetoothClass.Device.PERIPHERAL_POINTING: + return "PERIPHERAL_POINTING"; + case BluetoothClass.Device.PERIPHERAL_KEYBOARD_POINTING: + return "PERIPHERAL_KEYBOARD_POINTING"; + case BluetoothClass.Device.PERIPHERAL_NON_KEYBOARD_NON_POINTING: + return "PERIPHERAL_NON_KEYBOARD_NON_POINTING"; + default: + return "PERIPHERAL (UNKNOWN)"; + } case BluetoothClass.Device.Major.IMAGING: return "IMAGING"; case BluetoothClass.Device.Major.WEARABLE: 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/BluetoothDeviceCategory.dart b/lib/BluetoothDeviceCategory.dart index 8dff58cc..e37754e5 100644 --- a/lib/BluetoothDeviceCategory.dart +++ b/lib/BluetoothDeviceCategory.dart @@ -13,6 +13,10 @@ enum BluetoothDeviceCategory { HEALTH, UNCATEGORIZED, UNKNOWN, + PERIPHERAL_KEYBOARD, + PERIPHERAL_POINTING, + PERIPHERAL_KEYBOARD_POINTING, + PERIPHERAL_NON_KEYBOARD_NON_POINTING, } BluetoothDeviceCategory mapStringToDeviceCategory(String deviceCategoryString) { @@ -39,6 +43,14 @@ BluetoothDeviceCategory mapStringToDeviceCategory(String deviceCategoryString) { return BluetoothDeviceCategory.HEALTH; case "UNCATEGORIZED": return BluetoothDeviceCategory.UNCATEGORIZED; + case "PERIPHERAL_KEYBOARD": + return BluetoothDeviceCategory.PERIPHERAL_KEYBOARD; + case "PERIPHERAL_POINTING": + return BluetoothDeviceCategory.PERIPHERAL_POINTING; + case "PERIPHERAL_KEYBOARD_POINTING": + return BluetoothDeviceCategory.PERIPHERAL_KEYBOARD_POINTING; + case "PERIPHERAL_NON_KEYBOARD_NON_POINTING": + return BluetoothDeviceCategory.PERIPHERAL_NON_KEYBOARD_NON_POINTING; default: return BluetoothDeviceCategory.UNKNOWN; } @@ -68,6 +80,14 @@ String mapDeviceCategoryToString(BluetoothDeviceCategory category) { return "HEALTH"; case BluetoothDeviceCategory.UNCATEGORIZED: return "UNCATEGORIZED"; + case BluetoothDeviceCategory.PERIPHERAL_KEYBOARD: + return "PERIPHERAL_KEYBOARD"; + case BluetoothDeviceCategory.PERIPHERAL_POINTING: + return "PERIPHERAL_POINTING"; + case BluetoothDeviceCategory.PERIPHERAL_KEYBOARD_POINTING: + return "PERIPHERAL_KEYBOARD_POINTING"; + case BluetoothDeviceCategory.PERIPHERAL_NON_KEYBOARD_NON_POINTING: + return "PERIPHERAL_NON_KEYBOARD_NON_POINTING"; default: return "UNKNOWN"; } diff --git a/lib/flutter_bluetooth_serial.dart b/lib/flutter_bluetooth_serial.dart index d3299dc5..c6a5812a 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'; From a4ec4ca31828aa0c9989f36a9305c6e39a7d104b Mon Sep 17 00:00:00 2001 From: Tegar Date: Tue, 19 Sep 2023 11:38:34 +0700 Subject: [PATCH 12/14] Code improvement for bluetooth class --- .../FlutterBluetoothSerialPlugin.java | 52 +--------- example/lib/SelectBondedDevicePage.dart | 3 +- example/lib/helpers/LineChart.dart | 6 +- lib/BluetoothConnection.dart | 1 + lib/BluetoothDevice.dart | 8 +- lib/BluetoothDeviceCategory.dart | 98 ------------------ lib/BluetoothDeviceClass.dart | 99 +++++++++++++++++++ lib/flutter_bluetooth_serial.dart | 2 +- pubspec.yaml | 2 +- 9 files changed, 114 insertions(+), 157 deletions(-) delete mode 100644 lib/BluetoothDeviceCategory.dart create mode 100644 lib/BluetoothDeviceClass.dart 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 2de3e0de..d89a28b9 100644 --- a/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java +++ b/android/src/main/java/io/github/edufolly/flutterbluetoothserial/FlutterBluetoothSerialPlugin.java @@ -282,9 +282,9 @@ public void onReceive(Context context, Intent intent) { discoveryResult.put("isConnected", checkIsDeviceConnected(device)); discoveryResult.put("bondState", device.getBondState()); discoveryResult.put("rssi", deviceRSSI); - discoveryResult.put("category", convertDeviceClass(device.getBluetoothClass().getDeviceClass())); + discoveryResult.put("deviceClass", device.getBluetoothClass().getDeviceClass()); - Log.d(TAG, "Discovered " + device.getAddress() + " (category: " + convertDeviceClass(device.getBluetoothClass().getDeviceClass()) + ")"); + Log.d(TAG, "Discovered " + device.getAddress() + " (deviceClass: " + device.getBluetoothClass().getDeviceClass() + ")"); if (discoverySink != null) { discoverySink.success(discoveryResult); } @@ -501,50 +501,6 @@ static private boolean checkIsDeviceConnected(BluetoothDevice device) { } } - static private String convertDeviceClass(int deviceClassInt) { - int majorDeviceClass = deviceClassInt & 0x1F00; // Mask to extract major device class - switch (majorDeviceClass) { - case BluetoothClass.Device.Major.MISC: - return "MISC"; - case BluetoothClass.Device.Major.COMPUTER: - return "COMPUTER"; - case BluetoothClass.Device.Major.PHONE: - return "PHONE"; - case BluetoothClass.Device.Major.NETWORKING: - return "NETWORKING"; - case BluetoothClass.Device.Major.AUDIO_VIDEO: - return "AUDIO_VIDEO"; - case BluetoothClass.Device.Major.PERIPHERAL: - // Separate categories for barcode scanners, keyboards, and mice within "PERIPHERAL" - int minorDeviceClass = deviceClassInt & 0xFF; - switch (minorDeviceClass) { - case BluetoothClass.Device.PERIPHERAL_KEYBOARD: - return "PERIPHERAL_KEYBOARD"; - case BluetoothClass.Device.PERIPHERAL_POINTING: - return "PERIPHERAL_POINTING"; - case BluetoothClass.Device.PERIPHERAL_KEYBOARD_POINTING: - return "PERIPHERAL_KEYBOARD_POINTING"; - case BluetoothClass.Device.PERIPHERAL_NON_KEYBOARD_NON_POINTING: - return "PERIPHERAL_NON_KEYBOARD_NON_POINTING"; - default: - return "PERIPHERAL (UNKNOWN)"; - } - case BluetoothClass.Device.Major.IMAGING: - return "IMAGING"; - case BluetoothClass.Device.Major.WEARABLE: - return "WEARABLE"; - case BluetoothClass.Device.Major.TOY: - return "TOY"; - case BluetoothClass.Device.Major.HEALTH: - return "HEALTH"; - case BluetoothClass.Device.Major.UNCATEGORIZED: - return "UNCATEGORIZED"; - default: - return "UNKNOWN"; - } - } - - /// Helper wrapper class for `BluetoothConnection` private class BluetoothConnectionWrapper extends BluetoothConnection { private final int id; @@ -989,8 +945,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("category", convertDeviceClass(device.getBluetoothClass().getDeviceClass())); - Log.d(TAG, "Discovered " + device.getAddress() + " (category: " + convertDeviceClass(device.getBluetoothClass().getDeviceClass()) + ")"); + entry.put("deviceClass", device.getBluetoothClass().getDeviceClass()); + Log.d(TAG, "Discovered " + device.getAddress() + " (deviceClass: " + device.getBluetoothClass().getDeviceClass() + ")"); list.add(entry); } 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/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 a5e981ff..8e53f8d3 100644 --- a/lib/BluetoothDevice.dart +++ b/lib/BluetoothDevice.dart @@ -21,7 +21,7 @@ class BluetoothDevice { final BluetoothBondState bondState; /// Broadcasted friendly clas of the device. - final BluetoothDeviceCategory category; + final BluetoothDeviceClass deviceClass; /// Tells whether the device is bonded (ready to secure connect). @Deprecated('Use `isBonded` instead') @@ -37,7 +37,7 @@ class BluetoothDevice { this.type = BluetoothDeviceType.unknown, this.isConnected = false, this.bondState = BluetoothBondState.unknown, - this.category = BluetoothDeviceCategory.UNKNOWN, + this.deviceClass = BluetoothDeviceClass.UNCATEGORIZED, }); /// Creates `BluetoothDevice` from map. @@ -54,7 +54,7 @@ class BluetoothDevice { bondState: map["bondState"] != null ? BluetoothBondState.fromUnderlyingValue(map["bondState"]) : BluetoothBondState.unknown, - category: mapStringToDeviceCategory(map['category']) + deviceClass: (map['deviceClass'] as int).getBluetoothDeviceClassFromValue ); } @@ -65,7 +65,7 @@ class BluetoothDevice { "type": this.type.toUnderlyingValue(), "isConnected": this.isConnected, "bondState": this.bondState.toUnderlyingValue(), - 'category': mapDeviceCategoryToString(this.category), + 'deviceClass': this.deviceClass.value, }; /// Compares for equality of this and other `BluetoothDevice`. diff --git a/lib/BluetoothDeviceCategory.dart b/lib/BluetoothDeviceCategory.dart deleted file mode 100644 index e37754e5..00000000 --- a/lib/BluetoothDeviceCategory.dart +++ /dev/null @@ -1,98 +0,0 @@ -part of flutter_bluetooth_serial; - -enum BluetoothDeviceCategory { - MISC, - COMPUTER, - PHONE, - NETWORKING, - AUDIO_VIDEO, - PERIPHERAL, - IMAGING, - WEARABLE, - TOY, - HEALTH, - UNCATEGORIZED, - UNKNOWN, - PERIPHERAL_KEYBOARD, - PERIPHERAL_POINTING, - PERIPHERAL_KEYBOARD_POINTING, - PERIPHERAL_NON_KEYBOARD_NON_POINTING, -} - -BluetoothDeviceCategory mapStringToDeviceCategory(String deviceCategoryString) { - switch (deviceCategoryString) { - case "MISC": - return BluetoothDeviceCategory.MISC; - case "COMPUTER": - return BluetoothDeviceCategory.COMPUTER; - case "PHONE": - return BluetoothDeviceCategory.PHONE; - case "NETWORKING": - return BluetoothDeviceCategory.NETWORKING; - case "AUDIO_VIDEO": - return BluetoothDeviceCategory.AUDIO_VIDEO; - case "PERIPHERAL": - return BluetoothDeviceCategory.PERIPHERAL; - case "IMAGING": - return BluetoothDeviceCategory.IMAGING; - case "WEARABLE": - return BluetoothDeviceCategory.WEARABLE; - case "TOY": - return BluetoothDeviceCategory.TOY; - case "HEALTH": - return BluetoothDeviceCategory.HEALTH; - case "UNCATEGORIZED": - return BluetoothDeviceCategory.UNCATEGORIZED; - case "PERIPHERAL_KEYBOARD": - return BluetoothDeviceCategory.PERIPHERAL_KEYBOARD; - case "PERIPHERAL_POINTING": - return BluetoothDeviceCategory.PERIPHERAL_POINTING; - case "PERIPHERAL_KEYBOARD_POINTING": - return BluetoothDeviceCategory.PERIPHERAL_KEYBOARD_POINTING; - case "PERIPHERAL_NON_KEYBOARD_NON_POINTING": - return BluetoothDeviceCategory.PERIPHERAL_NON_KEYBOARD_NON_POINTING; - default: - return BluetoothDeviceCategory.UNKNOWN; - } -} - -String mapDeviceCategoryToString(BluetoothDeviceCategory category) { - switch (category) { - case BluetoothDeviceCategory.MISC: - return "MISC"; - case BluetoothDeviceCategory.COMPUTER: - return "COMPUTER"; - case BluetoothDeviceCategory.PHONE: - return "PHONE"; - case BluetoothDeviceCategory.NETWORKING: - return "NETWORKING"; - case BluetoothDeviceCategory.AUDIO_VIDEO: - return "AUDIO_VIDEO"; - case BluetoothDeviceCategory.PERIPHERAL: - return "PERIPHERAL"; - case BluetoothDeviceCategory.IMAGING: - return "IMAGING"; - case BluetoothDeviceCategory.WEARABLE: - return "WEARABLE"; - case BluetoothDeviceCategory.TOY: - return "TOY"; - case BluetoothDeviceCategory.HEALTH: - return "HEALTH"; - case BluetoothDeviceCategory.UNCATEGORIZED: - return "UNCATEGORIZED"; - case BluetoothDeviceCategory.PERIPHERAL_KEYBOARD: - return "PERIPHERAL_KEYBOARD"; - case BluetoothDeviceCategory.PERIPHERAL_POINTING: - return "PERIPHERAL_POINTING"; - case BluetoothDeviceCategory.PERIPHERAL_KEYBOARD_POINTING: - return "PERIPHERAL_KEYBOARD_POINTING"; - case BluetoothDeviceCategory.PERIPHERAL_NON_KEYBOARD_NON_POINTING: - return "PERIPHERAL_NON_KEYBOARD_NON_POINTING"; - default: - return "UNKNOWN"; - } -} - -extension BuildContextExtension on BluetoothDeviceCategory { - String get toStringValue => mapDeviceCategoryToString(this); -} 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 c6a5812a..1c84cab3 100644 --- a/lib/flutter_bluetooth_serial.dart +++ b/lib/flutter_bluetooth_serial.dart @@ -13,4 +13,4 @@ part './BluetoothPairingRequest.dart'; part './BluetoothDiscoveryResult.dart'; part './BluetoothConnection.dart'; part './FlutterBluetoothSerial.dart'; -part './BluetoothDeviceCategory.dart'; +part './BluetoothDeviceClass.dart'; diff --git a/pubspec.yaml b/pubspec.yaml index b5dd65b1..2790fd80 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -6,7 +6,7 @@ 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: From 78c20471257bae5d782a3228978d50afd242292d Mon Sep 17 00:00:00 2001 From: Tegar Date: Tue, 19 Sep 2023 11:40:47 +0700 Subject: [PATCH 13/14] handle if deviceClass null --- lib/BluetoothDevice.dart | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/BluetoothDevice.dart b/lib/BluetoothDevice.dart index 8e53f8d3..339b7333 100644 --- a/lib/BluetoothDevice.dart +++ b/lib/BluetoothDevice.dart @@ -45,17 +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, - deviceClass: (map['deviceClass'] as int).getBluetoothDeviceClassFromValue - ); + 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`. From ad63c61774eea844c51996ac87161e45d710c1af Mon Sep 17 00:00:00 2001 From: Tegar Date: Fri, 13 Oct 2023 09:56:41 +0700 Subject: [PATCH 14/14] update example icon bluetooth by device class --- example/lib/BluetoothDeviceListEntry.dart | 26 +++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) 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]);