Repository: MustansirZia/react-native-fused-location
Branch: master
Commit: 33cbe207e833
Files: 15
Total size: 34.0 KB
Directory structure:
gitextract_d7nogs51/
├── .eslintrc.js
├── .gitignore
├── .npmignore
├── .prettierrc.js
├── .vscode/
│ └── settings.json
├── CHANGELOG.md
├── LICENSE.txt
├── README.md
├── android/
│ ├── build.gradle
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ └── java/
│ └── com/
│ └── mustansirzia/
│ └── fused/
│ ├── FusedLocationModule.java
│ └── FusedLocationPackage.java
├── package.json
├── src/
│ └── index.ts
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .eslintrc.js
================================================
module.exports = {
parser: '@typescript-eslint/parser',
extends: [
'plugin:@typescript-eslint/recommended',
'prettier/@typescript-eslint',
'plugin:prettier/recommended',
],
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
},
ignorePatterns: ["lib/**"],
rules: {},
};
================================================
FILE: .gitignore
================================================
node_modules
npm-debug.log
.idea
android/android.iml
android/build/*
android/gradle/*
android/.gradle/*
android/gradlew
android/gradlew.bat
android/local.properties
lib
================================================
FILE: .npmignore
================================================
# From .gitignore.
node_modules
npm-debug.log
.idea
android/android.iml
android/build/*
android/gradle/*
android/.gradle/*
android/gradlew
android/gradlew.bat
android/local.properties
# Ones we don't want published to npm.
src/*
.vscode
tsconfig.json
.eslintrc.js
.prettierrc.js
yarn.lock
================================================
FILE: .prettierrc.js
================================================
module.exports = {
semi: true,
trailingComma: 'all',
singleQuote: true,
printWidth: 120,
tabWidth: 4
};
================================================
FILE: .vscode/settings.json
================================================
{
"eslint.autoFixOnSave": true,
"eslint.validate": [
"javascript",
{
"language": "typescript",
"autoFix": true
},
],
"editor.formatOnSave": true,
"[javascript]": {
"editor.formatOnSave": false,
},
"[javascriptreact]": {
"editor.formatOnSave": false,
},
"[typescript]": {
"editor.formatOnSave": false,
},
"[typescriptreact]": {
"editor.formatOnSave": false,
},
}
================================================
FILE: CHANGELOG.md
================================================
## Release Notes.
### 1.1.1
° `forceNewLocation` argument made optional for `getFusedLocation` function call.
### 1.0.0 - BREAKING CHANGE.
° Support library migrated to AndroidX namespace.
° Added support for Typescript. ❤️
### 0.5.0
° Google play services version can now be overriden and is defaulted to `16.+`.
° Android gradle version updated to `3.3.2`.
• Compile SDK version defaulted to `28`.
• Build tools version defaulted to `28.0.3`.
### 0.4.0
° `BuildToolsVersion` and `sdkVersion` are now taken from the main android project's gradle file.
### 0.2.0
° `LocationCallback` added instead of `LocationListener` to method `getFusedLocation()` when last location returned null or forceNewLocation was set to true. This would guarantee the promise is resolved or rejected depending upon location availability.
### 0.1.0
° Made `areProvidersAvailable` method public under `FusedLocation.areProvidersAvailable()`.
° Semver for this repo started.
### 0.0.11
° Add `timestamp` via [`getTime()`](https://developer.android.com/reference/android/location/Location.html#getTime()) to the `location` object. Returns the UNIX timestamp (in millis) of when the location was generated.
### 0.0.8
° Added `forceNewLocation` as an optional argument to `getFusedLocation`. This gets a new location everytime and never reuses a last known location.
° Added a check if GPS Provider or Network Provider exists on the device. Useful on emulators where `getFusedLocation` used to hang when GPS was turned off.
° Added `mocked` property to the `Location` object.
• PR for #1 and #3 from - https://github.com/ginosi.
### 0.0.5
° Fixed typo in ReadMe. Changed `setLocationFatestInterval` to `setFastestLocationInterval` in js example.
### 0.0.4
° Fixed typo in ReadMe. Changed `FusedLocation` to `FusedLocationPackage` in manual linking.
PR by - https://github.com/jarvisluong
### 0.0.3
° Default values added to Readme.
### 0.0.2
° iOS compatibility fixes.
### 0.0.1
° Initial Commit.
================================================
FILE: LICENSE.txt
================================================
MIT License
Copyright (c) 2017 Mustansir Zia
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# react-native-fused-location
[](https://badge.fury.io/js/react-native-fused-location)
[](https://www.npmjs.com/package/react-native-fused-location)
[](http://packagequality.com/#?package=react-native-fused-location)
[](https://opensource.org/licenses/mit-license.php)
Get the finest location on Android using Fused API.
I created this react native module with an inspiration that none of react native's location libraries use the newer Fused API to get location. According to google, it is the most accurate way to get location in an Android device and judges by itself when to use GPS or cell towers/wifi. Thus, it works with both.
## Install
`npm install react-native-fused-location --save`
or
`yarn add react-native-fused-location`
#### Automatic Link.
`react-native link react-native-fused-location`
#### Manual Link.
• in `android/app/build.gradle:`
```diff
dependencies {
...
compile "com.facebook.react:react-native:+" // From node_modules
+ compile project(':react-native-fused-location')
}
```
• in `android/settings.gradle`:
```diff
...
include ':app'
+ include ':react-native-fused-location'
+ project(':react-native-fused-location').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fused-location/android')
```
• in `MainApplication.java:`
```diff
+ import com.mustansirzia.fused.FusedLocationPackage;
@Override
protected List getPackages() {
return Arrays.asList(
...
+ new FusedLocationPackage(),
...
new MainReactPackage()
);
}
```
#### Migration to AndroidX. - BREAKING CHANGE in `1.0.0`.
• Version `1.0.0` and above of this libary now makes use of AndroidX namespace instead of the legacy android support library namespace. If your app hasn't migrated to AndroidX yet, consider doing so or instead use an older version of this library such as `0.5.1`. React Native `0.59` uses AndroidX.
To enable AndroidX add these two lines in your `android/gradle.properties` file.
```properties
android.useAndroidX=true
android.enableJetifier=true
```
If this doesn't work out. Check out [this](https://developer.android.com/jetpack/androidx/migrate) official guide from Google.
A guide more specific to React Native would be [here](https://itnext.io/react-native-how-to-handle-an-app-with-both-pre-androidx-and-androidx-dependencies-rn60-bf4df7ea0dd2).
## Permissions.
Add this to your `AndroidManifest.xml`:
```xml
...
...
...
```
## Usage.
### API.
| Function | Arguments | Returns | Note |
|:---|:---:|:---:|:------|
| `getFusedLocation` | `forceNewLocation` | `Promise[Location]` | Call this once to get `Location`. Pass optional boolean `forceNewLocation` to get new location update. Otherwise return the last known location. Returns a promise.
| `startLocationUpdates` | Nil | `Promise[Nil]` | Call this to start receiving location updates. The function returns a promise that will resolve after the bootstrap of the Fused provider is done.
**Note: You still need to subscribe to `fusedLocation` event.
So, you need to call this before you call `FusedLocation.on`.
| `stopLocationUpdates` | Nil | `Promise[Boolean]` | Stop receiving location updates. Call this to stop listening to device's location updates. The function returns a promise that will resolve to a boolean reflecting if the updates were indeed stoped or not (if they were already stopped beforehand).
| `on` | `eventName, callback` | `Subscription` | Subscribe to an event. The callback is called with `Location` updates if the eventName is `fusedLocation`.
Call this after you call `startLocationUpdates`
| `off` | `Subscription` | Nil | Unsubscribe from the corresponding subscription.
| `areProvidersAvailable` | Nil | `Promise[Boolean]` | Returns a promise that will always resolve to a boolean value. The resolved value reflects the providers' availability; true when location providers are available and false otherwise.
### Configuration.
#### `setLocationPriority(priority)`
Set location accuracy. `priority` be of the following types.
`FusedLocation.Constants.HIGH_ACCURACY` Most accurate. Least battery efficient. Uses GPS only.
`FusedLocation.Constants.BALANCED` Mixed. Chooses an appropriate provider.
`FusedLocation.Constants.LOW_POWER` Least accurate. Most battery efficient. Uses Wifi/Cell Towers only.
`FusedLocation.Constants.NO_POWER` Uses location updates from other apps (if they occur). Don't request location from your app.
• Default `FusedLocation.Constants.BALANCED`
#### `setLocationInterval(interval)`
Set an approximate interval (in milliseconds) between each location updates. Please note that this interval may not be strictly followed. Updates may come faster or slower than the interval argument.
• Default `15000`
#### `setFastestLocationInterval(interval)`
Set the minimum possible interval between location updates (in milliseconds).
• Default `10000`
#### `setSmallestDisplacement(displacement)`
Set smallest amount of displacement (in meters) to occur after which the location update will be received.
• Default `0`
For more info, see here.
### Types.
```
type Location {
latitude: Number,
longitude: Number,
speed: Number,
altitude: Number,
provider: String,
accuracy: Number,
bearing: Number,
mocked: Boolean,
timestamp: String
}
```
```
type Subscription {
listener: Function,
eventName: String
}
```
### Example.
```js
...
import FusedLocation from 'react-native-fused-location';
...
async componentDidMount() {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION, {
title: 'App needs to access your location',
message: 'App needs access to your location ' +
'so we can let our app be even more awesome.'
}
);
if (granted) {
FusedLocation.setLocationPriority(FusedLocation.Constants.HIGH_ACCURACY);
// Get location once.
const location = await FusedLocation.getFusedLocation();
this.setState({lat: location.latitude, long: location.longitude});
// Set options.
FusedLocation.setLocationPriority(FusedLocation.Constants.BALANCED);
FusedLocation.setLocationInterval(20000);
FusedLocation.setFastestLocationInterval(15000);
FusedLocation.setSmallestDisplacement(10);
// Keep getting updated location.
FusedLocation.startLocationUpdates();
// Place listeners.
this.subscription = FusedLocation.on('fusedLocation', location => {
/* location = {
latitude: 14.2323,
longitude: -2.2323,
speed: 0,
altitude: 0,
provider: 'fused',
accuracy: 30,
bearing: 10,
mocked: false,
timestamp: '1513190221416'
}
*/
console.log(location);
});
/* Optional
this.errSubscription = FusedLocation.on('fusedLocationError', error => {
console.warn(error);
});
*/
}
...
componentWillUnmount() {
FusedLocation.off(this.subscription);
// FusedLocation.off(this.errSubscription);
FusedLocation.stopLocationUpdates();
}
...
```
## Compatibility.
• For versions < `1.0.0`, use with RN versions `> 0.40.x < 0.59.x`.
• For versions >= `1.0.0`, use with RN versions `> 0.59.x`.
Tested with Android SDK version `>= 16 (Android 4.1 - Jelly Bean)`. Please feel free to test it with other versions.
This repository follows [Semantic Versioning](https://semver.org/). No breaking changes will be incorporated till `v2.x.x`.
## Release Notes.
See CHANGELOG.md.
## License.
See License.
## Support.
Support my OSS work by buying me a coffee!
================================================
FILE: android/build.gradle
================================================
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.3.2'
}
}
apply plugin: 'com.android.library'
def DEFAULT_COMPILE_SDK_VERSION = 28
def DEFAULT_BUILD_TOOLS_VERSION = "28.0.3"
def DEFAULT_TARGET_SDK_VERSION = 28
def DEFAULT_MIN_SDK_VERSION = 16
def DEFAULT_GOOGLE_PLAY_SERVICES_VERSION = "16.+"
def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
}
android {
compileSdkVersion safeExtGet('compileSdkVersion', DEFAULT_COMPILE_SDK_VERSION)
buildToolsVersion safeExtGet('buildToolsVersion', DEFAULT_BUILD_TOOLS_VERSION)
defaultConfig {
minSdkVersion safeExtGet('minSdkVersion', DEFAULT_MIN_SDK_VERSION)
targetSdkVersion safeExtGet('targetSdkVersion', DEFAULT_TARGET_SDK_VERSION)
versionCode 1
versionName "0.1"
}
lintOptions {
abortOnError false
}
}
repositories {
google()
jcenter()
}
dependencies {
implementation "com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}"
implementation "com.google.android.gms:play-services-location:${safeExtGet('googlePlayServicesVersion', DEFAULT_GOOGLE_PLAY_SERVICES_VERSION)}"
}
================================================
FILE: android/src/main/AndroidManifest.xml
================================================
================================================
FILE: android/src/main/java/com/mustansirzia/fused/FusedLocationModule.java
================================================
package com.mustansirzia.fused;
import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import android.util.Log;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationAvailability;
import com.google.android.gms.location.LocationCallback;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationResult;
import com.google.android.gms.location.LocationServices;
/**
* Written with ❤! By M on 10/06/17.
*/
public class FusedLocationModule extends ReactContextBaseJavaModule {
private static final String TAG = "FUSED_LOCATION";
private final int PLAY_SERVICES_RESOLUTION_REQUEST = 2404;
private final String NATIVE_EVENT = "fusedLocation";
private final String NATIVE_ERROR = "fusedLocationError";
private final String ERROR_PLAY_SERVICES_NOT_FOUND = "Play services not found.";
private final String ERROR_UNAUTHORIZED = "Appropriate permissions not given.";
private final String ERROR_NO_LOCATION_PROVIDER = "No location provider found.";
private int mLocationInterval = 15000;
private int mLocationPriority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
private int mLocationFastestInterval = 10000;
private int mSmallestDisplacement = 0;
private LocationListener mLocationListener;
private GoogleApiClient mGoogleApiClient;
public FusedLocationModule(ReactApplicationContext reactContext) {
super(reactContext);
}
@Override
public String getName() {
return "FusedLocation";
}
@ReactMethod
public void setLocationInterval(int mLocationInterval) {
this.mLocationInterval = mLocationInterval;
}
@ReactMethod
public void setLocationPriority(int mLocationPriority) {
switch (mLocationPriority) {
case 0:
this.mLocationPriority = LocationRequest.PRIORITY_HIGH_ACCURACY;
break;
case 1:
this.mLocationPriority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;
break;
case 2:
this.mLocationPriority = LocationRequest.PRIORITY_LOW_POWER;
break;
case 3:
this.mLocationPriority = LocationRequest.PRIORITY_NO_POWER;
break;
}
}
@ReactMethod
public void setFastestLocationInterval(int mLocationFastestInterval) {
this.mLocationFastestInterval = mLocationFastestInterval;
}
@ReactMethod
public void setSmallestDisplacement(int mSmallestDisplacement) {
this.mSmallestDisplacement = mSmallestDisplacement;
}
@SuppressWarnings("All")
@ReactMethod
public void getFusedLocation(boolean forceNewLocation, final Promise promise) {
try {
if (!areProvidersAvailable()) {
promise.reject(TAG, ERROR_NO_LOCATION_PROVIDER);
return;
}
if (!checkForPlayServices()) {
promise.reject(TAG, ERROR_PLAY_SERVICES_NOT_FOUND);
return;
}
if (ActivityCompat.checkSelfPermission(getReactApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getReactApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
promise.reject(TAG, ERROR_UNAUTHORIZED);
return;
}
final GoogleApiClient googleApiClient;
LocationRequest request = buildLR();
googleApiClient = new GoogleApiClient.Builder(getReactApplicationContext())
.addApi(LocationServices.API)
.build();
googleApiClient.blockingConnect();
final Location location;
if (!forceNewLocation) {
location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
} else {
location = null;
}
if (location == null) {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, request, new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
super.onLocationResult(locationResult);
promise.resolve(convertLocationToJSON(locationResult.getLastLocation()));
}
@Override
public void onLocationAvailability(LocationAvailability locationAvailability) {
super.onLocationAvailability(locationAvailability);
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
googleApiClient.disconnect();
if (!locationAvailability.isLocationAvailable()) {
promise.reject(TAG, "Location not available. Does your phone have GPS turned on and internet connectivity?");
}
}
}, null);
return;
}
promise.resolve(convertLocationToJSON(location));
googleApiClient.disconnect();
} catch (Exception ex) {
Log.e(TAG, "Native Location Module ERR - " + ex.toString());
promise.reject(TAG, ex.toString());
}
}
@SuppressWarnings("All")
@ReactMethod
public void startLocationUpdates(final Promise promise) {
try {
if (!checkForPlayServices()) {
WritableMap params = new WritableNativeMap();
params.putString("error", ERROR_PLAY_SERVICES_NOT_FOUND);
sendEvent(getReactApplicationContext(), NATIVE_ERROR, params);
promise.reject(TAG, ERROR_PLAY_SERVICES_NOT_FOUND);
return;
}
if (ActivityCompat.checkSelfPermission(getReactApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getReactApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
WritableMap params = new WritableNativeMap();
params.putString("error", ERROR_UNAUTHORIZED);
sendEvent(getReactApplicationContext(), NATIVE_ERROR, params);
promise.reject(TAG, ERROR_UNAUTHORIZED);
return;
}
if (!areProvidersAvailable()) {
WritableMap params = new WritableNativeMap();
params.putString("error", ERROR_NO_LOCATION_PROVIDER);
sendEvent(getReactApplicationContext(), NATIVE_ERROR, params);
// Allow the App to still register the location updates so that it can send new locations if the user turns on the GPS through the notification bar
// promise.reject(TAG, ERROR_NO_LOCATION_PROVIDER);
// return;
}
LocationRequest request = buildLR();
Log.d("request", request.getPriority() + "");
mGoogleApiClient = new GoogleApiClient.Builder(getReactApplicationContext())
.addApi(LocationServices.API)
.build();
mGoogleApiClient.blockingConnect();
mLocationListener = new LocationListener() {
@Override
public void onLocationChanged(Location l) {
sendEvent(getReactApplicationContext(), NATIVE_EVENT, convertLocationToJSON(l));
}
};
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, request, mLocationListener);
promise.resolve(null);
} catch (Exception ex) {
Log.e(TAG, "Native Location Module ERR - " + ex.toString());
WritableMap params = new WritableNativeMap();
params.putString("error", "Native Location Module ERR - " + ex.toString());
sendEvent(getReactApplicationContext(), NATIVE_ERROR, params);
promise.reject(TAG, ex);
}
}
@ReactMethod
public void stopLocationUpdates(final Promise promise) {
if (mGoogleApiClient != null && mLocationListener != null && mGoogleApiClient.isConnected()) {
PendingResult pendingResult = LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, mLocationListener);
pendingResult.setResultCallback(new ResultCallback() {
@Override
public void onResult(@NonNull Status status) {
mGoogleApiClient.disconnect();
if (!status.isSuccess()) {
Log.e(TAG, "Could not remove location updates.");
promise.reject(TAG, String.valueOf(status.getStatusCode()));
} else {
promise.resolve(true);
}
}
});
} else {
promise.resolve(false);
}
}
@ReactMethod
public void areProvidersAvailable(final Promise promise) {
promise.resolve(areProvidersAvailable());
}
private boolean areProvidersAvailable() {
LocationManager lm = (LocationManager) getReactApplicationContext().getSystemService(Context.LOCATION_SERVICE);
boolean gps_enabled = false;
try {
gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER) || lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {
Log.e(TAG, ex.toString());
}
return gps_enabled;
}
// ~ https://stackoverflow.com/questions/
// 22493465/check-if-correct-google-play-service-available-unfortunately-application-has-s
private boolean checkForPlayServices() {
GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();
int resultCode = googleApiAvailability
.isGooglePlayServicesAvailable(getReactApplicationContext());
if (resultCode != ConnectionResult.SUCCESS) {
if (googleApiAvailability.isUserResolvableError(resultCode)) {
googleApiAvailability.getErrorDialog(getCurrentActivity(), resultCode,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
}
return false;
}
return true;
}
private WritableMap convertLocationToJSON(Location l) {
WritableMap params = new WritableNativeMap();
params.putDouble("latitude", l.getLatitude());
params.putDouble("longitude", l.getLongitude());
params.putDouble("accuracy", l.getAccuracy());
params.putDouble("altitude", l.getAltitude());
params.putDouble("bearing", l.getBearing());
params.putString("provider", l.getProvider());
params.putDouble("speed", l.getSpeed());
params.putString("timestamp", Long.toString(l.getTime()));
boolean isMock;
if (android.os.Build.VERSION.SDK_INT >= 18) {
isMock = l.isFromMockProvider();
} else {
isMock = !Settings.Secure.getString(getReactApplicationContext().getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals("0");
}
params.putBoolean("mocked", isMock);
return params;
}
private LocationRequest buildLR() {
LocationRequest request = new LocationRequest();
request.setPriority(mLocationPriority);
request.setInterval(mLocationInterval);
request.setFastestInterval(mLocationFastestInterval);
request.setSmallestDisplacement(mSmallestDisplacement);
return request;
}
/*
* Internal function for communicating with JS
*/
private void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params) {
if (reactContext.hasActiveCatalystInstance()) {
reactContext
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
.emit(eventName, params);
} else {
Log.d(TAG, "Waiting for Catalyst Instance...");
}
}
}
================================================
FILE: android/src/main/java/com/mustansirzia/fused/FusedLocationPackage.java
================================================
package com.mustansirzia.fused;
import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.JavaScriptModule;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Written with ❤! By M on 10/06/17.
*/
public class FusedLocationPackage implements ReactPackage {
@Override
public List createNativeModules(ReactApplicationContext reactContext) {
List modules = new ArrayList<>();
modules.add(new FusedLocationModule(reactContext));
return modules;
}
// Deprecated RN 0.47
public List> createJSModules() {
return Collections.emptyList();
}
@Override
public List createViewManagers(ReactApplicationContext reactContext) {
return Collections.emptyList();
}
}
================================================
FILE: package.json
================================================
{
"name": "react-native-fused-location",
"version": "1.1.2",
"description": "A react native module for android which gets the finest location from fused API. Gets location with or without GPS.",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"scripts": {
"start": "tsc -w",
"build": "tsc",
"prepublish": "npm run build --scripts-prepend-node-path",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/MustansirZia/react-native-fused-location"
},
"keywords": [
"react",
"react-native",
"location",
"gps",
"fused",
"android",
"play-services",
"npm",
"native"
],
"author": "Mustansir Zia ",
"license": "MIT",
"peerDependencies": {
"react": ">=15.4.0",
"react-native": ">=0.40.0"
},
"nativePackage": true,
"devDependencies": {
"@types/react-native": "^0.60.24",
"@typescript-eslint/eslint-plugin": "^2.10.0",
"@typescript-eslint/parser": "^2.10.0",
"eslint": "^6.7.2",
"eslint-config-prettier": "^6.7.0",
"eslint-plugin-prettier": "^3.1.1",
"prettier": "^1.19.1",
"typescript": "^3.7.3"
}
}
================================================
FILE: src/index.ts
================================================
/**
* Created by M on 11/06/17. With ❤
*/
import { NativeModules, DeviceEventEmitter, Platform } from 'react-native';
type EventName = 'fusedLocation' | 'fusedLocationError';
type LocationAccuracy = 0 | 1 | 2 | 3;
type LocationCallback = (location: Location) => void;
interface Location {
latitude: number;
longitude: number;
speed: number;
altitude: number;
provider: string;
accuracy: number;
bearing: number;
mocked: boolean;
timestamp: string;
}
interface Subscription {
listener: () => void;
eventName: string;
}
const FusedLocation = NativeModules.FusedLocation;
const checkforAndroid = (): void => {
if (Platform.OS !== 'android') {
throw new Error('react-native-fused-location cannot be used any other platform other than android.');
}
};
export default {
getFusedLocation: (forceNewLocation = false): Promise => {
checkforAndroid();
return FusedLocation.getFusedLocation(forceNewLocation);
},
startLocationUpdates: (): Promise => {
checkforAndroid();
return FusedLocation.startLocationUpdates();
},
stopLocationUpdates: (): Promise => {
checkforAndroid();
return FusedLocation.stopLocationUpdates();
},
on: (eventName: EventName, cb: LocationCallback): Subscription => {
checkforAndroid();
if (eventName != 'fusedLocation' && eventName != 'fusedLocationError') {
throw new Error("Event name has to be one of 'fusedLocation' or 'fusedLocationError'");
}
return { listener: DeviceEventEmitter.addListener(eventName, cb).listener, eventName };
},
off: (subscription: Subscription): void => {
checkforAndroid();
DeviceEventEmitter.removeListener(subscription.eventName, subscription.listener);
},
setLocationPriority: (priority: LocationAccuracy): Promise => {
checkforAndroid();
if (priority < 0 || priority > 3) {
throw new Error('Invalid priority set for fused api');
}
return FusedLocation.setLocationPriority(priority);
},
setLocationInterval: (intervalInMillis: number): Promise => {
checkforAndroid();
return FusedLocation.setLocationInterval(intervalInMillis);
},
setFastestLocationInterval: (intervalInMillis: number): Promise => {
checkforAndroid();
return FusedLocation.setFastestLocationInterval(intervalInMillis);
},
setSmallestDisplacement: (displacementInMeters: number): Promise => {
checkforAndroid();
return FusedLocation.setSmallestDisplacement(displacementInMeters);
},
areProvidersAvailable: (): Promise => {
checkforAndroid();
return FusedLocation.areProvidersAvailable();
},
Constants: {
HIGH_ACCURACY: 0,
BALANCED: 1,
LOW_POWER: 2,
NO_POWER: 3,
},
};
================================================
FILE: tsconfig.json
================================================
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"lib": [
"DOM",
"ES2015"
],
"jsx": "react-native",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./lib",
"rootDir": "./src",
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
"strictBindCallApply": true,
"strictPropertyInitialization": true,
"noImplicitThis": true,
"alwaysStrict": true,
"noUnusedLocals": true,
"noFallthroughCasesInSwitch": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"skipLibCheck": true
},
"exclude": [
"node_modules"
],
"include": [
"./src/*.ts"
]
}