├── .gitignore
├── LICENSE
├── README.md
├── RNLocation.h
├── RNLocation.js
├── RNLocation.m
├── RNLocation.xcodeproj
└── project.pbxproj
├── build.gradle
├── index.js
├── package.json
└── src
└── main
├── AndroidManifest.xml
└── java
└── com
└── syarul
└── rnlocation
├── RNLocation.java
└── RNLocationModule.java
/.gitignore:
--------------------------------------------------------------------------------
1 | ### SublimeText ###
2 | *.sublime-workspace
3 |
4 | ### OSX ###
5 | .DS_Store
6 | .AppleDouble
7 | .LSOverride
8 | Icon
9 |
10 | # Thumbnails
11 | ._*
12 |
13 | # Files that might appear on external disk
14 | .Spotlight-V100
15 | .Trashes
16 |
17 | ### Windows ###
18 | # Windows image file caches
19 | Thumbs.db
20 | ehthumbs.db
21 |
22 | # Folder config file
23 | Desktop.ini
24 |
25 | # Recycle Bin used on file shares
26 | $RECYCLE.BIN/
27 |
28 | # Webstorm
29 | .idea
30 |
31 | # App specific
32 |
33 | npm-debug.log
34 | node_modules/
35 | .tmp
36 | old
37 |
38 | # Binaries
39 | *.ipa
40 | *.zip
41 |
42 | # Xcode
43 | build/
44 | *.pbxuser
45 | !default.pbxuser
46 | *.mode1v3
47 | !default.mode1v3
48 | *.mode2v3
49 | !default.mode2v3
50 | *.perspectivev3
51 | !default.perspectivev3
52 | *.xcworkspace
53 | !default.xcworkspace
54 | xcuserdata
55 | profile
56 | *.moved-aside
57 | DerivedData
58 |
59 | .idea/
60 |
61 | # Pods - for those of you who use CocoaPods
62 | Pods
63 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Antonio Grass
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-native-gps
2 |
3 | Native GPS location support for React Native for Android and IOS. This module was inspired in project of [timfpark](https://github.com/timfpark/react-native-location) and [syarul](https://github.com/syarul/react-native-android-location). For the moment is not compatible for a PR back to one of that repositories because some methods are not implemented yet and some structure changed. Only a few methods are implemented so if you want to contribute, any contribution of new missing methods will be appreciated.
4 |
5 | ## Installation
6 | #### Install the npm package
7 | ```bash
8 | npm i --save https://github.com/agrass/react-native-gps
9 | ```
10 | ## IOS
11 | You then need to add the Objective C part to your XCode project. Drag `RNLocation.xcodeproj` from the `node_modules/react-native-location` folder into your XCode project. Click on the your project in XCode, goto Build Phases then Link Binary With Libraries and add `libRNLocation.a` and `CoreLocation.framework`.
12 |
13 | NOTE: Make sure you don't have the `RNLocation` project open separately in XCode otherwise it won't work.
14 |
15 | ### Android
16 |
17 | * In `android/settings.gradle`
18 |
19 | ```gradle
20 | ...
21 | include ':RNLocation'
22 | project(':RNLocation').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-gps')
23 | ```
24 |
25 | * In `android/app/build.gradle`
26 |
27 | ```gradle
28 | ...
29 | dependencies {
30 | ...
31 | compile project(':RNLocation')
32 | }
33 | ```
34 |
35 | * register module (in MainActivity.java)
36 |
37 | ```java
38 | import com.syarul.rnlocation.RNLocation; // <--- import
39 |
40 | public class MainActivity extends Activity implements DefaultHardwareBackBtnHandler {
41 | ......
42 |
43 | @Override
44 | protected void onCreate(Bundle savedInstanceState) {
45 | super.onCreate(savedInstanceState);
46 | mReactRootView = new ReactRootView(this);
47 |
48 | mReactInstanceManager = ReactInstanceManager.builder()
49 | .setApplication(getApplication())
50 | .setBundleAssetName("index.android.bundle")
51 | .setJSMainModuleName("index.android")
52 | .addPackage(new MainReactPackage())
53 | .addPackage(new RNLocation()) // <-- Register package here
54 | .setUseDeveloperSupport(BuildConfig.DEBUG)
55 | .setInitialLifecycleState(LifecycleState.RESUMED)
56 | .build();
57 |
58 | mReactRootView.startReactApplication(mReactInstanceManager, "example", null);
59 |
60 | setContentView(mReactRootView);
61 | }
62 |
63 | ......
64 |
65 | }
66 | ```
67 |
68 | #### Add permissions to your Project
69 |
70 | Add this to your AndroidManifest file;
71 |
72 | ``` xml
73 | // file: android/app/src/main/AndroidManifest.xml
74 |
75 |
76 | ```
77 |
78 | ## Location Usage
79 | ```javascript
80 | var React = require('react-native');
81 | var { DeviceEventEmitter } = React;
82 |
83 | var { RNLocation: Location } = require('NativeModules');
84 |
85 | Location.startUpdatingLocation();
86 |
87 | var subscription = DeviceEventEmitter.addListener(
88 | 'locationUpdated',
89 | (location) => {
90 | /* Example location returned
91 | {
92 | speed: -1,
93 | longitude: -0.1337,
94 | latitude: 51.50998,
95 | accuracy: 5,
96 | heading: -1,
97 | altitude: 0,
98 | altitudeAccuracy: -1
99 | }
100 | */
101 | }
102 | );
103 | ```
104 |
105 |
106 | ## Methods
107 |
108 | To access the methods, you need import the `react-native-location` module.
109 |
110 | ### Location.requestWhenInUseAuthorization
111 | ```javascript
112 | Location.requestWhenInUseAuthorization();
113 | ```
114 |
115 | This method should be called before anything else. It requests location updates while the application is open. If the application is in the background, you will not get location updates (for the moment, background work not implemented yet).
116 |
117 | ### Location.startUpdatingLocation
118 | ```javascript
119 | Location.startUpdatingLocation();
120 | var subscription = DeviceEventEmitter.addListener(
121 | 'locationUpdated',
122 | (location) => {
123 | // do something with the location
124 | }
125 | );
126 | ```
127 |
128 | ### Location.stopUpdatingLocation
129 | ```javascript
130 | Location.stopUpdatingLocation();
131 | ```
132 | ## License
133 | MIT, for more information see `LICENSE`
134 |
--------------------------------------------------------------------------------
/RNLocation.h:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | @interface RNLocation : NSObject
4 |
5 | @end
6 |
--------------------------------------------------------------------------------
/RNLocation.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Stub of RNLocation for Android.
3 | *
4 | * @providesModule RNLocation
5 | * @flow
6 | */
7 |
8 | 'use strict';
9 |
10 | var { NativeModules } = require('react-native');
11 | module.exports = NativeModules.RNLocation;
12 |
--------------------------------------------------------------------------------
/RNLocation.m:
--------------------------------------------------------------------------------
1 | #import
2 |
3 | #import
4 | #import
5 | #import
6 |
7 | #import "RNLocation.h"
8 |
9 | @interface RNLocation()
10 |
11 | @property (strong, nonatomic) CLLocationManager *locationManager;
12 |
13 | @end
14 |
15 | @implementation RNLocation
16 |
17 | RCT_EXPORT_MODULE()
18 |
19 | @synthesize bridge = _bridge;
20 |
21 | #pragma mark Initialization
22 |
23 | - (instancetype)init
24 | {
25 | if (self = [super init]) {
26 | self.locationManager = [[CLLocationManager alloc] init];
27 |
28 | self.locationManager.delegate = self;
29 |
30 | self.locationManager.distanceFilter = kCLDistanceFilterNone;
31 | self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
32 |
33 | self.locationManager.pausesLocationUpdatesAutomatically = NO;
34 | }
35 |
36 | return self;
37 | }
38 |
39 | #pragma mark
40 |
41 | RCT_EXPORT_METHOD(requestAlwaysAuthorization)
42 | {
43 | NSLog(@"react-native-location: requestAlwaysAuthorization");
44 | [self.locationManager requestAlwaysAuthorization];
45 | }
46 |
47 | RCT_EXPORT_METHOD(requestWhenInUseAuthorization)
48 | {
49 | NSLog(@"react-native-location: requestWhenInUseAuthorization");
50 | [self.locationManager requestWhenInUseAuthorization];
51 | }
52 |
53 | RCT_EXPORT_METHOD(getAuthorizationStatus:(RCTResponseSenderBlock)callback)
54 | {
55 | callback(@[[self nameForAuthorizationStatus:[CLLocationManager authorizationStatus]]]);
56 | }
57 |
58 | RCT_EXPORT_METHOD(setDesiredAccuracy:(double) accuracy)
59 | {
60 | self.locationManager.desiredAccuracy = accuracy;
61 | }
62 |
63 | RCT_EXPORT_METHOD(setDistanceFilter:(double) distance)
64 | {
65 | self.locationManager.distanceFilter = distance;
66 | }
67 |
68 | RCT_EXPORT_METHOD(setAllowsBackgroundLocationUpdates:(BOOL) enabled)
69 | {
70 | self.locationManager.allowsBackgroundLocationUpdates = enabled;
71 | }
72 |
73 | RCT_EXPORT_METHOD(startMonitoringSignificantLocationChanges)
74 | {
75 | NSLog(@"react-native-location: startMonitoringSignificantLocationChanges");
76 | [self.locationManager startMonitoringSignificantLocationChanges];
77 | }
78 |
79 | RCT_EXPORT_METHOD(startUpdatingLocation)
80 | {
81 | [self.locationManager startUpdatingLocation];
82 | }
83 |
84 | RCT_EXPORT_METHOD(startUpdatingHeading)
85 | {
86 | [self.locationManager startUpdatingHeading];
87 | }
88 |
89 | RCT_EXPORT_METHOD(stopMonitoringSignificantLocationChanges)
90 | {
91 | [self.locationManager stopMonitoringSignificantLocationChanges];
92 | }
93 |
94 | RCT_EXPORT_METHOD(stopUpdatingLocation)
95 | {
96 | [self.locationManager stopUpdatingLocation];
97 | }
98 |
99 | RCT_EXPORT_METHOD(stopUpdatingHeading)
100 | {
101 | [self.locationManager stopUpdatingHeading];
102 | }
103 |
104 | -(NSString *)nameForAuthorizationStatus:(CLAuthorizationStatus)authorizationStatus
105 | {
106 | switch (authorizationStatus) {
107 | case kCLAuthorizationStatusAuthorizedAlways:
108 | NSLog(@"Authorization Status: authorizedAlways");
109 | return @"authorizedAlways";
110 |
111 | case kCLAuthorizationStatusAuthorizedWhenInUse:
112 | NSLog(@"Authorization Status: authorizedWhenInUse");
113 | return @"authorizedWhenInUse";
114 |
115 | case kCLAuthorizationStatusDenied:
116 | NSLog(@"Authorization Status: denied");
117 | return @"denied";
118 |
119 | case kCLAuthorizationStatusNotDetermined:
120 | NSLog(@"Authorization Status: notDetermined");
121 | return @"notDetermined";
122 |
123 | case kCLAuthorizationStatusRestricted:
124 | NSLog(@"Authorization Status: restricted");
125 | return @"restricted";
126 | }
127 | }
128 |
129 | -(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status
130 | {
131 | NSString *statusName = [self nameForAuthorizationStatus:status];
132 | [self.bridge.eventDispatcher sendDeviceEventWithName:@"authorizationStatusDidChange" body:statusName];
133 | }
134 |
135 | - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
136 | NSLog(@"Location manager failed: %@", error);
137 | }
138 |
139 | - (void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading {
140 | if (newHeading.headingAccuracy < 0)
141 | return;
142 |
143 | // Use the true heading if it is valid.
144 | CLLocationDirection heading = ((newHeading.trueHeading > 0) ?
145 | newHeading.trueHeading : newHeading.magneticHeading);
146 |
147 | NSDictionary *headingEvent = @{
148 | @"heading": @(heading)
149 | };
150 |
151 | NSLog(@"heading: %f", heading);
152 | [self.bridge.eventDispatcher sendDeviceEventWithName:@"headingUpdated" body:headingEvent];
153 | }
154 |
155 | - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
156 | CLLocation *location = [locations lastObject];
157 | NSDictionary *locationEvent = @{
158 | @"latitude": @(location.coordinate.latitude),
159 | @"longitude": @(location.coordinate.longitude),
160 | @"altitude": @(location.altitude),
161 | @"accuracy": @(location.horizontalAccuracy),
162 | @"altitudeAccuracy": @(location.verticalAccuracy),
163 | @"course": @(location.course),
164 | @"speed": @(location.speed),
165 | @"timestamp": @([location.timestamp timeIntervalSince1970] * 1000) // in ms
166 | };
167 |
168 | NSLog(@"%@: lat: %f, long: %f, altitude: %f", location.timestamp, location.coordinate.latitude, location.coordinate.longitude, location.altitude);
169 | [self.bridge.eventDispatcher sendDeviceEventWithName:@"locationUpdated" body:locationEvent];
170 | }
171 | @end
172 |
--------------------------------------------------------------------------------
/RNLocation.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 13BE3DEE1AC21097009241FE /* RNLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* RNLocation.m */; };
11 | /* End PBXBuildFile section */
12 |
13 | /* Begin PBXCopyFilesBuildPhase section */
14 | 58B511D91A9E6C8500147676 /* CopyFiles */ = {
15 | isa = PBXCopyFilesBuildPhase;
16 | buildActionMask = 2147483647;
17 | dstPath = "include/$(PRODUCT_NAME)";
18 | dstSubfolderSpec = 16;
19 | files = (
20 | );
21 | runOnlyForDeploymentPostprocessing = 0;
22 | };
23 | /* End PBXCopyFilesBuildPhase section */
24 |
25 | /* Begin PBXFileReference section */
26 | 134814201AA4EA6300B7C361 /* libRNLocation.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNLocation.a; sourceTree = BUILT_PRODUCTS_DIR; };
27 | 13BE3DEC1AC21097009241FE /* RNLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNLocation.h; sourceTree = ""; };
28 | 13BE3DED1AC21097009241FE /* RNLocation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNLocation.m; sourceTree = ""; };
29 | /* End PBXFileReference section */
30 |
31 | /* Begin PBXFrameworksBuildPhase section */
32 | 58B511D81A9E6C8500147676 /* Frameworks */ = {
33 | isa = PBXFrameworksBuildPhase;
34 | buildActionMask = 2147483647;
35 | files = (
36 | );
37 | runOnlyForDeploymentPostprocessing = 0;
38 | };
39 | /* End PBXFrameworksBuildPhase section */
40 |
41 | /* Begin PBXGroup section */
42 | 134814211AA4EA7D00B7C361 /* Products */ = {
43 | isa = PBXGroup;
44 | children = (
45 | 134814201AA4EA6300B7C361 /* libRNLocation.a */,
46 | );
47 | name = Products;
48 | sourceTree = "";
49 | };
50 | 58B511D21A9E6C8500147676 = {
51 | isa = PBXGroup;
52 | children = (
53 | 13BE3DEC1AC21097009241FE /* RNLocation.h */,
54 | 13BE3DED1AC21097009241FE /* RNLocation.m */,
55 | 134814211AA4EA7D00B7C361 /* Products */,
56 | );
57 | sourceTree = "";
58 | };
59 | /* End PBXGroup section */
60 |
61 | /* Begin PBXNativeTarget section */
62 | 58B511DA1A9E6C8500147676 /* RNLocation */ = {
63 | isa = PBXNativeTarget;
64 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNLocation" */;
65 | buildPhases = (
66 | 58B511D71A9E6C8500147676 /* Sources */,
67 | 58B511D81A9E6C8500147676 /* Frameworks */,
68 | 58B511D91A9E6C8500147676 /* CopyFiles */,
69 | );
70 | buildRules = (
71 | );
72 | dependencies = (
73 | );
74 | name = RNLocation;
75 | productName = RCTDataManager;
76 | productReference = 134814201AA4EA6300B7C361 /* libRNLocation.a */;
77 | productType = "com.apple.product-type.library.static";
78 | };
79 | /* End PBXNativeTarget section */
80 |
81 | /* Begin PBXProject section */
82 | 58B511D31A9E6C8500147676 /* Project object */ = {
83 | isa = PBXProject;
84 | attributes = {
85 | LastUpgradeCheck = 0610;
86 | ORGANIZATIONNAME = Facebook;
87 | TargetAttributes = {
88 | 58B511DA1A9E6C8500147676 = {
89 | CreatedOnToolsVersion = 6.1.1;
90 | };
91 | };
92 | };
93 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNLocation" */;
94 | compatibilityVersion = "Xcode 3.2";
95 | developmentRegion = English;
96 | hasScannedForEncodings = 0;
97 | knownRegions = (
98 | en,
99 | );
100 | mainGroup = 58B511D21A9E6C8500147676;
101 | productRefGroup = 58B511D21A9E6C8500147676;
102 | projectDirPath = "";
103 | projectRoot = "";
104 | targets = (
105 | 58B511DA1A9E6C8500147676 /* RNLocation */,
106 | );
107 | };
108 | /* End PBXProject section */
109 |
110 | /* Begin PBXSourcesBuildPhase section */
111 | 58B511D71A9E6C8500147676 /* Sources */ = {
112 | isa = PBXSourcesBuildPhase;
113 | buildActionMask = 2147483647;
114 | files = (
115 | 13BE3DEE1AC21097009241FE /* RNLocation.m in Sources */,
116 | );
117 | runOnlyForDeploymentPostprocessing = 0;
118 | };
119 | /* End PBXSourcesBuildPhase section */
120 |
121 | /* Begin XCBuildConfiguration section */
122 | 58B511ED1A9E6C8500147676 /* Debug */ = {
123 | isa = XCBuildConfiguration;
124 | buildSettings = {
125 | ALWAYS_SEARCH_USER_PATHS = NO;
126 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
127 | CLANG_CXX_LIBRARY = "libc++";
128 | CLANG_ENABLE_MODULES = YES;
129 | CLANG_ENABLE_OBJC_ARC = YES;
130 | CLANG_WARN_BOOL_CONVERSION = YES;
131 | CLANG_WARN_CONSTANT_CONVERSION = YES;
132 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
133 | CLANG_WARN_EMPTY_BODY = YES;
134 | CLANG_WARN_ENUM_CONVERSION = YES;
135 | CLANG_WARN_INT_CONVERSION = YES;
136 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
137 | CLANG_WARN_UNREACHABLE_CODE = YES;
138 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
139 | COPY_PHASE_STRIP = NO;
140 | ENABLE_STRICT_OBJC_MSGSEND = YES;
141 | GCC_C_LANGUAGE_STANDARD = gnu99;
142 | GCC_DYNAMIC_NO_PIC = NO;
143 | GCC_OPTIMIZATION_LEVEL = 0;
144 | GCC_PREPROCESSOR_DEFINITIONS = (
145 | "DEBUG=1",
146 | "$(inherited)",
147 | );
148 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
149 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
150 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
151 | GCC_WARN_UNDECLARED_SELECTOR = YES;
152 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
153 | GCC_WARN_UNUSED_FUNCTION = YES;
154 | GCC_WARN_UNUSED_VARIABLE = YES;
155 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
156 | MTL_ENABLE_DEBUG_INFO = YES;
157 | ONLY_ACTIVE_ARCH = YES;
158 | SDKROOT = iphoneos;
159 | };
160 | name = Debug;
161 | };
162 | 58B511EE1A9E6C8500147676 /* Release */ = {
163 | isa = XCBuildConfiguration;
164 | buildSettings = {
165 | ALWAYS_SEARCH_USER_PATHS = NO;
166 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
167 | CLANG_CXX_LIBRARY = "libc++";
168 | CLANG_ENABLE_MODULES = YES;
169 | CLANG_ENABLE_OBJC_ARC = YES;
170 | CLANG_WARN_BOOL_CONVERSION = YES;
171 | CLANG_WARN_CONSTANT_CONVERSION = YES;
172 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
173 | CLANG_WARN_EMPTY_BODY = YES;
174 | CLANG_WARN_ENUM_CONVERSION = YES;
175 | CLANG_WARN_INT_CONVERSION = YES;
176 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
177 | CLANG_WARN_UNREACHABLE_CODE = YES;
178 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
179 | COPY_PHASE_STRIP = YES;
180 | ENABLE_NS_ASSERTIONS = NO;
181 | ENABLE_STRICT_OBJC_MSGSEND = YES;
182 | GCC_C_LANGUAGE_STANDARD = gnu99;
183 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
184 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
185 | GCC_WARN_UNDECLARED_SELECTOR = YES;
186 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
187 | GCC_WARN_UNUSED_FUNCTION = YES;
188 | GCC_WARN_UNUSED_VARIABLE = YES;
189 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
190 | MTL_ENABLE_DEBUG_INFO = NO;
191 | SDKROOT = iphoneos;
192 | VALIDATE_PRODUCT = YES;
193 | };
194 | name = Release;
195 | };
196 | 58B511F01A9E6C8500147676 /* Debug */ = {
197 | isa = XCBuildConfiguration;
198 | buildSettings = {
199 | HEADER_SEARCH_PATHS = (
200 | "$(inherited)",
201 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
202 | "$(SRCROOT)/../../React/**",
203 | "$(SRCROOT)/node_modules/react-native/React/**",
204 | "$(SRCROOT)/../react-native/React/**",
205 | );
206 | LIBRARY_SEARCH_PATHS = "$(inherited)";
207 | OTHER_LDFLAGS = "-ObjC";
208 | PRODUCT_NAME = RNLocation;
209 | SKIP_INSTALL = YES;
210 | USER_HEADER_SEARCH_PATHS = "";
211 | };
212 | name = Debug;
213 | };
214 | 58B511F11A9E6C8500147676 /* Release */ = {
215 | isa = XCBuildConfiguration;
216 | buildSettings = {
217 | HEADER_SEARCH_PATHS = (
218 | "$(inherited)",
219 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
220 | "$(SRCROOT)/../../React/**",
221 | "$(SRCROOT)/node_modules/react-native/React/**",
222 | "$(SRCROOT)/../react-native/React/**",
223 | );
224 | LIBRARY_SEARCH_PATHS = "$(inherited)";
225 | OTHER_LDFLAGS = "-ObjC";
226 | PRODUCT_NAME = RNLocation;
227 | SKIP_INSTALL = YES;
228 | USER_HEADER_SEARCH_PATHS = "";
229 | };
230 | name = Release;
231 | };
232 | /* End XCBuildConfiguration section */
233 |
234 | /* Begin XCConfigurationList section */
235 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNLocation" */ = {
236 | isa = XCConfigurationList;
237 | buildConfigurations = (
238 | 58B511ED1A9E6C8500147676 /* Debug */,
239 | 58B511EE1A9E6C8500147676 /* Release */,
240 | );
241 | defaultConfigurationIsVisible = 0;
242 | defaultConfigurationName = Release;
243 | };
244 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNLocation" */ = {
245 | isa = XCConfigurationList;
246 | buildConfigurations = (
247 | 58B511F01A9E6C8500147676 /* Debug */,
248 | 58B511F11A9E6C8500147676 /* Release */,
249 | );
250 | defaultConfigurationIsVisible = 0;
251 | defaultConfigurationName = Release;
252 | };
253 | /* End XCConfigurationList section */
254 | };
255 | rootObject = 58B511D31A9E6C8500147676 /* Project object */;
256 | }
257 |
--------------------------------------------------------------------------------
/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.11.+'
17 | }
18 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Stub of RNLocation for Android.
3 | *
4 | * @providesModule RNLocation
5 | * @flow
6 | */
7 |
8 | 'use strict';
9 |
10 | var { NativeModules } = require('react-native');
11 | module.exports = NativeModules.RNLocation;
12 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-native-gps",
3 | "version": "0.1.2",
4 | "devDependencies": {
5 | "react-native": "^0.14"
6 | },
7 | "repository": {
8 | "type": "git",
9 | "url": "https://github.com/agrass/react-native-gps.git"
10 | },
11 | "license": "MIT",
12 | "keywords": [
13 | "react-native",
14 | "react-component",
15 | "ios",
16 | "location"
17 | ],
18 | "main": "RNLocation.js"
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/main/java/com/syarul/rnlocation/RNLocation.java:
--------------------------------------------------------------------------------
1 | package com.syarul.rnlocation;
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 | import com.syarul.rnlocation.RNLocationModule;
9 |
10 | import java.util.Arrays;
11 | import java.util.Collections;
12 | import java.util.List;
13 |
14 | public class RNLocation implements ReactPackage {
15 | @Override
16 | public List createNativeModules( ReactApplicationContext reactContext) {
17 | return Arrays.asList(
18 | new RNLocationModule(reactContext)
19 | );
20 | }
21 | @Override
22 | public List> createJSModules() {
23 | return Collections.emptyList();
24 | }
25 | @Override
26 | public List createViewManagers(ReactApplicationContext reactApplicationContext) {
27 | return Collections.emptyList();
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/syarul/rnlocation/RNLocationModule.java:
--------------------------------------------------------------------------------
1 | package com.syarul.rnlocation;
2 |
3 | import android.location.Location;
4 | import android.location.LocationManager;
5 | import android.location.LocationListener;
6 | import android.content.Context;
7 | import android.support.annotation.Nullable;
8 | import android.util.Log;
9 | import android.os.Bundle;
10 |
11 | import com.facebook.react.bridge.Arguments;
12 | import com.facebook.react.bridge.ReactApplicationContext;
13 | import com.facebook.react.bridge.ReactContext;
14 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
15 | import com.facebook.react.bridge.ReactMethod;
16 | import com.facebook.react.bridge.ReadableMap;
17 | import com.facebook.react.bridge.WritableMap;
18 | import com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter;
19 |
20 | public class RNLocationModule extends ReactContextBaseJavaModule{
21 |
22 | // React Class Name as called from JS
23 | public static final String REACT_CLASS = "RNLocation";
24 | // Unique Name for Log TAG
25 | public static final String TAG = RNLocationModule.class.getSimpleName();
26 |
27 | private static final float RCT_DEFAULT_LOCATION_ACCURACY = 1;
28 | public static int POSITION_UNAVAILABLE = 2;
29 |
30 | // Save last Location Provided
31 | private Location mLastLocation;
32 | private LocationListener mLocationListener;
33 | private LocationManager locationManager;
34 |
35 | //The React Native Context
36 | ReactApplicationContext mReactContext;
37 |
38 |
39 | // Constructor Method as called in Package
40 | public RNLocationModule(ReactApplicationContext reactContext) {
41 | super(reactContext);
42 | // Save Context for later use
43 | mReactContext = reactContext;
44 |
45 | locationManager = (LocationManager) mReactContext.getSystemService(Context.LOCATION_SERVICE);
46 | }
47 |
48 |
49 | @Override
50 | public String getName() {
51 | return REACT_CLASS;
52 | }
53 |
54 | private static class LocationOptions {
55 | private final long timeout;
56 | private final double maximumAge;
57 | private final boolean highAccuracy;
58 | private final float distanceFilter;
59 |
60 | private LocationOptions(
61 | long timeout,
62 | double maximumAge,
63 | boolean highAccuracy,
64 | float distanceFilter) {
65 | this.timeout = timeout;
66 | this.maximumAge = maximumAge;
67 | this.highAccuracy = highAccuracy;
68 | this.distanceFilter = distanceFilter;
69 | }
70 |
71 | private static LocationOptions fromReactMap(ReadableMap map) {
72 | // precision might be dropped on timeout (double -> int conversion), but that's OK
73 | long timeout =
74 | map.hasKey("timeout") ? (long) map.getDouble("timeout") : Long.MAX_VALUE;
75 | double maximumAge =
76 | map.hasKey("maximumAge") ? map.getDouble("maximumAge") : Double.POSITIVE_INFINITY;
77 | boolean highAccuracy = !map.hasKey("enableHighAccuracy") || map.getBoolean("enableHighAccuracy");
78 | float distanceFilter = map.hasKey("distanceFilter") ?
79 | (float) map.getDouble("distanceFilter") :
80 | RCT_DEFAULT_LOCATION_ACCURACY;
81 |
82 | return new LocationOptions(timeout, maximumAge, highAccuracy, distanceFilter);
83 | }
84 | }
85 |
86 | /*
87 | * Location permission request (Not implemented yet)
88 | */
89 | @ReactMethod
90 | public void requestWhenInUseAuthorization(){
91 | Log.i(TAG, "Requesting authorization");
92 | }
93 |
94 | @Nullable
95 | private static String getValidProvider(LocationManager locationManager, boolean highAccuracy) {
96 | String provider =
97 | highAccuracy ? LocationManager.GPS_PROVIDER : LocationManager.NETWORK_PROVIDER;
98 | if (!locationManager.isProviderEnabled(provider)) {
99 | provider = provider.equals(LocationManager.GPS_PROVIDER)
100 | ? LocationManager.NETWORK_PROVIDER
101 | : LocationManager.GPS_PROVIDER;
102 | if (!locationManager.isProviderEnabled(provider)) {
103 | return null;
104 | }
105 | }
106 | return provider;
107 | }
108 |
109 | private void emitError(int code, String message) {
110 | WritableMap error = Arguments.createMap();
111 | error.putInt("code", code);
112 |
113 | if (message != null) {
114 | error.putString("message", message);
115 | }
116 |
117 | getReactApplicationContext().getJSModule(RCTDeviceEventEmitter.class)
118 | .emit("geolocationError", error);
119 | }
120 |
121 | /*
122 | * Location Callback as called by JS
123 | */
124 | @ReactMethod
125 | public void startUpdatingLocation(ReadableMap options) {
126 | LocationOptions locationOptions = LocationOptions.fromReactMap(options);
127 | String provider = getValidProvider(locationManager, locationOptions.highAccuracy);
128 |
129 | if (provider == null) {
130 | emitError(POSITION_UNAVAILABLE, "No location provider available.");
131 | return;
132 | }
133 |
134 | mLocationListener = new LocationListener(){
135 | @Override
136 | public void onStatusChanged(String provider,int status,Bundle extras){
137 | WritableMap params = Arguments.createMap();
138 | params.putString("provider", provider);
139 | params.putInt("status", status);
140 |
141 | sendEvent(mReactContext, "providerStatusChanged", params);
142 | }
143 |
144 | @Override
145 | public void onProviderEnabled(String provider){
146 | sendEvent(mReactContext, "providerEnabled", Arguments.createMap());
147 | }
148 |
149 | @Override
150 | public void onProviderDisabled(String provider){
151 | sendEvent(mReactContext, "providerDisabled", Arguments.createMap());
152 | }
153 |
154 | @Override
155 | public void onLocationChanged(Location loc){
156 | mLastLocation = loc;
157 | if (mLastLocation != null) {
158 | try {
159 | double longitude;
160 | double latitude;
161 | double speed;
162 | double altitude;
163 | double accuracy;
164 | double course;
165 |
166 | // Receive Longitude / Latitude from (updated) Last Location
167 | longitude = mLastLocation.getLongitude();
168 | latitude = mLastLocation.getLatitude();
169 | speed = mLastLocation.getSpeed();
170 | altitude = mLastLocation.getAltitude();
171 | accuracy = mLastLocation.getAccuracy();
172 | course = mLastLocation.getBearing();
173 |
174 | Log.i(TAG, "Got new location. Lng: " +longitude+" Lat: "+latitude);
175 |
176 | // Create Map with Parameters to send to JS
177 | WritableMap params = Arguments.createMap();
178 | params.putDouble("longitude", longitude);
179 | params.putDouble("latitude", latitude);
180 | params.putDouble("speed", speed);
181 | params.putDouble("altitude", altitude);
182 | params.putDouble("accuracy", accuracy);
183 | params.putDouble("course", course);
184 |
185 | // Send Event to JS to update Location
186 | sendEvent(mReactContext, "locationUpdated", params);
187 | } catch (Exception e) {
188 | e.printStackTrace();
189 | Log.i(TAG, "Location services disconnected.");
190 | }
191 | }
192 | }
193 | };
194 |
195 | locationManager.requestLocationUpdates(provider, 1000, locationOptions.distanceFilter, mLocationListener);
196 | }
197 |
198 | @ReactMethod
199 | public void stopUpdatingLocation() {
200 | try {
201 | locationManager.removeUpdates(mLocationListener);
202 | Log.i(TAG, "Location service disabled.");
203 | }catch(Exception e) {
204 | e.printStackTrace();
205 | }
206 | }
207 |
208 | /*
209 | * Internal function for communicating with JS
210 | */
211 | private void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params) {
212 | if (reactContext.hasActiveCatalystInstance()) {
213 | reactContext
214 | .getJSModule(RCTDeviceEventEmitter.class)
215 | .emit(eventName, params);
216 | } else {
217 | Log.i(TAG, "Waiting for CatalystInstance...");
218 | }
219 | }
220 | }
221 |
--------------------------------------------------------------------------------