Baseflow / Baseflow/flutter-permission-handler

flutter: Bluetooth permissions denied. Scan: false, Connect: false

Open
#1,418 3 comments 0 reactions 0 assignees View on GitHub
Dominant language
Dart
Stars
2.2k
Forks
970
Avg merge
14h 22m
Merged PRs (30d)
2

Description

### Please check the following before submitting a new issue.

- [X] I have searched the [existing issues](https://github.com/baseflow/flutter-permission-handler/issues).
- [X] I have carefully [read the documentation](https://github.com/baseflow/flutter-permission-handler/blob/main/permission_handler/README.md).

### Please select for which platform(s) you need help

- [ ] Android
- [X] iOS
- [ ] Windows

### Your question

I am developing a bluetooth scanning app using flutter and I encountered permission issue.

I get this message when I try to test it.

flutter: Bluetooth permissions denied. Scan: false, Connect: false

This is my main.dart

import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';

void main() {
runApp(const MyApp());
}

class MyApp extends StatelessWidget {
const MyApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter BLE Scanner',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(),
);
}
}

class BleController extends GetxController {
FlutterBlue ble = FlutterBlue.instance;
List devicesList = []; // To store discovered devices

// This function will start the BLE scan and update the device list
Future scanDevices() async {
var bluetoothScanPermission = await Permission.bluetoothScan.request();
var bluetoothConnectPermission = await Permission.bluetoothConnect.request();

// Check if both Bluetooth scan and connect permissions are granted
if (bluetoothScanPermission.isGranted && bluetoothConnectPermission.isGranted) {
// Start scanning
ble.startScan(timeout: Duration(seconds: 15));

// Listen to scan results and add them to the list
ble.scanResults.listen((results) {
devicesList = results;
update(); // Notify listeners to rebuild the UI with the updated devices list
});

// Stop scanning after the timeout
await Future.delayed(Duration(seconds: 15));
ble.stopScan();
} else {
print("Bluetooth permissions denied. Scan: ${bluetoothScanPermission.isGranted}, Connect: ${bluetoothConnectPermission.isGranted}");
}
}

// Function to connect to a device
Future connectToDevice(BluetoothDevice device) async {
try {
await device.connect(timeout: Duration(seconds: 15));
device.state.listen((state) {
if (state == BluetoothDeviceState.connecting) {
print("Connecting to ${device.name}...");
} else if (state == BluetoothDeviceState.connected) {
print("Connected to ${device.name}");
} else {
print("Device ${device.name} disconnected");
}
});
} catch (e) {
print("Error connecting to device: $e");
}
}

// Stream to listen for scan results
Stream> get scanResults => ble.scanResults;
}

class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});

@override
State createState() => _MyHomePageState();
}

class _MyHomePageState extends State {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("BLE Scanner"),
),
body: GetBuilder(
init: BleController(),
builder: (controller) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// List the found devices
Expanded(
child: ListView.builder(
itemCount: controller.devicesList.length,
itemBuilder: (context, index) {
final device = controller.devicesList[index];
return Card(
elevation: 2,
child: ListTile(
title: Text(device.device.name.isNotEmpty
? device.device.name
: "Unnamed Device"),
subtitle: Text(device.device.id.id),
trailing: Text(device.rssi.toString()),
onTap: () => controller.connectToDevice(device.device),
),
);
},
),
),
SizedBox(height: 10),
// Button to start scanning
ElevatedButton(
onPressed: () async {
await controller.scanDevices();
},
child: const Text("Start Scan"),
),
],
),
);
},
),
);
}
}

This is my info.plist

CADisableMinimumFrameDurationOnPhone

CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
NSBluetoothAlwaysUsageDescription
We need access to Bluetooth to scan and connect to nearby devices.
NSBluetoothPeripheralUsageDescription
We need access to Bluetooth to communicate with nearby devices.

CFBundleDisplayName
Testflutter
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
testflutter
CFBundlePackageType
APPL
CFBundleShortVersionString
$(FLUTTER_BUILD_NAME)
CFBundleSignature
????
CFBundleVersion
$(FLUTTER_BUILD_NUMBER)
LSRequiresIPhoneOS

UIApplicationSupportsIndirectInputEvents

UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
Main
UISupportedInterfaceOrientations

UIInterfaceOrientationPortrait
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight

UISupportedInterfaceOrientations~ipad

UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight

This is my pod file

# Uncomment this line to define a global platform for your project
platform :ios, '12.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}

def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end

File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end

require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

flutter_ios_podfile_setup

target 'Runner' do
use_frameworks!
use_modular_headers!

flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
target 'RunnerTests' do
inherit! :search_paths
end

# Add Bluetooth permission for iOS
post_install do |installer|
installer.pods_project.targets.each do |target|
# Add the Bluetooth permission to the build settings
target.build_configurations.each do |config|
config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
'$(inherited)',
'PERMISSION_BLUETOOTH=1', # Add this line for Bluetooth permission
]
end

flutter_additional_ios_build_settings(target)
end
end
end

![image](https://github.com/user-attachments/assets/1787cca2-6e40-4979-b33a-a55953ed79c8)

Eventhough the app asks for permission and even after granting it, it says that flutter: Bluetooth permissions denied. Can someone help?

### Version

na

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.