├── README.md ├── android ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── surialabs │ │ └── rn │ │ └── geofencing │ │ ├── GeoFencing.java │ │ └── GeoFencingPackage.java │ └── res │ └── values │ └── strings.xml ├── index.js ├── ios ├── SLRNGeoFencing.h └── SLRNGeoFencing.m ├── package.json ├── react-native-geo-fencing.podspec └── screenshots ├── link_binaries.png └── linker_flags.png /README.md: -------------------------------------------------------------------------------- 1 | # react-native-geo-fencing 2 | 3 | Native modules to determine if a location is within defined geographical boundaries using Google Geometry library [for ios](https://developers.google.com/maps/documentation/ios-sdk/reference/group___geometry_utils.html#ga8aad2b31a4a4197c919b8da82c84d180) and [android](http://googlemaps.github.io/android-maps-utils/javadoc/com/google/maps/android/PolyUtil.html#containsLocation-LatLng-java.util.List-boolean-). 4 | 5 | ### Usage 6 | ```js 7 | import GeoFencing from 'react-native-geo-fencing'; 8 | ``` 9 | ```js 10 | // with navigator geolocation 11 | componentDidMount() { 12 | const polygon = [ 13 | { lat: 3.1336599385978805, lng: 101.31866455078125 }, 14 | { lat: 3.3091633559540123, lng: 101.66198730468757 }, 15 | { lat: 3.091150714460597, lng: 101.92977905273438 }, 16 | { lat: 2.7222113428196213, lng: 101.74850463867188 }, 17 | { lat: 2.7153526167685347, lng: 101.47933959960938 }, 18 | { lat: 3.1336599385978805, lng: 101.31866455078125 } // last point has to be same as first point 19 | ]; 20 | 21 | navigator.geolocation.getCurrentPosition( 22 | (position) => { 23 | let point = { 24 | lat: position.coords.latitude, 25 | lng: position.coords.longitude 26 | }; 27 | 28 | GeoFencing.containsLocation(point, polygon) 29 | .then(() => console.log('point is within polygon')) 30 | .catch(() => console.log('point is NOT within polygon')) 31 | }, 32 | (error) => alert(error.message), 33 | { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 } 34 | ); 35 | } 36 | ``` 37 | 38 | ```js 39 | // with only point and polygon 40 | componentDidMount() { 41 | const polygon = [ 42 | { lat: 3.1336599385978805, lng: 101.31866455078125 }, 43 | { lat: 3.3091633559540123, lng: 101.66198730468757 }, 44 | { lat: 3.091150714460597, lng: 101.92977905273438 }, 45 | { lat: 3.1336599385978805, lng: 101.31866455078125 } // last point has to be same as first point 46 | ]; 47 | 48 | let point = { 49 | lat: 2.951269758090068, 50 | lng: 101.964111328125 51 | }; 52 | 53 | GeoFencing.containsLocation(point, polygon) 54 | .then(() => console.log('point is within polygon')) 55 | .catch(() => console.log('point is NOT within polygon')) 56 | } 57 | ``` 58 | 59 | ### Installation 60 | $ npm install --save react-native-geo-fencing 61 | #### ios 62 | Within ```ios/``` directory of your react-native app: 63 | 64 | 1. Create a ```Podfile``` manually or simply 65 | 66 | $ pod init 67 | 68 | ```ruby 69 | # Podfile for cocoapods 1.0 70 | platform :ios, '7.0' 71 | 72 | target 'yourAppTarget' do 73 | pod 'React', path: '../node_modules/react-native' 74 | pod 'react-native-geo-fencing', path: '../node_modules/react-native-geo-fencing' 75 | end 76 | ``` 77 | 78 | ```ruby 79 | # for older version of CocoaPods 80 | platform :ios, '7.0' 81 | 82 | pod 'React', path: '../node_modules/react-native' 83 | pod 'react-native-geo-fencing', path: '../node_modules/react-native-geo-fencing' 84 | ``` 85 | 86 | 2. Then 87 | 88 | $ pod install 89 | 90 | 3. Add ```$(inherited)``` for ```Other Linker Flags``` to your project's ```build settings``` 91 | ![linking_library](/screenshots/linker_flags.png) 92 | 93 | 4. Link the static library 94 | ![linking_binaries](/screenshots/link_binaries.png) 95 | 96 | 97 | #### android 98 | 1. Add the following to ```android/settings.gradle``` 99 | ```java 100 | include ':react-native-geo-fencing' 101 | project(':react-native-geo-fencing').projectDir = new File(settingsDir, '../node_modules/react-native-geo-fencing/android') 102 | ``` 103 | 104 | 2. Add the following to ```android/app/build.gradle``` 105 | ```java 106 | dependencies { 107 | // ... 108 | compile project(':react-native-geo-fencing') 109 | } 110 | ``` 111 | 112 | 3. Edit ```android/src/.../MainActivity.java``` 113 | ```java 114 | // ... 115 | import com.surialabs.rn.geofencing.GeoFencingPackage;// <-- 116 | 117 | public class MainActivity extends ReactActivity { 118 | @Override 119 | protected List getPackages() { 120 | return Arrays.asList( 121 | new MainReactPackage(), 122 | new GeoFencingPackage() // <-- 123 | ); 124 | } 125 | } 126 | ``` 127 | 4. Enable access to location when using the app from your ```AndroidManifest.xml``` 128 | 129 | `````` 130 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.1" 6 | 7 | defaultConfig { 8 | minSdkVersion 16 9 | targetSdkVersion 22 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | } 14 | 15 | dependencies { 16 | compile 'com.facebook.react:react-native:0.19.+' 17 | compile 'com.google.android.gms:play-services-maps:8.4.0' 18 | compile 'com.google.maps.android:android-maps-utils:0.4' 19 | } 20 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /android/src/main/java/com/surialabs/rn/geofencing/GeoFencing.java: -------------------------------------------------------------------------------- 1 | package com.surialabs.rn.geofencing; 2 | 3 | import com.facebook.react.bridge.NativeModule; 4 | import com.facebook.react.bridge.ReactApplicationContext; 5 | import com.facebook.react.bridge.ReactContext; 6 | import com.facebook.react.bridge.ReactContextBaseJavaModule; 7 | import com.facebook.react.bridge.ReactMethod; 8 | import com.facebook.react.bridge.ReadableArray; 9 | import com.facebook.react.bridge.ReadableMap; 10 | import com.facebook.react.bridge.Callback; 11 | 12 | import com.google.maps.android.PolyUtil; 13 | import com.google.android.gms.maps.model.LatLng; 14 | import java.util.List; 15 | import java.util.ArrayList; 16 | 17 | public class GeoFencing extends ReactContextBaseJavaModule { 18 | public GeoFencing(ReactApplicationContext reactContext) { 19 | super(reactContext); 20 | } 21 | 22 | @Override 23 | public String getName() { 24 | return "SLRNGeoFencing"; 25 | } 26 | 27 | @ReactMethod 28 | public void containsLocation( 29 | ReadableMap point, 30 | ReadableArray polygon, 31 | Callback completionCallback) { 32 | 33 | LatLng locationPoint = new LatLng( 34 | point.getDouble("lat"), 35 | point.getDouble("lng") 36 | ); 37 | 38 | List polygonList = new ArrayList<>(); 39 | 40 | for (int i = 0; i < polygon.size(); i++) { 41 | ReadableMap vertex = polygon.getMap(i); 42 | polygonList.add( 43 | new LatLng( 44 | vertex.getDouble("lat"), 45 | vertex.getDouble("lng") 46 | ) 47 | ); 48 | } 49 | 50 | boolean isWithinCoverage = PolyUtil.containsLocation(locationPoint, polygonList, false); 51 | 52 | completionCallback.invoke(isWithinCoverage); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /android/src/main/java/com/surialabs/rn/geofencing/GeoFencingPackage.java: -------------------------------------------------------------------------------- 1 | package com.surialabs.rn.geofencing; 2 | 3 | import com.facebook.react.ReactPackage; 4 | import com.facebook.react.bridge.JavaScriptModule; 5 | import com.facebook.react.bridge.NativeModule; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.uimanager.ViewManager; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | public class GeoFencingPackage implements ReactPackage { 14 | @Override 15 | public List createNativeModules(ReactApplicationContext reactContext) { 16 | List modules = new ArrayList<>(); 17 | 18 | modules.add(new GeoFencing(reactContext)); 19 | 20 | return modules; 21 | } 22 | 23 | @Override 24 | public List> createJSModules() { 25 | return Collections.emptyList(); 26 | } 27 | 28 | @Override 29 | public List createViewManagers(ReactApplicationContext reactContext) { 30 | return Collections.emptyList(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /android/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | react-native-geo-fencing 3 | 4 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const GeoFencing = require('react-native').NativeModules.SLRNGeoFencing; 4 | 5 | module.exports = { 6 | containsLocation: function (point, polygon) { 7 | return new Promise(function (resolve, reject) { 8 | GeoFencing.containsLocation( 9 | point, 10 | polygon, 11 | isWithinCoverage => { 12 | if (isWithinCoverage) { 13 | resolve(true); 14 | } else { 15 | reject(); 16 | } 17 | } 18 | ) 19 | }); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /ios/SLRNGeoFencing.h: -------------------------------------------------------------------------------- 1 | #import "RCTBridgeModule.h" 2 | 3 | @interface SLRNGeoFencing : NSObject 4 | @end 5 | -------------------------------------------------------------------------------- /ios/SLRNGeoFencing.m: -------------------------------------------------------------------------------- 1 | #import "SLRNGeoFencing.h" 2 | #import 3 | #import 4 | 5 | @implementation SLRNGeoFencing 6 | 7 | RCT_EXPORT_MODULE(); 8 | 9 | RCT_EXPORT_METHOD( 10 | containsLocation:(NSDictionary *)point 11 | polygon:(NSArray *)polygon 12 | callback:(RCTResponseSenderBlock)callback) 13 | { 14 | 15 | CLLocationCoordinate2D locationPoint = CLLocationCoordinate2DMake( 16 | [[point objectForKey:@"lat"] doubleValue], 17 | [[point objectForKey:@"lng"] doubleValue] 18 | ); 19 | 20 | GMSMutablePath *polygonPath = [GMSMutablePath path]; 21 | 22 | for(int i = 0; i < [polygon count]; i++) { 23 | [polygonPath addCoordinate:CLLocationCoordinate2DMake( 24 | [[polygon[i] objectForKey:@"lat"] doubleValue], 25 | [[polygon[i] objectForKey:@"lng"] doubleValue] 26 | )]; 27 | } 28 | 29 | 30 | if (GMSGeometryContainsLocation(locationPoint, (GMSPath *)polygonPath, NO)) { 31 | // locationPoint is in polygonPath 32 | callback(@[@YES]); 33 | } else { 34 | // locationPoint is NOT in polygonPath. 35 | callback(@[@NO]); 36 | } 37 | } 38 | @end 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-geo-fencing", 3 | "version": "0.1.0", 4 | "description": "Native modules to determine if a location is within defined geographical boundaries using Google Geometry library", 5 | "main": "index.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "https://github.com/surialabs/react-native-geo-fencing.git" 9 | }, 10 | "keywords": [ 11 | "react-native", 12 | "googlemaps", 13 | "geometry", 14 | "polygon", 15 | "containsLocation", 16 | "geo-fencing" 17 | ], 18 | "author": "Chin Loong Tan ", 19 | "license": "MIT", 20 | "peerDependencies": { 21 | "react-native": ">=0.8.0" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /react-native-geo-fencing.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = "react-native-geo-fencing" 3 | s.author = { "Chin Loong Tan" => "chinloong.tan@surialabs.com" } 4 | 5 | s.version = "0.1.0" 6 | s.summary = "Native modules to determine if a location is within defined geographical boundaries using Google Geometry library" 7 | s.license = "MIT" 8 | 9 | s.homepage = "https://github.com/surialabs/react-native-geo-fencing" 10 | s.source = { git: "https://github.com/surialabs/react-native-geo-fencing.git", :tag => "#{s.version}" } 11 | 12 | s.requires_arc = true 13 | s.source_files = "ios/*" 14 | s.platform = :ios, "7.0" 15 | 16 | s.dependency "GoogleMaps" 17 | s.dependency "React" 18 | end 19 | -------------------------------------------------------------------------------- /screenshots/link_binaries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surialabs/react-native-geo-fencing/99f80981059e72ef92b630115ea4e44cdc88fa1e/screenshots/link_binaries.png -------------------------------------------------------------------------------- /screenshots/linker_flags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/surialabs/react-native-geo-fencing/99f80981059e72ef92b630115ea4e44cdc88fa1e/screenshots/linker_flags.png --------------------------------------------------------------------------------