pauldemarco / flutter_blue

Bluetooth plugin for Flutter
BSD 3-Clause "New" or "Revised" License
2.36k stars 1.23k forks source link

Flutter Blue not detecting Android Devices #602

Open bilaalabdelhassan opened 4 years ago

bilaalabdelhassan commented 4 years ago

I built a Flutter app which detects devices within a certain range and vibrates as soon as it's too close.

While the app works wonders for PC or other devices like Bedroom TV, Samsung Watches or any other Devices, it doesn't detect any single Android Phone, which is my main focus.

If I scan for devices on my mobile, I can detect Android Phones within range but my app doesn't detect them.

I read a lot and even allowed Location permissions but still in vain.

Can someone help me?

My Code is below: (I know that it needs a lot of refactoring but I would've refactored it once I get the core functionality to work)

You should be able to replicate my complete app using the code below:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_blue/flutter_blue.dart';
import 'dart:math';
import 'package:flutter/services.dart';
import 'package:vibration/vibration.dart';

void main() {
  runApp(
    MaterialApp(
      debugShowCheckedModeBanner: false,
      home: SpriteDemo(),
    ),
  );
}

class SpritePainter extends CustomPainter {
  final Animation<double> _animation;

  SpritePainter(this._animation) : super(repaint: _animation);

  void circle(Canvas canvas, Rect rect, double value) {
    double opacity = (1.0 - (value / 4.0)).clamp(0.0, 1.0);
    Color colorConnected = new Color.fromRGBO(0, 204, 0, opacity);

    double size = rect.width / 2;
    double area = size * size;
    double radius = sqrt(area * value / 4);

    final Paint paint = new Paint()..color = colorConnected;
    canvas.drawCircle(rect.center, radius, paint);
  }

  @override
  void paint(Canvas canvas, Size size) {
    Rect rect = new Rect.fromLTRB(0.0, 0.0, size.width, size.height);

    for (int wave = 3; wave >= 0; wave--) {
      circle(canvas, rect, wave + _animation.value);
    }
  }

  @override
  bool shouldRepaint(SpritePainter oldDelegate) {
    return true;
  }
}

class SpriteDemo extends StatefulWidget {
  @override
  SpriteDemoState createState() => new SpriteDemoState();
}

class SpriteDemoState extends State<SpriteDemo>
    with SingleTickerProviderStateMixin {
  AnimationController _controller;
  FlutterBlue flutterBlue = FlutterBlue.instance;
  var state;
  var deviceId;
  var deviceIds;
  var devicesFound = 0;
  var rssiValues = [];
  var rssiValue = 0;
  var output = 'Searching for devices within 1m Radius';

  @override
  void initState() {
    super.initState();
    _controller = new AnimationController(
      vsync: this,
    );
    //_startAnimation();
    _printData();
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  void _printData() {
    _controller.stop();
    _controller.reset();
    _controller.repeat(
      period: Duration(seconds: 1),
    );

    Timer.periodic(Duration(seconds: 4), (timer) {
      flutterBlue.startScan(timeout: Duration(seconds: 2000));
      var subscription = FlutterBlue.instance.scanResults.listen(
        (results) {
          // do something with scan results
          for (ScanResult r in results) {
            print('${r.device.name} found! rssi: ${r.rssi}');

            if (r.rssi > -50) {
              Vibration.vibrate(duration: 500);
              output = 'Move Away!';
            }
          }
          setState(() {
            devicesFound = results.length;
          });
        },
      );
      flutterBlue.stopScan();
      output = 'Searching for devices within 1m Radius';
    });
  }

  @override
  Widget build(BuildContext context) {
    SystemChrome.setEnabledSystemUIOverlays([SystemUiOverlay.bottom]);
    return new Scaffold(
      body: Stack(
        children: <Widget>[
          Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              CustomPaint(
                painter: SpritePainter(_controller),

Please note that I have also added the following in my AndroidManifest.xml

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

My version of Flutter Blue and Vibration Module in my pubspec.yaml is

flutter_blue: ^0.7.2
vibration: ^1.2.4

I have also changed my minSdkVersion to 21 in build.gradle.

I am running the code on my Samsung Galaxy Note 9 with Android 10.

Thank you.

jjakob666 commented 4 years ago

I'm having the same problem. I installed my app on two phones. I use beacon_broadcast flutter library and my app can broadcast an AltBeacon and I can see the beacon with the Android app store app "BeaconScope". each phone can see the other's beacon. However, when using flutter_blue to scan it never sees the AltBeacon. Here is my creation of the beacon for broadcasting if you want to test scanning with flutter_blue.

//ALTBEACON format using beacon_broadcast: ^0.2.1 beaconBroadcast .setUUID(myUUID) .setMajorId(1) .setMinorId(100) .setLayout(BeaconBroadcast.ALTBEACON_LAYOUT) //Android-only, optional .setManufacturerId(0x001D) //Android-only, optional .setTransmissionPower(-59); //optional can be used to control distance detection between phones

jjakob666 commented 4 years ago

I solved the problem by switching the the library flutter_beacon ^0.3.0 found here: https://pub.dev/packages/flutter_beacon

here is my code:

// if you want to manage manual checking about the required permissions await flutterBeacon.initializeScanning;

  // or if you want to include automatic checking permission
  await flutterBeacon.initializeAndCheckScanning;

  final regions = <Region>[];

  if (Platform.isIOS) {
    // iOS platform, at least set identifier and proximityUUID for region scanning
    regions.add(Region(
        identifier: 'Apple Airlocate',
        proximityUUID: 'E2C56DB5-DFFB-48D2-B060-D0F5A71096E0'));
  } else {
    // android platform, it can ranging out of beacon that filter all of Proximity UUID
    regions.add(Region(identifier: 'com.beacon'));
  }

  // to start ranging beacons
  var _streamRanging = flutterBeacon.ranging(regions).listen((RangingResult result) {
    result.beacons.forEach((beacon) {
      print("_doBLERangingForBeacons() found new beacon: " + beacon.toString());
     });
  });

Timer(Duration(seconds: 10), () {
      print('_doBLERangingForBeacons() stop beacon scanning');
      // to stop ranging beacons
      _streamRanging.cancel();
    });
bilaalabdelhassan commented 4 years ago

That was great to hear. I will test this thank you!

Does it detect only iBeacons though? Can it detect AltBeacon?

jjakob666 commented 4 years ago

With my changes it detects both