beacons_plugin 1.0.12

  • Readme
  • Changelog
  • Example
  • Installing
  • 87

beacons_plugin #

pub package

This plugin is developed to scan nearby iBeacons on both Android iOS. This library makes it easier to scan & range nearby BLE beacons and read their proximity values.

Android #

For Android change min SDK version:

defaultConfig {
  ...
  minSdkVersion 19
  ...
}

Change your Android Project's MainActivity class to following:

import com.umair.beacons_plugin.BeaconsActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant

class MainActivity : BeaconsActivity(){

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        GeneratedPluginRegistrant.registerWith(flutterEngine)
    }
}

Add following dependency on build.gradle file:

    implementation 'org.altbeacon:android-beacon-library:2.16.4'

Add following in Android Manifest file:

    
        <uses-permission android:name="android.permission.BLUETOOTH" />
        <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
        <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
        <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
        <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
        <uses-permission android:name="android.permission.WAKE_LOCK" />
    
        <uses-feature
            android:name="android.hardware.bluetooth_le"
            android:required="true" />
            
        <application
                android:icon="@mipmap/ic_launcher"
                android:label="beacons_plugin_example">
                <receiver
                    android:name="com.umair.beacons_plugin.RebootBroadcastReceiver"
                    android:enabled="true">
                    <intent-filter>
                        <action android:name="android.intent.action.BOOT_COMPLETED"></action>
                    </intent-filter>
                </receiver>
        
                <service
                    android:name="com.umair.beacons_plugin.BeaconsDiscoveryService"
                    android:exported="true" />
        
                <service
                    android:name="org.altbeacon.beacon.service.BeaconService"
                    android:enabled="true"
                    android:isolatedProcess="false"
                    android:label="beacon" />
                <service
                    android:name="org.altbeacon.beacon.BeaconIntentProcessor"
                    android:enabled="true" />
        </application>

That's it for Android.

iOS #

In your AppDelegate.swift file change it to like this:

    
    import UIKit
    import Flutter
    import CoreLocation
    
    @UIApplicationMain
    @objc class AppDelegate: FlutterAppDelegate {
    
        let locationManager = CLLocationManager()
    
        override func application(
            _ application: UIApplication,
            didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
        ) -> Bool {
    
            locationManager.requestAlwaysAuthorization()
            GeneratedPluginRegistrant.register(with: self)
    
            return super.application(application, didFinishLaunchingWithOptions: launchOptions)
        }
    }

In your Info.plist file add following lines:

    <dict>
    	<key>UIBackgroundModes</key>
      <string>location</string>
      <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>
    </dict>

Install #

In your pubspec.yaml

dependencies:
  beacons_plugin: [LATEST_VERSION]
import 'dart:async';
import 'dart:io' show Platform;
import 'package:flutter/services.dart';
import 'package:beacons_plugin/beacons_plugin.dart';

Ranging Beacons & Setting Up #

    // if you need to monitor also major and minor use the original version and not this fork
    BeaconsPlugin.addRegion("myBeacon", "01022022-f88f-0000-00ae-9605fd9bb620")
        .then((result) {
          print(result);
        });
    
    //Send 'true' to run in background
    await BeaconsPlugin.runInBackground(true);
    
    //IMPORTANT: Start monitoring once scanner is setup & ready (only for Android)
    if (Platform.isAndroid) {
      BeaconsPlugin.channel.setMethodCallHandler((call) async {
        if (call.method == 'scannerReady') {
          await BeaconsPlugin.startMonitoring;
        }
      });
    } else if (Platform.isIOS) {
      await BeaconsPlugin.startMonitoring;
    }
    

Listen To Beacon Scan Results as Stream #

    
    final StreamController<String> beaconEventsController = StreamController<String>.broadcast();
    BeaconsPlugin.listenToBeacons(beaconEventsController);
    
    static listenToBeacons() async {
        eventChannel.receiveBroadcastStream().listen((dynamic event) {
          print('Received: $event');
        }, onError: (dynamic error) {
          print('Received error: ${error.message}');
        });
    }
    
    beaconEventsController.stream.listen(
        (data) {
          if (data.isNotEmpty) {
            setState(() {
              _beaconResult = data;
            });
            print("Beacons DataReceived: " + data);
          }
        },
        onDone: () {},
        onError: (error) {
          print("Error: $error");
        });

