Implement requestPermission API (#190)
* Implement requestPermission api * Update example ios podfile * Update example windows dependencies * Update Readme and Changelog * Resolve Ai Comments * Improve bluetooth permission handling * Update Readme * Improve readme --------- Co-authored-by: Foti Dim <foti@navideck.com>
This commit is contained in:
@@ -24,7 +24,7 @@ if (flutterVersionName == null) {
|
||||
|
||||
android {
|
||||
namespace "com.navideck.universal_ble_example"
|
||||
compileSdkVersion 35
|
||||
compileSdkVersion 36
|
||||
ndkVersion flutter.ndkVersion
|
||||
|
||||
compileOptions {
|
||||
@@ -45,7 +45,7 @@ android {
|
||||
// You can update the following values to match your application needs.
|
||||
// For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
|
||||
minSdkVersion flutter.minSdkVersion
|
||||
targetSdkVersion 35
|
||||
targetSdkVersion 36
|
||||
versionCode flutterVersionCode.toInteger()
|
||||
versionName flutterVersionName
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<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.BLUETOOTH" android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" android:maxSdkVersion="30" />
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https://services.gradle.org/distributions/gradle-8.10.2-all.zip
|
||||
distributionUrl=https://services.gradle.org/distributions/gradle-8.14.3-all.zip
|
||||
|
||||
@@ -18,8 +18,8 @@ pluginManagement {
|
||||
|
||||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
id "com.android.application" version "8.6.1" apply false
|
||||
id "org.jetbrains.kotlin.android" version "1.9.0" apply false
|
||||
id "com.android.application" version "8.13.1" apply false
|
||||
id "org.jetbrains.kotlin.android" version "2.2.21" apply false
|
||||
}
|
||||
|
||||
include ":app"
|
||||
@@ -1,39 +1,27 @@
|
||||
PODS:
|
||||
- device_info_plus (0.0.1):
|
||||
- Flutter
|
||||
- Flutter (1.0.0)
|
||||
- integration_test (0.0.1):
|
||||
- Flutter
|
||||
- permission_handler_apple (9.3.0):
|
||||
- Flutter
|
||||
- universal_ble (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- integration_test (from `.symlinks/plugins/integration_test/ios`)
|
||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||
- universal_ble (from `.symlinks/plugins/universal_ble/darwin`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
device_info_plus:
|
||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
integration_test:
|
||||
:path: ".symlinks/plugins/integration_test/ios"
|
||||
permission_handler_apple:
|
||||
:path: ".symlinks/plugins/permission_handler_apple/ios"
|
||||
universal_ble:
|
||||
:path: ".symlinks/plugins/universal_ble/darwin"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
integration_test: 252f60fa39af5e17c3aa9899d35d908a0721b573
|
||||
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
|
||||
universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6
|
||||
|
||||
PODFILE CHECKSUM: 4f1c12611da7338d21589c0b2ecd6bd20b109694
|
||||
|
||||
@@ -198,7 +198,6 @@
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
2F5EDC3CC74E7431E4CB95DF /* [CP] Embed Pods Frameworks */,
|
||||
6B74A273405B2F59259FD41D /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -325,23 +324,6 @@
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
6B74A273405B2F59259FD41D /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
7E79F47357B64513A488AC3E /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
||||
@@ -131,4 +131,9 @@ class MockUniversalBle extends UniversalBlePlatform {
|
||||
Future<bool> disableBluetooth() {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> requestPermissions({bool withAndroidFineLocation = false}) {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
// ignore_for_file: avoid_print
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
/*
|
||||
Required Permissions :
|
||||
<----------->
|
||||
IOS :
|
||||
- Bluetooth
|
||||
<----------->
|
||||
Android :
|
||||
if AndroidVersions < 12
|
||||
- Location
|
||||
- Bluetooth
|
||||
else
|
||||
- Bluetooth Scan
|
||||
- Bluetooth Connect
|
||||
<----------->
|
||||
Macos :
|
||||
<----------->
|
||||
Windows : None
|
||||
<----------->
|
||||
Linux : None
|
||||
<----------->
|
||||
Web :
|
||||
Check if Browser Supports Bluetooth
|
||||
*/
|
||||
class PermissionHandler {
|
||||
static Future<bool> arePermissionsGranted() async {
|
||||
if (!isMobilePlatform) return true;
|
||||
|
||||
var status = await _permissionStatus;
|
||||
bool blePermissionGranted = status[0];
|
||||
bool locationPermissionGranted = status[1];
|
||||
|
||||
if (locationPermissionGranted && blePermissionGranted) return true;
|
||||
|
||||
if (!blePermissionGranted) {
|
||||
PermissionStatus blePermissionCheck =
|
||||
await Permission.bluetooth.request();
|
||||
if (blePermissionCheck.isPermanentlyDenied) {
|
||||
print("Bluetooth Permission Permanently Denied");
|
||||
openAppSettings();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!locationPermissionGranted) {
|
||||
PermissionStatus locationPermissionCheck =
|
||||
await Permission.location.request();
|
||||
if (locationPermissionCheck.isPermanentlyDenied) {
|
||||
print("Location Permission Permanently Denied");
|
||||
openAppSettings();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static Future<List<bool>> get _permissionStatus async {
|
||||
bool blePermissionGranted = false;
|
||||
bool locationPermissionGranted = false;
|
||||
|
||||
if (await requiresExplicitAndroidBluetoothPermissions) {
|
||||
bool bleConnectPermission =
|
||||
(await Permission.bluetoothConnect.request()).isGranted;
|
||||
bool bleScanPermission =
|
||||
(await Permission.bluetoothScan.request()).isGranted;
|
||||
|
||||
blePermissionGranted = bleConnectPermission && bleScanPermission;
|
||||
locationPermissionGranted = true;
|
||||
} else {
|
||||
PermissionStatus permissionStatus = await Permission.bluetooth.request();
|
||||
blePermissionGranted = permissionStatus.isGranted;
|
||||
locationPermissionGranted = await requiresLocationPermission
|
||||
? (await Permission.locationWhenInUse.request()).isGranted
|
||||
: true;
|
||||
}
|
||||
return [blePermissionGranted, locationPermissionGranted];
|
||||
}
|
||||
|
||||
static bool get isMobilePlatform =>
|
||||
!kIsWeb && (Platform.isAndroid || Platform.isIOS);
|
||||
|
||||
static Future<bool> get requiresLocationPermission async =>
|
||||
!kIsWeb &&
|
||||
Platform.isAndroid &&
|
||||
(!await requiresExplicitAndroidBluetoothPermissions);
|
||||
|
||||
static Future<bool> get requiresExplicitAndroidBluetoothPermissions async {
|
||||
if (kIsWeb || !Platform.isAndroid) return false;
|
||||
AndroidDeviceInfo androidInfo = await DeviceInfoPlugin().androidInfo;
|
||||
return androidInfo.version.sdkInt >= 31;
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import 'package:universal_ble_example/data/mock_universal_ble.dart';
|
||||
import 'package:universal_ble_example/home/widgets/scan_filter_widget.dart';
|
||||
import 'package:universal_ble_example/home/widgets/scanned_devices_placeholder_widget.dart';
|
||||
import 'package:universal_ble_example/home/widgets/scanned_item_widget.dart';
|
||||
import 'package:universal_ble_example/data/permission_handler.dart';
|
||||
import 'package:universal_ble_example/peripheral_details/peripheral_detail_page.dart';
|
||||
import 'package:universal_ble_example/widgets/platform_button.dart';
|
||||
import 'package:universal_ble_example/widgets/responsive_buttons_grid.dart';
|
||||
@@ -90,9 +89,7 @@ class _MyAppState extends State<MyApp> {
|
||||
}
|
||||
|
||||
Future<void> startScan() async {
|
||||
await UniversalBle.startScan(
|
||||
scanFilter: scanFilter,
|
||||
);
|
||||
await UniversalBle.startScan(scanFilter: scanFilter);
|
||||
}
|
||||
|
||||
Future<void> _getSystemDevices() async {
|
||||
@@ -221,12 +218,15 @@ class _MyAppState extends State<MyApp> {
|
||||
),
|
||||
if (BleCapabilities.requiresRuntimePermission)
|
||||
PlatformButton(
|
||||
text: 'Check Permissions',
|
||||
text: 'Request Permissions',
|
||||
onPressed: () async {
|
||||
bool hasPermissions =
|
||||
await PermissionHandler.arePermissionsGranted();
|
||||
if (hasPermissions) {
|
||||
try {
|
||||
await UniversalBle.requestPermissions(
|
||||
withAndroidFineLocation: false,
|
||||
);
|
||||
showSnackbar("Permissions granted");
|
||||
} catch (e) {
|
||||
showSnackbar(e.toString());
|
||||
}
|
||||
},
|
||||
),
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
import FlutterMacOS
|
||||
import Foundation
|
||||
|
||||
import device_info_plus
|
||||
import universal_ble
|
||||
|
||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||
UniversalBlePlugin.register(with: registry.registrar(forPlugin: "UniversalBlePlugin"))
|
||||
}
|
||||
|
||||
@@ -1,26 +1,20 @@
|
||||
PODS:
|
||||
- device_info_plus (0.0.1):
|
||||
- FlutterMacOS
|
||||
- FlutterMacOS (1.0.0)
|
||||
- universal_ble (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
|
||||
DEPENDENCIES:
|
||||
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
|
||||
- FlutterMacOS (from `Flutter/ephemeral`)
|
||||
- universal_ble (from `Flutter/ephemeral/.symlinks/plugins/universal_ble/darwin`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
device_info_plus:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
|
||||
FlutterMacOS:
|
||||
:path: Flutter/ephemeral
|
||||
universal_ble:
|
||||
:path: Flutter/ephemeral/.symlinks/plugins/universal_ble/darwin
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
device_info_plus: 5401765fde0b8d062a2f8eb65510fb17e77cf07f
|
||||
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
|
||||
universal_ble: cf52a7b3fd2e7c14d6d7262e9fdadb72ab6b88a6
|
||||
|
||||
|
||||
+8
-93
@@ -81,22 +81,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.11"
|
||||
device_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: device_info_plus
|
||||
sha256: "77f757b789ff68e4eaf9c56d1752309bd9f7ad557cb105b938a7f8eb89e59110"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.1.2"
|
||||
device_info_plus_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: device_info_plus_platform_interface
|
||||
sha256: e1ea89119e34903dca74b883d0dd78eb762814f97fb6c76f35e9ff74d261a18f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.3"
|
||||
expandable:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -160,11 +144,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
fuchsia_remote_debug_protocol:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
@@ -179,10 +158,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: leak_tracker
|
||||
sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0"
|
||||
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.0.1"
|
||||
version: "11.0.2"
|
||||
leak_tracker_flutter_testing:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -235,10 +214,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c
|
||||
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
version: "1.17.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -247,54 +226,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
permission_handler:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: permission_handler
|
||||
sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.4.0"
|
||||
permission_handler_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_android
|
||||
sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "12.1.0"
|
||||
permission_handler_apple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_apple
|
||||
sha256: f000131e755c54cf4d84a5d8bd6e4149e262cc31c5a8b1d698de1ac85fa41023
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.4.7"
|
||||
permission_handler_html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_html
|
||||
sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.3+5"
|
||||
permission_handler_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_platform_interface
|
||||
sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.3.0"
|
||||
permission_handler_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_windows
|
||||
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -384,10 +315,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
|
||||
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.7.6"
|
||||
version: "0.7.7"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -402,7 +333,7 @@ packages:
|
||||
path: ".."
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.21.1"
|
||||
version: "1.0.0"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -435,22 +366,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
win32:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "66814138c3562338d05613a6e368ed8cfb237ad6d64a9e9334be3f309acfca03"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.14.0"
|
||||
win32_registry:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32_registry
|
||||
sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.5"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -461,4 +376,4 @@ packages:
|
||||
version: "6.6.1"
|
||||
sdks:
|
||||
dart: ">=3.8.0 <4.0.0"
|
||||
flutter: ">=3.29.0"
|
||||
flutter: ">=3.18.0-18.0.pre.54"
|
||||
|
||||
@@ -12,8 +12,6 @@ dependencies:
|
||||
convert: ^3.1.1
|
||||
expandable: ^5.0.1
|
||||
cupertino_icons: ^1.0.2
|
||||
permission_handler: ^11.3.1
|
||||
device_info_plus: ^9.0.2
|
||||
universal_ble:
|
||||
path: ../
|
||||
|
||||
|
||||
@@ -6,12 +6,9 @@
|
||||
|
||||
#include "generated_plugin_registrant.h"
|
||||
|
||||
#include <permission_handler_windows/permission_handler_windows_plugin.h>
|
||||
#include <universal_ble/universal_ble_plugin_c_api.h>
|
||||
|
||||
void RegisterPlugins(flutter::PluginRegistry* registry) {
|
||||
PermissionHandlerWindowsPluginRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin"));
|
||||
UniversalBlePluginCApiRegisterWithRegistrar(
|
||||
registry->GetRegistrarForPlugin("UniversalBlePluginCApi"));
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#
|
||||
|
||||
list(APPEND FLUTTER_PLUGIN_LIST
|
||||
permission_handler_windows
|
||||
universal_ble
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user