From 3e042b487baeb2afaea0dc2e442dcae4604e6afe Mon Sep 17 00:00:00 2001 From: Ashemah Harrison Date: Wed, 20 Sep 2017 14:58:52 +1000 Subject: [PATCH 01/10] Send native events through NativeEventEmitter rather than bridge instance (fix for RN ~0.45+) --- ios/RNiBeacon/RNiBeacon/RNiBeacon.h | 4 ++- ios/RNiBeacon/RNiBeacon/RNiBeacon.m | 46 +++++++++++++++++++++++------ 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/ios/RNiBeacon/RNiBeacon/RNiBeacon.h b/ios/RNiBeacon/RNiBeacon/RNiBeacon.h index d08cac98..f85560f1 100644 --- a/ios/RNiBeacon/RNiBeacon/RNiBeacon.h +++ b/ios/RNiBeacon/RNiBeacon/RNiBeacon.h @@ -7,8 +7,10 @@ // #import + #import +#import -@interface RNiBeacon : NSObject +@interface RNiBeacon : RCTEventEmitter @end diff --git a/ios/RNiBeacon/RNiBeacon/RNiBeacon.m b/ios/RNiBeacon/RNiBeacon/RNiBeacon.m index d91b6b03..5450ede0 100644 --- a/ios/RNiBeacon/RNiBeacon/RNiBeacon.m +++ b/ios/RNiBeacon/RNiBeacon/RNiBeacon.m @@ -25,8 +25,6 @@ @implementation RNiBeacon RCT_EXPORT_MODULE() -@synthesize bridge = _bridge; - #pragma mark Initialization - (instancetype)init @@ -42,6 +40,16 @@ - (instancetype)init return self; } +- (NSArray *)supportedEvents +{ + return @[ + @"authorizationStatusDidChange", + @"beaconsDidRange", + @"regionDidEnter", + @"regionDidExit", + ]; +} + #pragma mark -(CLBeaconRegion *) createBeaconRegion: (NSString *) identifier @@ -207,8 +215,8 @@ -(NSString *)nameForAuthorizationStatus:(CLAuthorizationStatus)authorizationStat -(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { - NSString *statusName = [self nameForAuthorizationStatus:status]; - [self.bridge.eventDispatcher sendDeviceEventWithName:@"authorizationStatusDidChange" body:statusName]; + NSString *statusName = [self nameForAuthorizationStatus:status]; + [self sendEventWithName:@"authorizationStatusDidChange" body:statusName]; } -(void)locationManager:(CLLocationManager *)manager rangingBeaconsDidFailForRegion:(CLBeaconRegion *)region withError:(NSError *)error @@ -224,6 +232,26 @@ -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *) NSLog(@"Location manager failed: %@", error); } +- (void) locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region +{ + NSLog(@"did determine state"); + + switch (state) { + case CLRegionStateInside: + NSLog(@"state inside"); + break; + case CLRegionStateOutside: + NSLog(@"state outside"); + break; + case CLRegionStateUnknown: + NSLog(@"state unknown"); + break; + default: + NSLog(@"Default case: Region unknown"); + break; + } +} + -(void) locationManager:(CLLocationManager *)manager didRangeBeacons: (NSArray *)beacons inRegion:(CLBeaconRegion *)region { @@ -252,27 +280,27 @@ -(void) locationManager:(CLLocationManager *)manager didRangeBeacons: @"beacons": beaconArray }; - [self.bridge.eventDispatcher sendDeviceEventWithName:@"beaconsDidRange" body:event]; + [self sendEventWithName:@"beaconsDidRange" body:event]; } -(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLBeaconRegion *)region { NSDictionary *event = @{ - @"identifier": region.identifier, + @"region": region.identifier, @"uuid": [region.proximityUUID UUIDString], }; - [self.bridge.eventDispatcher sendDeviceEventWithName:@"regionDidEnter" body:event]; + [self sendEventWithName:@"regionDidEnter" body:event]; } -(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLBeaconRegion *)region { NSDictionary *event = @{ - @"identifier": region.identifier, + @"region": region.identifier, @"uuid": [region.proximityUUID UUIDString], }; - [self.bridge.eventDispatcher sendDeviceEventWithName:@"regionDidExit" body:event]; + [self sendEventWithName:@"regionDidExit" body:event]; } From 808d166fddd87bea65b01f60bfe2755afdcce913 Mon Sep 17 00:00:00 2001 From: Ashemah Harrison Date: Wed, 20 Sep 2017 15:02:16 +1000 Subject: [PATCH 02/10] Added valid podspec --- ReactNativeBeaconsManager.podspec | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 ReactNativeBeaconsManager.podspec diff --git a/ReactNativeBeaconsManager.podspec b/ReactNativeBeaconsManager.podspec new file mode 100644 index 00000000..eae63a0b --- /dev/null +++ b/ReactNativeBeaconsManager.podspec @@ -0,0 +1,11 @@ +Pod::Spec.new do |s| + s.name = "ReactNativeBeaconsManager" + s.version = "1.0.8" + s.summary = "React-Native library for detecting beacons (iOS and Android)" + s.homepage = "https://github.com/MacKentoch/react-native-beacons-manager#readme" + s.license = { :type => "MIT" } + s.authors = { "" => "" } + s.platform = :ios, "8.0" + s.source = { :path => "." } + s.source_files = "ios", "ios/**/*.{h,m}" +end \ No newline at end of file From 7fbb41419764fcefad716eff99f90bf0b87e56a0 Mon Sep 17 00:00:00 2001 From: Ashemah Harrison Date: Wed, 20 Sep 2017 15:31:37 +1000 Subject: [PATCH 03/10] Add didDetermineState event --- ios/RNiBeacon/RNiBeacon/RNiBeacon.m | 32 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/ios/RNiBeacon/RNiBeacon/RNiBeacon.m b/ios/RNiBeacon/RNiBeacon/RNiBeacon.m index 5450ede0..9110fc70 100644 --- a/ios/RNiBeacon/RNiBeacon/RNiBeacon.m +++ b/ios/RNiBeacon/RNiBeacon/RNiBeacon.m @@ -47,6 +47,7 @@ - (instancetype)init @"beaconsDidRange", @"regionDidEnter", @"regionDidExit", + @"didDetermineState" ]; } @@ -232,24 +233,23 @@ -(void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *) NSLog(@"Location manager failed: %@", error); } +-(NSString *)stringForState:(CLRegionState)state { + switch (state) { + case CLRegionStateInside: return @"inside"; + case CLRegionStateOutside: return @"outside"; + case CLRegionStateUnknown: return @"unknown"; + } +} + - (void) locationManager:(CLLocationManager *)manager didDetermineState:(CLRegionState)state forRegion:(CLRegion *)region { - NSLog(@"did determine state"); - - switch (state) { - case CLRegionStateInside: - NSLog(@"state inside"); - break; - case CLRegionStateOutside: - NSLog(@"state outside"); - break; - case CLRegionStateUnknown: - NSLog(@"state unknown"); - break; - default: - NSLog(@"Default case: Region unknown"); - break; - } + NSDictionary *event = @{ + @"state": [self stringForState:state], + @"region": region.identifier, + @"uuid": [region.proximityUUID UUIDString] + }; + + [self sendEventWithName:@"didDetermineState" body:event]; } -(void) locationManager:(CLLocationManager *)manager didRangeBeacons: From 1faf44f409098a2ed1b01fa248660fc251f8c4bf Mon Sep 17 00:00:00 2001 From: Ashemah Harrison Date: Wed, 20 Sep 2017 15:56:05 +1000 Subject: [PATCH 04/10] Remove proximity uuid as it is a CLRegion not CLBeaconRegion --- ios/RNiBeacon/RNiBeacon/RNiBeacon.m | 1 - 1 file changed, 1 deletion(-) diff --git a/ios/RNiBeacon/RNiBeacon/RNiBeacon.m b/ios/RNiBeacon/RNiBeacon/RNiBeacon.m index 9110fc70..2104b952 100644 --- a/ios/RNiBeacon/RNiBeacon/RNiBeacon.m +++ b/ios/RNiBeacon/RNiBeacon/RNiBeacon.m @@ -246,7 +246,6 @@ - (void) locationManager:(CLLocationManager *)manager didDetermineState:(CLRegio NSDictionary *event = @{ @"state": [self stringForState:state], @"region": region.identifier, - @"uuid": [region.proximityUUID UUIDString] }; [self sendEventWithName:@"didDetermineState" body:event]; From 88571c9d80eb3a2ed8e2a1d9fcdafb72634a9706 Mon Sep 17 00:00:00 2001 From: Ashemah Harrison Date: Fri, 22 Sep 2017 10:57:06 +1000 Subject: [PATCH 05/10] Added default case --- ios/RNiBeacon/RNiBeacon/RNiBeacon.m | 1 + 1 file changed, 1 insertion(+) diff --git a/ios/RNiBeacon/RNiBeacon/RNiBeacon.m b/ios/RNiBeacon/RNiBeacon/RNiBeacon.m index 2104b952..0f053a24 100644 --- a/ios/RNiBeacon/RNiBeacon/RNiBeacon.m +++ b/ios/RNiBeacon/RNiBeacon/RNiBeacon.m @@ -238,6 +238,7 @@ -(NSString *)stringForState:(CLRegionState)state { case CLRegionStateInside: return @"inside"; case CLRegionStateOutside: return @"outside"; case CLRegionStateUnknown: return @"unknown"; + default: return @"unknown"; } } From 6780047dfcb44b47ad7ff73490c0b3b458a6de1c Mon Sep 17 00:00:00 2001 From: MacKentoch Date: Wed, 20 Sep 2017 06:54:51 +0200 Subject: [PATCH 06/10] working example for #42 --- examples/BeaconsDemo/index.ios.js | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/BeaconsDemo/index.ios.js b/examples/BeaconsDemo/index.ios.js index 50eb022b..f58a026d 100644 --- a/examples/BeaconsDemo/index.ios.js +++ b/examples/BeaconsDemo/index.ios.js @@ -76,6 +76,7 @@ class BeaconsDemo extends Component { // you also have to add "Privacy - Location Always Usage Description" in your "Info.plist" file // otherwise monitoring won't work Beacons.requestAlwaysAuthorization(); + Beacons.shouldDropEmptyRanges(true); // Define a region which can be identifier + uuid, // identifier + uuid + major or identifier + uuid + major + minor // (minor and major properties are numbers) From 238aff24e8e4427adc3c4d401fd2c7b48f68c907 Mon Sep 17 00:00:00 2001 From: Ashemah Harrison Date: Fri, 22 Sep 2017 11:06:56 +1000 Subject: [PATCH 07/10] Change region back to identifier --- ios/RNiBeacon/RNiBeacon/RNiBeacon.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ios/RNiBeacon/RNiBeacon/RNiBeacon.m b/ios/RNiBeacon/RNiBeacon/RNiBeacon.m index 0f053a24..42e7f872 100644 --- a/ios/RNiBeacon/RNiBeacon/RNiBeacon.m +++ b/ios/RNiBeacon/RNiBeacon/RNiBeacon.m @@ -246,7 +246,7 @@ - (void) locationManager:(CLLocationManager *)manager didDetermineState:(CLRegio { NSDictionary *event = @{ @"state": [self stringForState:state], - @"region": region.identifier, + @"identifier": region.identifier, }; [self sendEventWithName:@"didDetermineState" body:event]; @@ -286,7 +286,7 @@ -(void) locationManager:(CLLocationManager *)manager didRangeBeacons: -(void)locationManager:(CLLocationManager *)manager didEnterRegion:(CLBeaconRegion *)region { NSDictionary *event = @{ - @"region": region.identifier, + @"identifier": region.identifier, @"uuid": [region.proximityUUID UUIDString], }; @@ -296,7 +296,7 @@ -(void)locationManager:(CLLocationManager *)manager -(void)locationManager:(CLLocationManager *)manager didExitRegion:(CLBeaconRegion *)region { NSDictionary *event = @{ - @"region": region.identifier, + @"identifier": region.identifier, @"uuid": [region.proximityUUID UUIDString], }; From c384833fc001908b8c0d67743a1ef3b6187a7c88 Mon Sep 17 00:00:00 2001 From: Ashemah Harrison Date: Fri, 22 Sep 2017 11:15:08 +1000 Subject: [PATCH 08/10] Update examples --- examples/samples/ranging.ios.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/samples/ranging.ios.js b/examples/samples/ranging.ios.js index 02f35eba..7df91e45 100644 --- a/examples/samples/ranging.ios.js +++ b/examples/samples/ranging.ios.js @@ -1,4 +1,5 @@ +import { NativeEventEmitter } from 'react-native' import Beacons from 'react-native-beacons-manager'; import moment from 'moment'; @@ -8,6 +9,10 @@ class beaconRangingOnly extends Component { constructor(props) { super(props); + this.beaconsEmitter = new NativeEventEmitter(Beacons); + this.beaconsDidRangeEvent = null; + this.authStateDidRangeEvent = null; + this.state = { // region information uuid: '7b44b47b-52a1-5381-90c2-f09b6838c5d4', @@ -24,7 +29,7 @@ class beaconRangingOnly extends Component { // // OPTIONAL: listen to authorization change - DeviceEventEmitter.addListener( + this.authStateDidRangeEvent = this.beaconsEmitter.addListener( 'authorizationStatusDidChange', (info) => console.log('authorizationStatusDidChange: ', info) ); @@ -47,7 +52,7 @@ class beaconRangingOnly extends Component { // // Ranging: Listen for beacon changes - DeviceEventEmitter.addListener( + this.beaconsDidRangeEvent = this.beaconsEmitter.addListener( 'beaconsDidRange', (data) => { // console.log('beaconsDidRange data: ', data); @@ -62,7 +67,8 @@ class beaconRangingOnly extends Component { // stop ranging beacons: Beacons.stopRangingBeaconsInRegion(region); // remove beacons event we registered at componentDidMount - DeviceEventEmitter.removeListener('beaconsDidRange'); + this.beaconsDidRangeEvent.remove(); + this.authStateDidRangeEvent.remove(); } render() { From 33ed9e51aef3eaefaa1da61a7721b67037aa6b6a Mon Sep 17 00:00:00 2001 From: Ashemah Harrison Date: Fri, 22 Sep 2017 12:11:28 +1000 Subject: [PATCH 09/10] Removed unneeded files --- lib/module.android.js | 231 ------------------------------------------ lib/module.ios.js | 7 -- 2 files changed, 238 deletions(-) delete mode 100644 lib/module.android.js delete mode 100644 lib/module.ios.js diff --git a/lib/module.android.js b/lib/module.android.js deleted file mode 100644 index cdfdfb25..00000000 --- a/lib/module.android.js +++ /dev/null @@ -1,231 +0,0 @@ -// @flow - -const RN = require('react-native'); - -const beaconsAndroid: any = RN.NativeModules.BeaconsAndroidModule; - -const PARSER_IBEACON: string = 'm:0-3=4c000215,i:4-19,i:20-21,i:22-23,p:24-24'; -const PARSER_ESTIMOTE: string = 'm:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24'; -const ALTBEACON: string = 'm:2-3=beac,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25'; -const EDDYSTONE_TLM: string = 'x,s:0-1=feaa,m:2-2=20,d:3-3,d:4-5,d:6-7,d:8-11,d:12-15'; -const EDDYSTONE_UID: string = 's:0-1=feaa,m:2-2=00,p:3-3:-41,i:4-13,i:14-19'; -const EDDYSTONE_URL: string = 's:0-1=feaa,m:2-2=10,p:3-3:-41,i:4-20v'; - -const tramissionSupport: Array = [ - 'SUPPORTED', - 'NOT_SUPPORTED_MIN_SDK', - 'NOT_SUPPORTED_BLE', - 'DEPRECATED_NOT_SUPPORTED_MULTIPLE_ADVERTISEMENTS', - 'NOT_SUPPORTED_CANNOT_GET_ADVERTISER', - 'NOT_SUPPORTED_CANNOT_GET_ADVERTISER_MULTIPLE_ADVERTISEMENTS' -]; - -const ARMA_RSSI_FILTER = beaconsAndroid.ARMA_RSSI_FILTER; -const RUNNING_AVG_RSSI_FILTER = beaconsAndroid.RUNNING_AVG_RSSI_FILTER; - -function setHardwareEqualityEnforced(e: boolean): void { - beaconsAndroid.setHardwareEqualityEnforced(e); -} - -/** - * set beacon layout for iBeacon - * - */ -function detectIBeacons(): void { - beaconsAndroid.addParser(PARSER_IBEACON); -} - -/** -* set beacon layout for alBeacon -* -*/ -function detectAltBeacons(): void { - beaconsAndroid.addParser(ALTBEACON); -} - -/** -* set beacon layout for estimote -* -*/ -function detectEstimotes(): void { - beaconsAndroid.addParser(PARSER_ESTIMOTE); -} - -/** -* set beacon layout for eddystone UID -* -*/ -function detectEddystoneUID(): void { - beaconsAndroid.addParser(EDDYSTONE_UID); -} - -/** -* set beacon layout for eddystone URL -* -*/ -function detectEddystoneURL(): void { - beaconsAndroid.addParser(EDDYSTONE_URL); -} - -/** -* set beacon layout for eddystone TLM -* -*/ -function detectEddystoneTLM(): void { - beaconsAndroid.addParser(EDDYSTONE_TLM); -} - -/** -* set beacon for custom layout -* -*/ -function detectCustomBeaconLayout(parser: number): void { - beaconsAndroid.addParser(parser); -} - -function setBackgroundScanPeriod(period: number): void { - beaconsAndroid.setBackgroundScanPeriod(period); -} - -function setBackgroundBetweenScanPeriod(period: number): void { - beaconsAndroid.setBackgroundBetweenScanPeriod(period); -} - -function setForegroundScanPeriod(period: number): void { - beaconsAndroid.setForegroundScanPeriod(period); -} - -function setRssiFilter(filterType: number, avgModifier: number): void { - beaconsAndroid.setRssiFilter(filterType, avgModifier); -} - -function getRangedRegions(): Promise { - return new Promise((resolve, reject) => { - beaconsAndroid.getRangedRegions(resolve); - }); -} - -type BeaconRegion = { - identifier: string, - uuid: string, - minor?: number, - major?: number -}; - - -/** - * get monitored regions - * - * @returns {Promise>} promise resolve to an array of monitored regions - */ -function getMonitoredRegions(): Promise> { - return new Promise((resolve, reject) => { - beaconsAndroid.getMonitoredRegions(resolve); - }); -} - -/** - * check if beacon support transmission - * - * @returns {Promise} promise resolve to an integer - */ -function checkTransmissionSupported(): Promise { - return new Promise((resolve, reject) => { - beaconsAndroid.checkTransmissionSupported(status => resolve(tramissionSupport[status])); - }); -} - -/** - * start monitoring for a region - * - * @param {Object: BeaconRegion} region region to monitor (identifier + uuid -> major and minor are optional) - * @returns {Promise} promise resolves to void or error - */ -function startMonitoringForRegion(region: BeaconRegion): Promise { - return new Promise((resolve, reject) => { - // NOTE: major and minor are optional values: if user don't assign them we have to send a null value (not undefined): - beaconsAndroid.startMonitoring( - region.identifier, - region.uuid, - region.minor ? region.minor : -1, - region.major ? region.major : -1, - resolve, - reject - ); - }); -} - -/** - * start ranging a region (with optional UUID) - * - * @param {string} regionId specified region to range - * @param {string} [beaconsUUID] optional UUID - * @returns {Promise} promise resolves to void or error - */ -function startRangingBeaconsInRegion(regionId: string, beaconsUUID?: string): Promise { - return new Promise( - (resolve, reject) => { - beaconsAndroid.startRanging(regionId, beaconsUUID, resolve, reject); - } - ); -} - -/** - * stops monittorings for a region - * - * @param {BeaconRegion} region region (see BeaconRegion type) - * @returns {Promise} promise resolves to void or error - */ -function stopMonitoringForRegion(region: BeaconRegion): Promise { - return new Promise( - (resolve, reject) => { - beaconsAndroid.stopMonitoring( - region.identifier, - region.uuid, - region.minor ? region.minor : -1, - region.major ? region.major : -1, - resolve, - reject - ); - } - ); -} - -/** - * Stops the range scan for beacons - * - * @param {string} regionId specified region to stop scan - * @param {string} beaconsUUID optional UUID within the specified region - * @returns {Promise} promise: resolves to void when successful - */ -function stopRangingBeaconsInRegion(regionId: string, beaconsUUID?: string): Promise { - return new Promise( - (resolve, reject) => { - beaconsAndroid.stopRanging(regionId, beaconsUUID, resolve, reject); - } - ); -} - -module.exports = { - setHardwareEqualityEnforced, - detectIBeacons, - detectAltBeacons, - detectEstimotes, - detectEddystoneUID, - detectEddystoneTLM, - detectEddystoneURL, - detectCustomBeaconLayout, - setBackgroundScanPeriod, - setBackgroundBetweenScanPeriod, - setForegroundScanPeriod, - setRssiFilter, - checkTransmissionSupported, - getRangedRegions, - getMonitoredRegions, - startMonitoringForRegion, - startRangingBeaconsInRegion, - stopMonitoringForRegion, - stopRangingBeaconsInRegion, - ARMA_RSSI_FILTER, - RUNNING_AVG_RSSI_FILTER -}; diff --git a/lib/module.ios.js b/lib/module.ios.js deleted file mode 100644 index 8f885510..00000000 --- a/lib/module.ios.js +++ /dev/null @@ -1,7 +0,0 @@ -// @flow - -const RN = require('react-native'); - -const NativeRNiBeacons = RN.NativeModules.RNiBeacon; - -module.exports = NativeRNiBeacons; From 5b0c2f1721015afa8aa52b7cd3176729631a279f Mon Sep 17 00:00:00 2001 From: Ashemah Harrison Date: Fri, 22 Sep 2017 12:11:48 +1000 Subject: [PATCH 10/10] Return BeaconsEventEmitter as well from structure --- lib/next/new.module.android.js | 3 +++ lib/next/new.module.ios.js | 3 +++ 2 files changed, 6 insertions(+) diff --git a/lib/next/new.module.android.js b/lib/next/new.module.android.js index 612319f4..7d13d879 100644 --- a/lib/next/new.module.android.js +++ b/lib/next/new.module.android.js @@ -17,6 +17,7 @@ import { } from './module.types'; const BeaconsManager: BeaconsManagerANDROID = RN.NativeModules.BeaconsAndroidModule; +const BeaconsEventEmitter = RN.DeviceEventEmitter; const ARMA_RSSI_FILTER = BeaconsManager.ARMA_RSSI_FILTER; const RUNNING_AVG_RSSI_FILTER = BeaconsManager.RUNNING_AVG_RSSI_FILTER; @@ -238,6 +239,8 @@ function stopRangingBeaconsInRegion( } module.exports = { + BeaconsEventEmitter, + setHardwareEqualityEnforced, detectIBeacons, detectAltBeacons, diff --git a/lib/next/new.module.ios.js b/lib/next/new.module.ios.js index 374246ad..3d5ca052 100644 --- a/lib/next/new.module.ios.js +++ b/lib/next/new.module.ios.js @@ -9,6 +9,7 @@ import type { } from './module.types'; const BeaconsManager: BeaconsManagerIOS = RN.NativeModules.RNiBeacon; +const BeaconsEventEmitter = new RN.NativeEventEmitter(BeaconsManager); /** * request always authorization (mandatory when ranging beacons but energy drain) @@ -143,6 +144,8 @@ function stopRangingBeaconsInRegion( } module.exports = { + BeaconsEventEmitter, + requestAlwaysAuthorization, requestWhenInUseAuthorization, getAuthorizationStatus,