Scan Results #

DataAndroidiOS
nameYesYes
uuidYesYes
majorYesYes
minorYesYes
distanceYesYes
proximityYesYes
rssiYesYes
macAddressYesNo
txPowerYesNo

Native Libraries #

Author #

Flutter Beacons plugin is developed by Umair Adil. You can email me at m.umair.adil@gmail.com for any queries.

1.0.112 #

  • Handled initialization exception

1.0.10 #

  • Fixed Beacons not detected in iOS.
  • Fixed background service not stopped issue on stop scanning event.

1.0.9 #

  • Fixed 'Beacon' JSON issue.

1.0.7 #

  • Added Background scan mode
  • Fixed iOS build issue

1.0.5 - 1.0.6 #

  • Fixed Method channel not found issue.

1.0.4 #

  • Updated Android Logic.

1.0.1 #

  • Initial Release.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'dart:async';
import 'dart:io' show Platform;
import 'package:beacons_plugin/beacons_plugin.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String _beaconResult = 'Not Scanned Yet.';
  int _nrMessaggesReceived = 0;
  var isRunning = false;

  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 {
    BeaconsPlugin.listenToBeacons(beaconEventsController);

    await BeaconsPlugin.addRegion(
        "BeaconType1", "909c3cf9-fc5c-4841-b695-380958a51a5a");
    await BeaconsPlugin.addRegion(
        "BeaconType2", "6a84c716-0f2a-1ce9-f210-6a63bd873dd9");

    beaconEventsController.stream.listen(
        (data) {
          if (data.isNotEmpty) {
            setState(() {
              _beaconResult = data;
              _nrMessaggesReceived++;
            });
            print("Beacons DataReceived: " + data);
          }
        },
        onDone: () {},
        onError: (error) {
          print("Error: $error");
        });

    //Send 'true' to run in background
    await BeaconsPlugin.runInBackground(true);

    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;
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Monitoring Beacons'),
        ),
        body: Center(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text('$_beaconResult'),
              Padding(
                padding: EdgeInsets.all(10.0),
              ),
              Text('$_nrMessaggesReceived'),
              SizedBox(
                height: 20.0,
              ),
              Visibility(
                visible: isRunning,
                child: RaisedButton(
                  onPressed: () async {
                    if (Platform.isAndroid) {
                      await BeaconsPlugin.stopMonitoring;

                      setState(() {
                        isRunning = false;
                      });
                    }
                  },
                  child: Text('Stop Scanning', style: TextStyle(fontSize: 20)),
                ),
              ),
              SizedBox(
                height: 20.0,
              ),
              Visibility(
                visible: !isRunning,
                child: RaisedButton(
                  onPressed: () async {
                    initPlatformState();
                    await BeaconsPlugin.startMonitoring;

                    setState(() {
                      isRunning = true;
                    });
                  },
                  child: Text('Start Scanning', style: TextStyle(fontSize: 20)),
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  beacons_plugin: ^1.0.12

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:beacons_plugin/beacons_plugin.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
75
Health:
Code health derived from static analysis. [more]
99
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
87
Learn more about scoring.

We analyzed this package on May 26, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.1
  • pana: 0.13.8-dev
  • Flutter: 1.17.0

Health issues and suggestions

Document public APIs. (-1 points)

11 out of 11 API elements have no dartdoc comment.Providing good documentation for libraries, classes, functions, and other API elements improves code readability and helps developers find and use your API.

Fix lib/beacons_plugin.dart. (-0.50 points)

Analysis of lib/beacons_plugin.dart reported 1 hint:

line 2 col 8: Unused import: 'dart:ffi'.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
flutter 0.0.0
Transitive dependencies
collection 1.14.12
meta 1.1.8
sky_engine 0.0.99
typed_data 1.1.6
vector_math 2.0.8
Dev dependencies
flutter_test