Skip to content

Commit

Permalink
add monitoring beacons, add default constructor to Beacon class
Browse files Browse the repository at this point in the history
  • Loading branch information
alann-maulana committed Jan 23, 2019
1 parent 43d44bf commit 4595a2c
Show file tree
Hide file tree
Showing 17 changed files with 708 additions and 325 deletions.
432 changes: 204 additions & 228 deletions .idea/workspace.xml

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# flutter_beacon

[![](/pub/v/flutter_beacon.svg)](https://github.com/alann-maulana/flutter_beacon) [![](/github/license/alann-maulana/flutter_beacon.svg)](https://github.com/alann-maulana/flutter_beacon/blob/master/LICENSE)

[Flutter plugin](https://pub.dartlang.org/packages/flutter_beacon/) to work with iBeacons.

An hybrid iBeacon scanner SDK for Flutter plugin. Supports Android API 18+ and iOS 8+.
Expand Down
139 changes: 119 additions & 20 deletions android/src/main/java/com/flutterbeacon/FlutterBeaconPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.altbeacon.beacon.BeaconConsumer;
import org.altbeacon.beacon.BeaconManager;
import org.altbeacon.beacon.BeaconParser;
import org.altbeacon.beacon.MonitorNotifier;
import org.altbeacon.beacon.RangeNotifier;
import org.altbeacon.beacon.Region;

Expand All @@ -36,7 +37,7 @@
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.Registrar;

public class FlutterBeaconPlugin implements MethodCallHandler, EventChannel.StreamHandler,
public class FlutterBeaconPlugin implements MethodCallHandler,
PluginRegistry.RequestPermissionsResultListener,
PluginRegistry.ActivityResultListener {
private static final String TAG = FlutterBeaconPlugin.class.getSimpleName();
Expand All @@ -47,8 +48,9 @@ public class FlutterBeaconPlugin implements MethodCallHandler, EventChannel.Stre
private final Registrar registrar;
private BeaconManager beaconManager;
private Result flutterResult;
private EventChannel.EventSink flutterEventSink;
private EventChannel.EventSink eventSinkRanging, eventSinkMonitoring;
private List<Region> regionRanging;
private List<Region> regionMonitoring;

private FlutterBeaconPlugin(Registrar registrar) {
this.registrar = registrar;
Expand All @@ -68,7 +70,11 @@ public static void registerWith(Registrar registrar) {

final EventChannel eventChannel =
new EventChannel(registrar.messenger(), "flutter_beacon_event");
eventChannel.setStreamHandler(instance);
eventChannel.setStreamHandler(instance.rangingStreamHandler);

final EventChannel eventChannelMonitoring =
new EventChannel(registrar.messenger(), "flutter_beacon_event_monitoring");
eventChannelMonitoring.setStreamHandler(instance.monitoringStreamHandler);
}

@Override
Expand All @@ -81,16 +87,6 @@ public void onMethodCall(MethodCall call, Result result) {
}
}

@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
this.startRanging(o, eventSink);
}

@Override
public void onCancel(Object o) {
this.stopRanging();
}

private void initialize() {
this.beaconManager = BeaconManager.getInstanceForApplication(registrar.activity());

Expand Down Expand Up @@ -139,6 +135,18 @@ private boolean checkBluetoothPoweredOn() {
return (adapter != null) && (adapter.isEnabled());
}

private EventChannel.StreamHandler rangingStreamHandler = new EventChannel.StreamHandler() {
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
FlutterBeaconPlugin.this.startRanging(o, eventSink);
}

@Override
public void onCancel(Object o) {
FlutterBeaconPlugin.this.stopRanging();
}
};

private void startRanging(Object o, EventChannel.EventSink eventSink) {
Log.d(TAG, "START RANGING=" + o);
if (o instanceof List) {
Expand All @@ -160,7 +168,7 @@ private void startRanging(Object o, EventChannel.EventSink eventSink) {
eventSink.error("Beacon", "invalid region for ranging", null);
return;
}
this.flutterEventSink = eventSink;
this.eventSinkRanging = eventSink;
if (!this.beaconManager.isBound(beaconConsumer)) {
this.beaconManager.bind(beaconConsumer);
} else {
Expand All @@ -176,15 +184,14 @@ private void startRanging() {
beaconManager.startRangingBeaconsInRegion(region);
}
} catch (RemoteException e) {
if (FlutterBeaconPlugin.this.flutterEventSink != null) {
FlutterBeaconPlugin.this.flutterEventSink.error("Beacon", e.getLocalizedMessage(), null);
if (FlutterBeaconPlugin.this.eventSinkRanging != null) {
FlutterBeaconPlugin.this.eventSinkRanging.error("Beacon", e.getLocalizedMessage(), null);
}
}
}

private void stopRanging() {
this.flutterEventSink = null;
this.beaconManager.unbind(beaconConsumer);
this.eventSinkRanging = null;
}

private final BeaconConsumer beaconConsumer = new BeaconConsumer() {
Expand Down Expand Up @@ -212,11 +219,103 @@ public boolean bindService(Intent intent, ServiceConnection serviceConnection, i
private final RangeNotifier rangeNotifier = new RangeNotifier() {
@Override
public void didRangeBeaconsInRegion(Collection<Beacon> collection, Region region) {
if (FlutterBeaconPlugin.this.flutterEventSink != null) {
if (FlutterBeaconPlugin.this.eventSinkRanging != null) {
Map<String, Object> map = new HashMap<>();
map.put("region", FlutterBeaconUtils.regionToMap(region));
map.put("beacons", FlutterBeaconUtils.beaconsToArray(new ArrayList<>(collection)));
FlutterBeaconPlugin.this.flutterEventSink.success(map);
FlutterBeaconPlugin.this.eventSinkRanging.success(map);
}
}
};

private EventChannel.StreamHandler monitoringStreamHandler = new EventChannel.StreamHandler() {
@Override
public void onListen(Object o, EventChannel.EventSink eventSink) {
FlutterBeaconPlugin.this.startMonitoring(o, eventSink);
}

@Override
public void onCancel(Object o) {
FlutterBeaconPlugin.this.stopMonitoring();
}
};

private void startMonitoring(Object o, EventChannel.EventSink eventSink) {
Log.d(TAG, "START MONITORING=" + o);
if (o instanceof List) {
//noinspection unchecked
List<Object> list = (List<Object>) o;
if (this.regionMonitoring == null) {
this.regionMonitoring = new ArrayList<>();
} else {
this.regionMonitoring.clear();
}
for (Object object : list) {
if (object instanceof Map) {
//noinspection unchecked
Region region = FlutterBeaconUtils.regionFromMap((Map<String, Object>) object);
this.regionMonitoring.add(region);
}
}
} else {
eventSink.error("Beacon", "invalid region for monitoring", null);
return;
}
this.eventSinkMonitoring = eventSink;
if (!this.beaconManager.isBound(beaconConsumer)) {
this.beaconManager.bind(beaconConsumer);
} else {
startMonitoring();
}
}

private void startMonitoring() {
try {
FlutterBeaconPlugin.this.beaconManager.removeAllMonitorNotifiers();
FlutterBeaconPlugin.this.beaconManager.addMonitorNotifier(monitorNotifier);
for (Region region : regionMonitoring) {
beaconManager.startMonitoringBeaconsInRegion(region);
}
} catch (RemoteException e) {
if (FlutterBeaconPlugin.this.eventSinkMonitoring != null) {
FlutterBeaconPlugin.this.eventSinkMonitoring.error("Beacon", e.getLocalizedMessage(), null);
}
}
}

private void stopMonitoring() {
this.eventSinkMonitoring = null;
}

private MonitorNotifier monitorNotifier = new MonitorNotifier() {
@Override
public void didEnterRegion(Region region) {
if (FlutterBeaconPlugin.this.eventSinkMonitoring != null) {
Map<String, Object> map = new HashMap<>();
map.put("event", "didEnterRegion");
map.put("region", FlutterBeaconUtils.regionToMap(region));
FlutterBeaconPlugin.this.eventSinkMonitoring.success(map);
}
}

@Override
public void didExitRegion(Region region) {
if (FlutterBeaconPlugin.this.eventSinkMonitoring != null) {
Map<String, Object> map = new HashMap<>();
map.put("event", "didExitRegion");
map.put("region", FlutterBeaconUtils.regionToMap(region));
FlutterBeaconPlugin.this.eventSinkMonitoring.success(map);
}
}

@Override
public void didDetermineStateForRegion(int state, Region region) {
if (FlutterBeaconPlugin.this.eventSinkMonitoring != null) {
Map<String, Object> map = new HashMap<>();
map.put("event", "didDetermineStateForRegion");
map.put("state", state == MonitorNotifier.INSIDE ? "INSIDE" : state == MonitorNotifier.OUTSIDE ?"OUTSIDE" : "UNKNOWN");
map.put("region", FlutterBeaconUtils.regionToMap(region));
FlutterBeaconPlugin.this.eventSinkMonitoring.success(map);
}
}
};
Expand Down
2 changes: 1 addition & 1 deletion example/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ buildscript {
}

dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath 'com.android.tools.build:gradle:3.3.0'
}
}

Expand Down
22 changes: 22 additions & 0 deletions ios/Classes/FBMonitoringStreamHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// FBMonitoringStreamHandler.h
// flutter_beacon
//
// Created by Alann Maulana on 23/01/19.
//

#import <Foundation/Foundation.h>
#import <Flutter/Flutter.h>

NS_ASSUME_NONNULL_BEGIN

@class FlutterBeaconPlugin;
@interface FBMonitoringStreamHandler : NSObject<FlutterStreamHandler>

@property (strong, nonatomic) FlutterBeaconPlugin* instance;

- (instancetype) initWithFlutterBeaconPlugin:(FlutterBeaconPlugin*) instance;

@end

NS_ASSUME_NONNULL_END
40 changes: 40 additions & 0 deletions ios/Classes/FBMonitoringStreamHandler.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// FBMonitoringStreamHandler.m
// flutter_beacon
//
// Created by Alann Maulana on 23/01/19.
//

#import "FBMonitoringStreamHandler.h"
#import <FlutterBeaconPlugin.h>

@implementation FBMonitoringStreamHandler

- (instancetype) initWithFlutterBeaconPlugin:(FlutterBeaconPlugin*) instance {
if (self = [super init]) {
_instance = instance;
}

return self;
}

///------------------------------------------------------------
#pragma mark - Flutter Stream Handler
///------------------------------------------------------------

- (FlutterError * _Nullable)onCancelWithArguments:(id _Nullable)arguments {
if (self.instance) {
[self.instance stopMonitoringBeacon];
}
return nil;
}

- (FlutterError * _Nullable)onListenWithArguments:(id _Nullable)arguments eventSink:(nonnull FlutterEventSink)events {
if (self.instance) {
self.instance.flutterEventSinkMonitoring = events;
[self.instance startMonitoringBeaconWithCall:arguments];
}
return nil;
}

@end
22 changes: 22 additions & 0 deletions ios/Classes/FBRangingStreamHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//
// FBRangingStreamHandler.h
// flutter_beacon
//
// Created by Alann Maulana on 23/01/19.
//

#import <Foundation/Foundation.h>
#import <Flutter/Flutter.h>

NS_ASSUME_NONNULL_BEGIN

@class FlutterBeaconPlugin;
@interface FBRangingStreamHandler : NSObject<FlutterStreamHandler>

@property (strong, nonatomic) FlutterBeaconPlugin* instance;

- (instancetype) initWithFlutterBeaconPlugin:(FlutterBeaconPlugin*) instance;

@end

NS_ASSUME_NONNULL_END
40 changes: 40 additions & 0 deletions ios/Classes/FBRangingStreamHandler.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// FBRangingStreamHandler.m
// flutter_beacon
//
// Created by Alann Maulana on 23/01/19.
//

#import "FBRangingStreamHandler.h"
#import <FlutterBeaconPlugin.h>

@implementation FBRangingStreamHandler

- (instancetype) initWithFlutterBeaconPlugin:(FlutterBeaconPlugin*) instance {
if (self = [super init]) {
_instance = instance;
}

return self;
}

///------------------------------------------------------------
#pragma mark - Flutter Stream Handler
///------------------------------------------------------------

- (FlutterError * _Nullable)onCancelWithArguments:(id _Nullable)arguments {
if (self.instance) {
[self.instance stopRangingBeacon];
}
return nil;
}

- (FlutterError * _Nullable)onListenWithArguments:(id _Nullable)arguments eventSink:(nonnull FlutterEventSink)events {
if (self.instance) {
self.instance.flutterEventSinkRanging = events;
[self.instance startRangingBeaconWithCall:arguments];
}
return nil;
}

@end
9 changes: 9 additions & 0 deletions ios/Classes/FlutterBeaconPlugin.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
#import <Flutter/Flutter.h>

@interface FlutterBeaconPlugin : NSObject<FlutterPlugin>

@property FlutterEventSink flutterEventSinkRanging;
@property FlutterEventSink flutterEventSinkMonitoring;

- (void) startRangingBeaconWithCall:(id)arguments;
- (void) stopRangingBeacon;
- (void) startMonitoringBeaconWithCall:(id)arguments;
- (void) stopMonitoringBeacon;

@end
Loading

0 comments on commit 4595a2c

Please sign in to comment.