Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

iOS doesn't work : bluetooth permission ? #49

Open
Cinqprien opened this issue Jun 9, 2021 · 7 comments
Open

iOS doesn't work : bluetooth permission ? #49

Cinqprien opened this issue Jun 9, 2021 · 7 comments

Comments

@Cinqprien
Copy link

Hello !

Thanks for the plugin. It's working fine on Android but I have a problem on iOS : it detect nothing since I pass in version 2.0.0. I think it has a link with a bluetooth permission. I add the lines in my info.plist but my phone doesn't ask me for bluetooth permission when I launch the app. Maybe there is something else ?

Here my info.plist :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>MiLo</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>$(FLUTTER_BUILD_NAME)</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>$(FLUTTER_BUILD_NUMBER)</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
	<string>App needs location permissions to scan nearby beacons.</string>
	<key>NSLocationWhenInUseUsageDescription</key>
	<string>App needs location permissions to scan nearby beacons.</string>
	<key>NSLocationAlwaysUsageDescription</key>
	<string>App needs location permissions to scan nearby beacons.</string>
	<key>NSAppTransportSecurity</key>
	<dict>
		<key>NSAllowsLocalNetworking</key>
		<true/>
	</dict>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIMainStoryboardFile</key>
	<string>Main</string>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UIViewControllerBasedStatusBarAppearance</key>
	<false/>
</dict>
</plist>

And here the code :

// All packages needed by the widget
import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:io' show Platform;
import 'dart:convert';
import 'package:beacons_plugin/beacons_plugin.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_application_1/widgets/beacon_card.dart';

class BeaconDetection extends StatefulWidget {
  // Declaration of the variables needed by the widget 1/2
  final townId;
  final fontsizeValue;
  final languageId;
  final wordMessageBeforeScan;
  final wordButtonLaunchScan;
  final wordButtonStopScan;
  // Declaration of the variables needed by the widget 2/2
  BeaconDetection(
      {this.townId,
      this.fontsizeValue,
      this.languageId,
      this.wordMessageBeforeScan,
      this.wordButtonLaunchScan,
      this.wordButtonStopScan});
  @override
  _BeaconDetectionState createState() => _BeaconDetectionState();
}

class _BeaconDetectionState extends State<BeaconDetection> {
  bool isRunning = false;
  String _beaconUuid = '';
  double _beaconDistance = 0;
  String _beaconDetectedUuid = 'null';
  double _beaconDetectedDistance = 0;

  final StreamController<String> beaconEventsController =
      StreamController<String>.broadcast();
  @override
  void initState() {
    super.initState();
    initPlatformState();
  }

  @override
  void dispose() {
    beaconEventsController.close();
    super.dispose();
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    if (Platform.isAndroid) {
      // Prominent disclosure
      await BeaconsPlugin.setDisclosureDialogMessage(
          title: "Need Location Permission",
          message: "This app collects location data to work with beacons.");
      // Only in case, you want the dialog to be shown again. By Default, dialog will never be shown if permissions are granted.
      // await BeaconsPlugin.clearDisclosureDialogShowFlag(false);
    }

    BeaconsPlugin.listenToBeacons(beaconEventsController);

    // Extraction of the name and the uuid of the beacons of the chosen city from the firebase
    FirebaseFirestore.instance
        .collection('towns/${widget.townId}/beacons')
        .snapshots()
        .listen((event) {
      event.docs.forEach((element) async {
        if (element['name'].isNotEmpty == true &&
            element['uuid'].isNotEmpty == true &&
            element['visibility'] == true) {
          await BeaconsPlugin.addRegion(element['name'], element['uuid']);
        }
      });
    });

    // When listening the data from beacons detected
    beaconEventsController.stream.listen(
        (data) {
          if (data.isNotEmpty) {
            setState(() {
              Map _beaconScanned = jsonDecode(data);
              _beaconUuid = _beaconScanned['uuid'];
              _beaconDistance = double.parse(_beaconScanned['distance']);
            });
            // print("Beacons DataReceived: " + data);
            FirebaseFirestore.instance
                .collection('towns/${widget.townId}/beacons')
                .where('uuid', isEqualTo: _beaconUuid)
                .snapshots()
                .listen((event) {
              event.docs.forEach((element) {
                if (_beaconUuid == element['uuid'] &&
                    element['visibility'] == true &&
                    _beaconDistance <= element['distance']) {
                  print('Beacon: $_beaconUuid | Distance: $_beaconDistance');
                  _beaconDetectedUuid = _beaconUuid;
                  _beaconDetectedDistance = _beaconDistance;
                }
              });
            });
          }
        },
        onDone: () {},
        onError: (error) {
          print("Error: $error");
        });
    await BeaconsPlugin.runInBackground(
        isRunning); // Send 'true' to run in background
    if (Platform.isAndroid) {
      BeaconsPlugin.channel.setMethodCallHandler((call) async {
        if (call.method == 'scannerReady') {
          await BeaconsPlugin.startMonitoring();
          setState(() {
            isRunning = true;
          });
        }
      });
    } else if (Platform.isIOS) {
      await BeaconsPlugin.startMonitoring();
      setState(() {
        isRunning = true;
      });
    }
    if (!mounted) return;
  }

