[
  {
    "path": ".eslintrc.js",
    "content": "module.exports = {\n    parser: '@typescript-eslint/parser',\n    extends: [\n        'plugin:@typescript-eslint/recommended',\n        'prettier/@typescript-eslint',\n        'plugin:prettier/recommended',\n    ],\n    parserOptions: {\n        ecmaVersion: 2018,\n        sourceType: 'module',\n    },\n    ignorePatterns: [\"lib/**\"],\n    rules: {},\n};"
  },
  {
    "path": ".gitignore",
    "content": "node_modules\nnpm-debug.log\n.idea\nandroid/android.iml\nandroid/build/*\nandroid/gradle/*\nandroid/.gradle/*\nandroid/gradlew\nandroid/gradlew.bat\nandroid/local.properties\nlib\n"
  },
  {
    "path": ".npmignore",
    "content": "# From .gitignore.\nnode_modules\nnpm-debug.log\n.idea\nandroid/android.iml\nandroid/build/*\nandroid/gradle/*\nandroid/.gradle/*\nandroid/gradlew\nandroid/gradlew.bat\nandroid/local.properties\n\n# Ones we don't want published to npm.\nsrc/*\n.vscode\ntsconfig.json\n.eslintrc.js\n.prettierrc.js\nyarn.lock\n"
  },
  {
    "path": ".prettierrc.js",
    "content": "module.exports = {\n    semi: true,\n    trailingComma: 'all',\n    singleQuote: true,\n    printWidth: 120,\n    tabWidth: 4    \n};"
  },
  {
    "path": ".vscode/settings.json",
    "content": "{\n    \"eslint.autoFixOnSave\": true,\n    \"eslint.validate\": [\n        \"javascript\",\n        {\n            \"language\": \"typescript\",\n            \"autoFix\": true\n        },\n    ],\n    \"editor.formatOnSave\": true,\n    \"[javascript]\": {\n        \"editor.formatOnSave\": false,\n    },\n    \"[javascriptreact]\": {\n        \"editor.formatOnSave\": false,\n    },\n    \"[typescript]\": {\n        \"editor.formatOnSave\": false,\n    },\n    \"[typescriptreact]\": {\n        \"editor.formatOnSave\": false,\n    },\n}"
  },
  {
    "path": "CHANGELOG.md",
    "content": "## Release Notes.\n\n### 1.1.1\n° `forceNewLocation` argument made optional for `getFusedLocation` function call.\n\n### 1.0.0 - BREAKING CHANGE.\n° Support library migrated to AndroidX namespace.\n<br />\n° Added support for Typescript. ❤️\n\n### 0.5.0\n° Google play services version can now be overriden and is defaulted to `16.+`.\n° Android gradle version updated to `3.3.2`.\n• Compile SDK version defaulted to `28`.\n•  Build tools version defaulted to `28.0.3`.\n\n### 0.4.0\n° `BuildToolsVersion` and `sdkVersion` are now taken from the main android project's gradle file.\n\n### 0.2.0\n° `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.\n\n### 0.1.0\n° Made `areProvidersAvailable` method public under `FusedLocation.areProvidersAvailable()`.\n° Semver for this repo started.\n\n### 0.0.11\n° 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.\n\n### 0.0.8\n° Added `forceNewLocation` as an optional argument to `getFusedLocation`. This gets a new location everytime and never reuses a last known location.\n\n° 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.\n\n° Added `mocked` property to the `Location` object.\n\n• PR for #1 and #3 from - https://github.com/ginosi.\n\n### 0.0.5\n° Fixed typo in ReadMe. Changed `setLocationFatestInterval` to `setFastestLocationInterval` in js example.\n\n### 0.0.4\n° Fixed typo in ReadMe. Changed `FusedLocation` to `FusedLocationPackage` in manual linking.\nPR by - https://github.com/jarvisluong\n\n### 0.0.3\n° Default values added to Readme.\n\n### 0.0.2\n° iOS compatibility fixes.\n\n### 0.0.1\n° Initial Commit.\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "MIT License\n\nCopyright (c) 2017 Mustansir Zia\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# react-native-fused-location\n\n[![npm version](https://badge.fury.io/js/react-native-fused-location.svg)](https://badge.fury.io/js/react-native-fused-location)\n[![npm](https://img.shields.io/npm/dt/react-native-fused-location.svg)](https://www.npmjs.com/package/react-native-fused-location)\n[![Package Quality](http://npm.packagequality.com/shield/react-native-fused-location.svg)](http://packagequality.com/#?package=react-native-fused-location)\n[![MIT Licence](https://badges.frapsoft.com/os/mit/mit.svg?v=103)](https://opensource.org/licenses/mit-license.php)\n\n\nGet the finest location on Android using <a href=\"https://developers.google.com/android/reference/com/google/android/gms/location/FusedLocationProviderApi\"> Fused </a> API. <br /> <br />\nI 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.\n<br />\n\n## Install\n`npm install react-native-fused-location --save`\n<br />\nor\n<br />\n`yarn add react-native-fused-location`\n<br />\n#### Automatic Link.\n`react-native link react-native-fused-location`\n#### Manual Link.\n• in `android/app/build.gradle:`\n\n```diff\ndependencies {\n    ...\n    compile \"com.facebook.react:react-native:+\"  // From node_modules\n+   compile project(':react-native-fused-location')\n}\n```\n\n• in `android/settings.gradle`:\n\n```diff\n...\ninclude ':app'\n+ include ':react-native-fused-location'\n+ project(':react-native-fused-location').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fused-location/android')\n```\n• in `MainApplication.java:`\n```diff\n+ import com.mustansirzia.fused.FusedLocationPackage;\n\n    @Override\n        protected List<ReactPackage> getPackages() {\n          return Arrays.<ReactPackage>asList(\n              ...\n+             new FusedLocationPackage(),\n              ...\n              new MainReactPackage()\n          );\n        }\n```\n#### Migration to AndroidX. - BREAKING CHANGE in `1.0.0`.\n• 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. \n<br />\nTo enable AndroidX add these two lines in your `android/gradle.properties` file.\n```properties\nandroid.useAndroidX=true\nandroid.enableJetifier=true\n```\nIf this doesn't work out. Check out [this](https://developer.android.com/jetpack/androidx/migrate) official guide from Google. \n<br> \nA 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). \n\n## Permissions.\nAdd this to your `AndroidManifest.xml`:\n\n```xml\n    ...\n    <uses-permission android:name=\"android.permission.ACCESS_COARSE_LOCATION\"/>\n    <uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\"/>\n    ...\n        <permission\n            android:name=\"android.permission.ACCESS_COARSE_LOCATION\"\n            android:protectionLevel=\"signature\" />\n        <permission\n                android:name=\"android.permission.ACCESS_FINE_LOCATION\"\n                android:protectionLevel=\"signature\"/>\n    ...            \n```\n\n## Usage.\n\n### API.\n| Function | Arguments | Returns | Note |\n|:---|:---:|:---:|:------|\n| `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.\n| `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. <br /> **<b>Note</b>: You still need to subscribe to `fusedLocation` event. <br /> So, you need to call this before you call `FusedLocation.on`.\n| `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).\n| `on` | `eventName, callback` | `Subscription` | Subscribe to an event. The callback is called with `Location` updates if the eventName is `fusedLocation`. <br /> Call this <b>after</b> you call `startLocationUpdates`\n| `off` | `Subscription` | Nil | Unsubscribe from the corresponding subscription.\n| `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.\n\n### Configuration.\n#### `setLocationPriority(priority)` <br />\nSet location accuracy. `priority` be of the following types. <br />\n<b>`FusedLocation.Constants.HIGH_ACCURACY`</b> Most accurate. Least battery efficient. Uses GPS only. <br />\n<b>`FusedLocation.Constants.BALANCED`</b> Mixed. Chooses an appropriate provider. <br />\n<b>`FusedLocation.Constants.LOW_POWER`</b> Least accurate. Most battery efficient. Uses Wifi/Cell Towers only. <br />\n<b>`FusedLocation.Constants.NO_POWER`</b> Uses location updates from other apps (if they occur). Don't request location from your app. <br />\n• Default `FusedLocation.Constants.BALANCED`<br />\n\n#### `setLocationInterval(interval)` <br />\nSet 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. <br />\n• Default `15000`\n\n#### `setFastestLocationInterval(interval)` <br />\nSet the minimum possible interval between location updates (in milliseconds). <br />\n• Default `10000`\n\n#### `setSmallestDisplacement(displacement)` <br />\nSet smallest amount of displacement (in meters) to occur after which the location update will be received. <br />\n• Default `0`\n\nFor more info, see <a href=\"https://developers.google.com/android/reference/com/google/android/gms/location/LocationRequest\"> here. </a>\n\n### Types.\n```\ntype Location {\n        latitude: Number,\n        longitude: Number,\n        speed: Number,\n        altitude: Number,\n        provider: String,\n        accuracy: Number,\n        bearing: Number,\n        mocked: Boolean,\n        timestamp: String\n}\n```\n```\ntype Subscription {\n        listener: Function,\n        eventName: String\n}\n```\n\n### Example.\n```js\n...\nimport FusedLocation from 'react-native-fused-location';\n...\n\nasync componentDidMount() {\n     const granted = await PermissionsAndroid.request(\n                    PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION, {\n                        title: 'App needs to access your location',\n                        message: 'App needs access to your location ' +\n                        'so we can let our app be even more awesome.'\n                        }\n                    );\n     if (granted) {\n\n        FusedLocation.setLocationPriority(FusedLocation.Constants.HIGH_ACCURACY);\n\n        // Get location once.\n        const location = await FusedLocation.getFusedLocation();\n        this.setState({lat: location.latitude, long: location.longitude});\n\n        // Set options.\n        FusedLocation.setLocationPriority(FusedLocation.Constants.BALANCED);\n        FusedLocation.setLocationInterval(20000);\n        FusedLocation.setFastestLocationInterval(15000);\n        FusedLocation.setSmallestDisplacement(10);\n\n\n        // Keep getting updated location.\n        FusedLocation.startLocationUpdates();\n\n        // Place listeners.\n        this.subscription = FusedLocation.on('fusedLocation', location => {\n           /* location = {\n             latitude: 14.2323,\n             longitude: -2.2323,\n             speed: 0,\n             altitude: 0,\n             provider: 'fused',\n             accuracy: 30,\n             bearing: 10,\n             mocked: false,\n             timestamp: '1513190221416'\n           }\n           */\n           console.log(location);\n        });\n\n        /* Optional\n        this.errSubscription = FusedLocation.on('fusedLocationError', error => {\n            console.warn(error);\n        });\n        */\n     }\n\n...\n\ncomponentWillUnmount() {\n\n    FusedLocation.off(this.subscription);\n    // FusedLocation.off(this.errSubscription);\n    FusedLocation.stopLocationUpdates();\n\n}  \n\n...\n\n```\n<br />\n\n## Compatibility.\n• For versions < `1.0.0`, use with RN versions `> 0.40.x < 0.59.x`.\n<br />\n• For versions >= `1.0.0`, use with RN versions `> 0.59.x`.\n\nTested with Android SDK version `>= 16 (Android 4.1 - Jelly Bean)`. Please feel free to test it with other versions.\n\nThis repository follows [Semantic Versioning](https://semver.org/). No breaking changes will be incorporated till `v2.x.x`.\n\n## Release Notes.       \nSee <a href=\"https://github.com/MustansirZia/react-native-fused-location/blob/master/CHANGELOG.md\"> CHANGELOG.md</a>.     \n\n## License.\nSee <a href=\"https://github.com/MustansirZia/react-native-fused-location/blob/master/LICENSE.txt\"> License</a>.\n\n## Support.\n\nSupport my OSS work by buying me a coffee!\n \n<a href=\"https://www.buymeacoffee.com/MustansirZia\" target=\"_blank\"><img src=\"https://cdn.buymeacoffee.com/buttons/v2/default-blue.png\" alt=\"Buy Me A Pizza\" style=\"height: 60px !important;width: 217px !important;\" ></a>\n\n"
  },
  {
    "path": "android/build.gradle",
    "content": "buildscript {\n    repositories {\n        google()\n        jcenter()\n    }\n\n    dependencies {\n        classpath 'com.android.tools.build:gradle:3.3.2'\n    }\n}\n\napply plugin: 'com.android.library'\n\ndef DEFAULT_COMPILE_SDK_VERSION          = 28\ndef DEFAULT_BUILD_TOOLS_VERSION          = \"28.0.3\"\ndef DEFAULT_TARGET_SDK_VERSION           = 28\ndef DEFAULT_MIN_SDK_VERSION              = 16\ndef DEFAULT_GOOGLE_PLAY_SERVICES_VERSION = \"16.+\"\n\ndef safeExtGet(prop, fallback) {\n    rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback\n}\n\nandroid {\n    compileSdkVersion safeExtGet('compileSdkVersion', DEFAULT_COMPILE_SDK_VERSION)\n    buildToolsVersion safeExtGet('buildToolsVersion', DEFAULT_BUILD_TOOLS_VERSION)\n\n    defaultConfig {\n        minSdkVersion safeExtGet('minSdkVersion', DEFAULT_MIN_SDK_VERSION)\n        targetSdkVersion safeExtGet('targetSdkVersion', DEFAULT_TARGET_SDK_VERSION)\n        versionCode 1\n        versionName \"0.1\"\n    }\n    lintOptions {\n        abortOnError false\n    }\n}\n\n\nrepositories {\n    google()\n    jcenter()\n}\n\ndependencies {\n    implementation \"com.facebook.react:react-native:${safeExtGet('reactNativeVersion', '+')}\"\n    implementation \"com.google.android.gms:play-services-location:${safeExtGet('googlePlayServicesVersion', DEFAULT_GOOGLE_PLAY_SERVICES_VERSION)}\"\n}\n"
  },
  {
    "path": "android/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n          package=\"com.mustansirzia.fused\">\n</manifest>\n"
  },
  {
    "path": "android/src/main/java/com/mustansirzia/fused/FusedLocationModule.java",
    "content": "package com.mustansirzia.fused;\n\nimport android.Manifest;\nimport android.content.Context;\nimport android.content.pm.PackageManager;\nimport android.location.Location;\nimport android.location.LocationManager;\nimport android.provider.Settings;\nimport androidx.annotation.NonNull;\nimport androidx.annotation.Nullable;\nimport androidx.core.app.ActivityCompat;\nimport android.util.Log;\n\nimport com.facebook.react.bridge.Promise;\nimport com.facebook.react.bridge.ReactApplicationContext;\nimport com.facebook.react.bridge.ReactContext;\nimport com.facebook.react.bridge.ReactContextBaseJavaModule;\nimport com.facebook.react.bridge.ReactMethod;\nimport com.facebook.react.bridge.WritableMap;\nimport com.facebook.react.bridge.WritableNativeMap;\nimport com.facebook.react.modules.core.DeviceEventManagerModule;\nimport com.google.android.gms.common.ConnectionResult;\nimport com.google.android.gms.common.GoogleApiAvailability;\nimport com.google.android.gms.common.api.GoogleApiClient;\nimport com.google.android.gms.common.api.PendingResult;\nimport com.google.android.gms.common.api.ResultCallback;\nimport com.google.android.gms.common.api.Status;\nimport com.google.android.gms.location.LocationAvailability;\nimport com.google.android.gms.location.LocationCallback;\nimport com.google.android.gms.location.LocationListener;\nimport com.google.android.gms.location.LocationRequest;\nimport com.google.android.gms.location.LocationResult;\nimport com.google.android.gms.location.LocationServices;\n\n/**\n * Written with ❤! By M on 10/06/17.\n */\n\npublic class FusedLocationModule extends ReactContextBaseJavaModule {\n\n    private static final String TAG = \"FUSED_LOCATION\";\n    private final int PLAY_SERVICES_RESOLUTION_REQUEST = 2404;\n    private final String NATIVE_EVENT = \"fusedLocation\";\n    private final String NATIVE_ERROR = \"fusedLocationError\";\n    private final String ERROR_PLAY_SERVICES_NOT_FOUND = \"Play services not found.\";\n    private final String ERROR_UNAUTHORIZED = \"Appropriate permissions not given.\";\n    private final String ERROR_NO_LOCATION_PROVIDER = \"No location provider found.\";\n    private int mLocationInterval = 15000;\n    private int mLocationPriority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;\n    private int mLocationFastestInterval = 10000;\n    private int mSmallestDisplacement = 0;\n    private LocationListener mLocationListener;\n    private GoogleApiClient mGoogleApiClient;\n\n    public FusedLocationModule(ReactApplicationContext reactContext) {\n        super(reactContext);\n    }\n\n    @Override\n    public String getName() {\n        return \"FusedLocation\";\n    }\n\n    @ReactMethod\n    public void setLocationInterval(int mLocationInterval) {\n        this.mLocationInterval = mLocationInterval;\n    }\n\n    @ReactMethod\n    public void setLocationPriority(int mLocationPriority) {\n        switch (mLocationPriority) {\n            case 0:\n                this.mLocationPriority = LocationRequest.PRIORITY_HIGH_ACCURACY;\n                break;\n            case 1:\n                this.mLocationPriority = LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY;\n                break;\n            case 2:\n                this.mLocationPriority = LocationRequest.PRIORITY_LOW_POWER;\n                break;\n            case 3:\n                this.mLocationPriority = LocationRequest.PRIORITY_NO_POWER;\n                break;\n        }\n    }\n\n    @ReactMethod\n    public void setFastestLocationInterval(int mLocationFastestInterval) {\n        this.mLocationFastestInterval = mLocationFastestInterval;\n    }\n\n    @ReactMethod\n    public void setSmallestDisplacement(int mSmallestDisplacement) {\n        this.mSmallestDisplacement = mSmallestDisplacement;\n    }\n\n    @SuppressWarnings(\"All\")\n    @ReactMethod\n    public void getFusedLocation(boolean forceNewLocation, final Promise promise) {\n        try {\n            if (!areProvidersAvailable()) {\n                promise.reject(TAG, ERROR_NO_LOCATION_PROVIDER);\n                return;\n            }\n            if (!checkForPlayServices()) {\n                promise.reject(TAG, ERROR_PLAY_SERVICES_NOT_FOUND);\n                return;\n            }\n            if (ActivityCompat.checkSelfPermission(getReactApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getReactApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {\n                promise.reject(TAG, ERROR_UNAUTHORIZED);\n                return;\n            }\n            final GoogleApiClient googleApiClient;\n            LocationRequest request = buildLR();\n            googleApiClient = new GoogleApiClient.Builder(getReactApplicationContext())\n                    .addApi(LocationServices.API)\n                    .build();\n            googleApiClient.blockingConnect();\n            final Location location;\n            if (!forceNewLocation) {\n                location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);\n            } else {\n                location = null;\n            }\n            if (location == null) {\n                LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, request, new LocationCallback() {\n                    @Override\n                    public void onLocationResult(LocationResult locationResult) {\n                        super.onLocationResult(locationResult);\n                        promise.resolve(convertLocationToJSON(locationResult.getLastLocation()));\n                    }\n\n                    @Override\n                    public void onLocationAvailability(LocationAvailability locationAvailability) {\n                        super.onLocationAvailability(locationAvailability);\n                        LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);\n                        googleApiClient.disconnect();\n                        if (!locationAvailability.isLocationAvailable()) {\n                            promise.reject(TAG, \"Location not available. Does your phone have GPS turned on and internet connectivity?\");\n                        }\n                    }\n                }, null);\n                return;\n            }\n            promise.resolve(convertLocationToJSON(location));\n            googleApiClient.disconnect();\n        } catch (Exception ex) {\n            Log.e(TAG, \"Native Location Module ERR - \" + ex.toString());\n            promise.reject(TAG, ex.toString());\n        }\n    }\n\n    @SuppressWarnings(\"All\")\n    @ReactMethod\n    public void startLocationUpdates(final Promise promise) {\n        try {\n            if (!checkForPlayServices()) {\n                WritableMap params = new WritableNativeMap();\n                params.putString(\"error\", ERROR_PLAY_SERVICES_NOT_FOUND);\n                sendEvent(getReactApplicationContext(), NATIVE_ERROR, params);\n                promise.reject(TAG, ERROR_PLAY_SERVICES_NOT_FOUND);\n                return;\n            }\n            if (ActivityCompat.checkSelfPermission(getReactApplicationContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getReactApplicationContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {\n                WritableMap params = new WritableNativeMap();\n                params.putString(\"error\", ERROR_UNAUTHORIZED);\n                sendEvent(getReactApplicationContext(), NATIVE_ERROR, params);\n                promise.reject(TAG, ERROR_UNAUTHORIZED);\n                return;\n            }\n            if (!areProvidersAvailable()) {\n                WritableMap params = new WritableNativeMap();\n                params.putString(\"error\", ERROR_NO_LOCATION_PROVIDER);\n                sendEvent(getReactApplicationContext(), NATIVE_ERROR, params);\n                // 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\n                // promise.reject(TAG, ERROR_NO_LOCATION_PROVIDER);\n                // return;\n            }\n            LocationRequest request = buildLR();\n            Log.d(\"request\", request.getPriority() + \"\");\n            mGoogleApiClient = new GoogleApiClient.Builder(getReactApplicationContext())\n                    .addApi(LocationServices.API)\n                    .build();\n            mGoogleApiClient.blockingConnect();\n            mLocationListener = new LocationListener() {\n                @Override\n                public void onLocationChanged(Location l) {\n                    sendEvent(getReactApplicationContext(), NATIVE_EVENT, convertLocationToJSON(l));\n                }\n            };\n            LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, request, mLocationListener);\n            promise.resolve(null);\n        } catch (Exception ex) {\n            Log.e(TAG, \"Native Location Module ERR - \" + ex.toString());\n            WritableMap params = new WritableNativeMap();\n            params.putString(\"error\", \"Native Location Module ERR - \" + ex.toString());\n            sendEvent(getReactApplicationContext(), NATIVE_ERROR, params);\n            promise.reject(TAG, ex);\n        }\n    }\n\n    @ReactMethod\n    public void stopLocationUpdates(final Promise promise) {\n        if (mGoogleApiClient != null && mLocationListener != null && mGoogleApiClient.isConnected()) {\n            PendingResult<Status> pendingResult = LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, mLocationListener);\n            pendingResult.setResultCallback(new ResultCallback<Status>() {\n                @Override\n                public void onResult(@NonNull Status status) {\n                    mGoogleApiClient.disconnect();\n                    if (!status.isSuccess()) {\n                        Log.e(TAG, \"Could not remove location updates.\");\n                        promise.reject(TAG, String.valueOf(status.getStatusCode()));\n                    } else {\n                        promise.resolve(true);\n                    }\n\n                }\n            });\n        } else {\n            promise.resolve(false);\n        }\n    }\n\n    @ReactMethod\n    public void areProvidersAvailable(final Promise promise) {\n        promise.resolve(areProvidersAvailable());\n    }\n\n    private boolean areProvidersAvailable() {\n        LocationManager lm = (LocationManager) getReactApplicationContext().getSystemService(Context.LOCATION_SERVICE);\n        boolean gps_enabled = false;\n        try {\n            gps_enabled = lm.isProviderEnabled(LocationManager.GPS_PROVIDER) || lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER);\n        } catch (Exception ex) {\n            Log.e(TAG, ex.toString());\n        }\n        return gps_enabled;\n    }\n\n    // ~ https://stackoverflow.com/questions/\n    // 22493465/check-if-correct-google-play-service-available-unfortunately-application-has-s\n    private boolean checkForPlayServices() {\n        GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();\n        int resultCode = googleApiAvailability\n                .isGooglePlayServicesAvailable(getReactApplicationContext());\n        if (resultCode != ConnectionResult.SUCCESS) {\n            if (googleApiAvailability.isUserResolvableError(resultCode)) {\n                googleApiAvailability.getErrorDialog(getCurrentActivity(), resultCode,\n                        PLAY_SERVICES_RESOLUTION_REQUEST).show();\n            }\n            return false;\n        }\n        return true;\n    }\n\n    private WritableMap convertLocationToJSON(Location l) {\n        WritableMap params = new WritableNativeMap();\n        params.putDouble(\"latitude\", l.getLatitude());\n        params.putDouble(\"longitude\", l.getLongitude());\n        params.putDouble(\"accuracy\", l.getAccuracy());\n        params.putDouble(\"altitude\", l.getAltitude());\n        params.putDouble(\"bearing\", l.getBearing());\n        params.putString(\"provider\", l.getProvider());\n        params.putDouble(\"speed\", l.getSpeed());\n        params.putString(\"timestamp\", Long.toString(l.getTime()));\n        boolean isMock;\n        if (android.os.Build.VERSION.SDK_INT >= 18) {\n            isMock = l.isFromMockProvider();\n        } else {\n            isMock = !Settings.Secure.getString(getReactApplicationContext().getContentResolver(), Settings.Secure.ALLOW_MOCK_LOCATION).equals(\"0\");\n        }\n        params.putBoolean(\"mocked\", isMock);\n        return params;\n    }\n\n    private LocationRequest buildLR() {\n        LocationRequest request = new LocationRequest();\n        request.setPriority(mLocationPriority);\n        request.setInterval(mLocationInterval);\n        request.setFastestInterval(mLocationFastestInterval);\n        request.setSmallestDisplacement(mSmallestDisplacement);\n        return request;\n    }\n\n    /*\n  * Internal function for communicating with JS\n  */\n    private void sendEvent(ReactContext reactContext, String eventName, @Nullable WritableMap params) {\n        if (reactContext.hasActiveCatalystInstance()) {\n            reactContext\n                    .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)\n                    .emit(eventName, params);\n        } else {\n            Log.d(TAG, \"Waiting for Catalyst Instance...\");\n        }\n    }\n}\n"
  },
  {
    "path": "android/src/main/java/com/mustansirzia/fused/FusedLocationPackage.java",
    "content": "package com.mustansirzia.fused;\n\nimport com.facebook.react.ReactPackage;\nimport com.facebook.react.bridge.JavaScriptModule;\nimport com.facebook.react.bridge.NativeModule;\nimport com.facebook.react.bridge.ReactApplicationContext;\nimport com.facebook.react.uimanager.ViewManager;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * Written with ❤! By M on 10/06/17.\n */\n\npublic class FusedLocationPackage implements ReactPackage {\n    @Override\n    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {\n        List<NativeModule> modules = new ArrayList<>();\n        modules.add(new FusedLocationModule(reactContext));\n        return modules;\n    }\n\n    // Deprecated RN 0.47\n    public List<Class<? extends JavaScriptModule>> createJSModules() {\n        return Collections.emptyList();\n    }\n\n    @Override\n    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {\n        return Collections.emptyList();\n    }\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"react-native-fused-location\",\n  \"version\": \"1.1.2\",\n  \"description\": \"A react native module for android which gets the finest location from fused API. Gets location with or without GPS.\",\n  \"main\": \"lib/index.js\",\n  \"types\": \"lib/index.d.ts\",\n  \"scripts\": {\n    \"start\": \"tsc -w\",\n    \"build\": \"tsc\",\n    \"prepublish\": \"npm run build --scripts-prepend-node-path\",\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/MustansirZia/react-native-fused-location\"\n  },\n  \"keywords\": [\n    \"react\",\n    \"react-native\",\n    \"location\",\n    \"gps\",\n    \"fused\",\n    \"android\",\n    \"play-services\",\n    \"npm\",\n    \"native\"\n  ],\n  \"author\": \"Mustansir Zia <mustansir29@hotmail.com>\",\n  \"license\": \"MIT\",\n  \"peerDependencies\": {\n    \"react\": \">=15.4.0\",\n    \"react-native\": \">=0.40.0\"\n  },\n  \"nativePackage\": true,\n  \"devDependencies\": {\n    \"@types/react-native\": \"^0.60.24\",\n    \"@typescript-eslint/eslint-plugin\": \"^2.10.0\",\n    \"@typescript-eslint/parser\": \"^2.10.0\",\n    \"eslint\": \"^6.7.2\",\n    \"eslint-config-prettier\": \"^6.7.0\",\n    \"eslint-plugin-prettier\": \"^3.1.1\",\n    \"prettier\": \"^1.19.1\",\n    \"typescript\": \"^3.7.3\"\n  }\n}"
  },
  {
    "path": "src/index.ts",
    "content": "/**\n * Created by M on 11/06/17. With ❤\n */\n\nimport { NativeModules, DeviceEventEmitter, Platform } from 'react-native';\n\ntype EventName = 'fusedLocation' | 'fusedLocationError';\n\ntype LocationAccuracy = 0 | 1 | 2 | 3;\n\ntype LocationCallback = (location: Location) => void;\n\ninterface Location {\n    latitude: number;\n    longitude: number;\n    speed: number;\n    altitude: number;\n    provider: string;\n    accuracy: number;\n    bearing: number;\n    mocked: boolean;\n    timestamp: string;\n}\n\ninterface Subscription {\n    listener: () => void;\n    eventName: string;\n}\n\nconst FusedLocation = NativeModules.FusedLocation;\n\nconst checkforAndroid = (): void => {\n    if (Platform.OS !== 'android') {\n        throw new Error('react-native-fused-location cannot be used any other platform other than android.');\n    }\n};\n\nexport default {\n    getFusedLocation: (forceNewLocation = false): Promise<Location> => {\n        checkforAndroid();\n        return FusedLocation.getFusedLocation(forceNewLocation);\n    },\n    startLocationUpdates: (): Promise<void> => {\n        checkforAndroid();\n        return FusedLocation.startLocationUpdates();\n    },\n    stopLocationUpdates: (): Promise<void> => {\n        checkforAndroid();\n        return FusedLocation.stopLocationUpdates();\n    },\n    on: (eventName: EventName, cb: LocationCallback): Subscription => {\n        checkforAndroid();\n        if (eventName != 'fusedLocation' && eventName != 'fusedLocationError') {\n            throw new Error(\"Event name has to be one of 'fusedLocation' or 'fusedLocationError'\");\n        }\n        return { listener: DeviceEventEmitter.addListener(eventName, cb).listener, eventName };\n    },\n    off: (subscription: Subscription): void => {\n        checkforAndroid();\n        DeviceEventEmitter.removeListener(subscription.eventName, subscription.listener);\n    },\n    setLocationPriority: (priority: LocationAccuracy): Promise<void> => {\n        checkforAndroid();\n        if (priority < 0 || priority > 3) {\n            throw new Error('Invalid priority set for fused api');\n        }\n        return FusedLocation.setLocationPriority(priority);\n    },\n    setLocationInterval: (intervalInMillis: number): Promise<void> => {\n        checkforAndroid();\n        return FusedLocation.setLocationInterval(intervalInMillis);\n    },\n    setFastestLocationInterval: (intervalInMillis: number): Promise<void> => {\n        checkforAndroid();\n        return FusedLocation.setFastestLocationInterval(intervalInMillis);\n    },\n    setSmallestDisplacement: (displacementInMeters: number): Promise<void> => {\n        checkforAndroid();\n        return FusedLocation.setSmallestDisplacement(displacementInMeters);\n    },\n    areProvidersAvailable: (): Promise<boolean> => {\n        checkforAndroid();\n        return FusedLocation.areProvidersAvailable();\n    },\n    Constants: {\n        HIGH_ACCURACY: 0,\n        BALANCED: 1,\n        LOW_POWER: 2,\n        NO_POWER: 3,\n    },\n};\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\n  \"compilerOptions\": {\n    \"target\": \"es6\",\n    \"module\": \"commonjs\",\n    \"lib\": [\n      \"DOM\",\n      \"ES2015\"\n    ],\n    \"jsx\": \"react-native\",\n    \"declaration\": true,\n    \"declarationMap\": true,\n    \"sourceMap\": true,\n    \"outDir\": \"./lib\",\n    \"rootDir\": \"./src\",\n    \"strict\": true,\n    \"noImplicitAny\": true,\n    \"strictNullChecks\": true,\n    \"strictBindCallApply\": true,\n    \"strictPropertyInitialization\": true,\n    \"noImplicitThis\": true,\n    \"alwaysStrict\": true,\n    \"noUnusedLocals\": true,\n    \"noFallthroughCasesInSwitch\": true,\n    \"allowSyntheticDefaultImports\": true,\n    \"esModuleInterop\": true,\n    \"forceConsistentCasingInFileNames\": true,\n    \"skipLibCheck\": true\n  },\n  \"exclude\": [\n    \"node_modules\"\n  ],\n  \"include\": [\n    \"./src/*.ts\"\n  ]\n}"
  }
]