  Widget build(BuildContext context) {
    return Column(
      children: [
        StreamBuilder<QuerySnapshot>(
            stream: FirebaseFirestore.instance
                .collection('towns/${widget.townId}/beacons')
                .where('uuid', isEqualTo: _beaconDetectedUuid)
                .snapshots(),
            builder: (ctx, snapshot) {
              if (snapshot.connectionState ==
                  ConnectionState.waiting) // Initialisation state
                return Container(
                  margin: const EdgeInsets.all(10),
                  height: 314, // Beacon card's size
                  child: Center(child: CircularProgressIndicator()),
                );
              if (_beaconDetectedUuid == 'null' &&
                  isRunning == false) // Before first scan State
                return Container(
                  margin: const EdgeInsets.all(10),
                  height: 314, // Beacon card's size
                  child: Center(child: Text(widget.wordMessageBeforeScan)),
                );
              if (_beaconDetectedUuid == 'null' &&
                  isRunning == true) // Launch first scan state
                return Container(
                  margin: const EdgeInsets.all(10),
                  height: 314, // Beacon card's size
                  child: Center(
                    child: CircularProgressIndicator(),
                  ),
                );
              final beacons = snapshot.data!.docs;
              return BeaconCard( // When the detection is done => Display the widget 'BeaconCard' with the following data
                title: beacons[0]['title'],
                monument: beacons[0]['monument'],
                image: beacons[0]['image'],
                duration: beacons[0]['duration'],
                distance: _beaconDetectedDistance,
                townId: widget.townId,
                uuid: beacons[0]['uuid'],
                fontsizeValue: widget.fontsizeValue,
                languageId: widget.languageId,
              );
            }),
        isRunning
            ? FloatingActionButton.extended( // If 'isRunning' is true => Display a button to stop the scan
                icon: Icon(Icons.bluetooth_disabled),
                label: Text(widget.wordButtonStopScan),
                backgroundColor: Colors.red,
                onPressed: () async {
                  await BeaconsPlugin.stopMonitoring();
                  setState(() {
                    isRunning = false;
                  });
                },
              )
            : FloatingActionButton.extended( // If 'isRunning' is false => Display a button to start the scan
                icon: Icon(Icons.bluetooth),
                label: Text(widget.wordButtonLaunchScan),
                backgroundColor: Theme.of(context).primaryColor,
                onPressed: () async {
                  initPlatformState();
                  await BeaconsPlugin.startMonitoring();
                  setState(() {
                    isRunning = true;
                    _beaconDetectedUuid = 'null';
                  });
                },
              ),
        SizedBox(
          height: 16,
        )
      ],
    );
  }
}

Thanks a lot and good day!

@RazaGR
Copy link

RazaGR commented Jun 9, 2021

same issue on iOS , @umair13adil any idea?

@Cinqprien
Copy link
Author

If anyone found a solution, I'll be glad to know it, it's really a big issue for me !

@Cinqprien
Copy link
Author

Okey, it's working when I put the UUID in my code, the problem is with the firebase. If anyone has a solution to store the UUID on firebase it's will be great!

@RazaGR
Copy link

RazaGR commented Jun 16, 2021

@Cinqprien could you please share your code?

@gordett
Copy link

gordett commented Jan 21, 2022

Okey, it's working when I put the UUID in my code, the problem is with the firebase. If anyone has a solution to store the UUID on firebase it's will be great!

Hello,

you put uuid in region and in ibeacon config?

i can find with android, but with iOS I can’t see any beacon. And I don’t have any error.

@daoxuanquan
Copy link

daoxuanquan commented Mar 22, 2022

If you want to detect beacons on IOS, you must add the UUID of the beacons you want to be detected by using addRegion before scaning. that no needed on Android. A

@gordett
Copy link

gordett commented Mar 22, 2022

Thanks for your info. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants