├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── android ├── build.gradle └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── com │ └── showlocationservicesdialogbox │ ├── LocationServicesDialogBoxModule.java │ └── LocationServicesDialogBoxPackage.java ├── demo.gif ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | .DS_Store 3 | 4 | # Xcode 5 | # 6 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 7 | 8 | ## Build generated 9 | android/build/ 10 | DerivedData 11 | 12 | ## Various settings 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | xcuserdata 22 | 23 | ## Other 24 | *.xccheckout 25 | *.moved-aside 26 | *.xcuserstate 27 | *.xcscmblueprint 28 | 29 | ## Obj-C/Swift specific 30 | *.hmap 31 | *.ipa 32 | 33 | # CocoaPods 34 | # 35 | # We recommend against adding the Pods directory to your .gitignore. However 36 | # you should judge for yourself, the pros and cons are mentioned at: 37 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 38 | # 39 | # Pods/ 40 | 41 | # Carthage 42 | # 43 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 44 | # Carthage/Checkouts 45 | 46 | Carthage/Build 47 | 48 | # fastlane 49 | # 50 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 51 | # screenshots whenever they are needed. 52 | # For more information about the recommended setup visit: 53 | # https://github.com/fastlane/fastlane/blob/master/docs/Gitignore.md 54 | 55 | fastlane/report.xml 56 | fastlane/screenshots 57 | 58 | node_modules/**/* 59 | 60 | # Android 61 | android/.idea/ 62 | android/gradle/ 63 | android/.gradle 64 | android/gradlew 65 | android/gradlew.bat 66 | android/local.properties 67 | .buckconfig 68 | .flowconfig 69 | .watchmanconfig 70 | .idea/ShowLocationServicesDialogBox.iml 71 | .idea/encodings.xml 72 | .idea/misc.xml 73 | .idea/modules.xml 74 | .idea/workspace.xml 75 | android/.gradle/ 76 | .idea/ 77 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | android/.idea/ 2 | android/gradle/ 3 | android/.gradle/ 4 | android/build/ 5 | android/gradlew 6 | android/gradlew.bat 7 | android/local.properties 8 | .buckconfig 9 | .flowconfig 10 | .watchmanconfig 11 | .idea/ 12 | demo.gif -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2018 webyonet (Burak Demirezen) 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## React Native Android Location Services Dialog Box 2 | 3 | 4 | A react-native component for turn on the dialog box from android location services 5 | 6 | 7 | [![GitHub tag](https://img.shields.io/github/tag/webyonet/react-native-android-location-services-dialog-box.svg)](https://github.com/webyonet/react-native-android-location-services-dialog-box) 8 | [![npm version](https://badge.fury.io/js/react-native-android-location-services-dialog-box.svg)](https://badge.fury.io/js/react-native-android-location-services-dialog-box) 9 | ![npm](https://img.shields.io/npm/dm/react-native-android-location-services-dialog-box.svg) 10 | ![npm](https://img.shields.io/npm/dt/react-native-android-location-services-dialog-box.svg) 11 | ![npm](https://img.shields.io/npm/l/react-native-android-location-services-dialog-box.svg) 12 | 13 | ### Installation 14 | 15 | #### Mostly automatic installation (recommended) 16 | 17 | 1. `yarn add react-native-android-location-services-dialog-box` 18 |
or
19 | `npm install react-native-android-location-services-dialog-box --save` 20 | 2. `react-native link react-native-android-location-services-dialog-box` 21 | 22 | #### Manual Installation 23 | 24 | ##### Android 25 | 26 | 1. `yarn add react-native-android-location-services-dialog-box` 27 |
or
28 | `npm install react-native-android-location-services-dialog-box --save` 29 | 2. Make the following additions to the given files: 30 | 31 | **android/settings.gradle** 32 | 33 | ```gradle 34 | include ':react-native-android-location-services-dialog-box' 35 | project(':react-native-android-location-services-dialog-box').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-android-location-services-dialog-box/android') 36 | ``` 37 | 38 | **android/app/build.gradle** 39 | 40 | ```gradle 41 | dependencies { 42 | ... 43 | compileOnly project(':react-native-android-location-services-dialog-box') 44 | } 45 | ``` 46 | 47 | **MainApplication.java** 48 | 49 | On top, where imports are: 50 | ```java 51 | import com.showlocationservicesdialogbox.LocationServicesDialogBoxPackage; 52 | ``` 53 | 54 | Under `protected List getPackages() {`: 55 | ```java 56 | return Arrays.asList( 57 | new MainReactPackage(), 58 | new LocationServicesDialogBoxPackage() // <== this 59 | ); 60 | ``` 61 | 62 | ### Usage 63 | 64 | ```javascript 65 | import { BackHandler, DeviceEventEmitter } from 'react-native'; 66 | import LocationServicesDialogBox from "react-native-android-location-services-dialog-box"; 67 | 68 | LocationServicesDialogBox.checkLocationServicesIsEnabled({ 69 | message: "

Use Location ?

This app wants to change your device settings:

Use GPS, Wi-Fi, and cell network for location

Learn more", 70 | ok: "YES", 71 | cancel: "NO", 72 | enableHighAccuracy: true, // true => GPS AND NETWORK PROVIDER, false => GPS OR NETWORK PROVIDER 73 | showDialog: true, // false => Opens the Location access page directly 74 | openLocationServices: true, // false => Directly catch method is called if location services are turned off 75 | preventOutSideTouch: false, // true => To prevent the location services window from closing when it is clicked outside 76 | preventBackClick: false, // true => To prevent the location services popup from closing when it is clicked back button 77 | providerListener: false // true ==> Trigger locationProviderStatusChange listener when the location state changes 78 | }).then(function(success) { 79 | console.log(success); // success => {alreadyEnabled: false, enabled: true, status: "enabled"} 80 | }).catch((error) => { 81 | console.log(error.message); // error.message => "disabled" 82 | }); 83 | 84 | BackHandler.addEventListener('hardwareBackPress', () => { //(optional) you can use it if you need it 85 | //do not use this method if you are using navigation."preventBackClick: false" is already doing the same thing. 86 | LocationServicesDialogBox.forceCloseDialog(); 87 | }); 88 | 89 | DeviceEventEmitter.addListener('locationProviderStatusChange', function(status) { // only trigger when "providerListener" is enabled 90 | console.log(status); // status => {enabled: false, status: "disabled"} or {enabled: true, status: "enabled"} 91 | }); 92 | 93 | componentWillUnmount() { 94 | // used only when "providerListener" is enabled 95 | LocationServicesDialogBox.stopListener(); // Stop the "locationProviderStatusChange" listener 96 | } 97 | ``` 98 | 99 | ### Configure Colors 100 | 101 | ```javascript 102 | import LocationServicesDialogBox from "react-native-android-location-services-dialog-box"; 103 | 104 | LocationServicesDialogBox.checkLocationServicesIsEnabled({ 105 | message: "Use Location ?", 106 | ok: "YES", 107 | cancel: "NO", 108 | style: { // (optional) 109 | backgroundColor: '#87a9ea',// (optional) 110 | 111 | positiveButtonTextColor: '#ffffff',// (optional) 112 | positiveButtonBackgroundColor: '#5fba7d',// (optional) 113 | 114 | negativeButtonTextColor: '#ffffff',// (optional) 115 | negativeButtonBackgroundColor: '#ba5f5f'// (optional) 116 | } 117 | }).then(function(success) { 118 | console.log(success); 119 | }).catch((error) => { 120 | console.log(error.message); 121 | }); 122 | 123 | ``` 124 | screen shot 2018-07-07 at 16 58 28 125 | 126 | ### Usage And Example For Async Method `ES6` 127 | 128 | ```javascript 129 | import { BackHandler, DeviceEventEmitter } from 'react-native'; 130 | import LocationServicesDialogBox from "react-native-android-location-services-dialog-box"; 131 | 132 | export default class LocationServiceTestPage extends Component { 133 | constructor(props){ 134 | super(props); 135 | 136 | this.checkIsLocation().catch(error => error); 137 | 138 | DeviceEventEmitter.addListener('locationProviderStatusChange', function(status) { // only trigger when "providerListener" is enabled 139 | console.log(status); // status => {enabled: false, status: "disabled"} or {enabled: true, status: "enabled"} 140 | }); 141 | } 142 | 143 | async checkIsLocation():Promise { 144 | let check = await LocationServicesDialogBox.checkLocationServicesIsEnabled({ 145 | message: "Use Location ?", 146 | ok: "YES", 147 | cancel: "NO", 148 | enableHighAccuracy: true, // true => GPS AND NETWORK PROVIDER, false => GPS OR NETWORK PROVIDER 149 | showDialog: true, // false => Opens the Location access page directly 150 | openLocationServices: true, // false => Directly catch method is called if location services are turned off 151 | preventOutSideTouch: false, //true => To prevent the location services window from closing when it is clicked outside 152 | preventBackClick: false, //true => To prevent the location services popup from closing when it is clicked back button 153 | providerListener: true // true ==> Trigger "locationProviderStatusChange" listener when the location state changes 154 | }).catch(error => error); 155 | 156 | return Object.is(check.status, "enabled"); 157 | } 158 | 159 | componentWillUnmount() { 160 | // used only when "providerListener" is enabled 161 | LocationServicesDialogBox.stopListener(); // Stop the "locationProviderStatusChange" listener 162 | } 163 | } 164 | ``` 165 | 166 | ### Examples `ES6` 167 | ```javascript 168 | import React, { Component } from 'react'; 169 | import { 170 | AppRegistry, 171 | Text, 172 | View, 173 | BackHandler, 174 | DeviceEventEmitter 175 | } from 'react-native'; 176 | 177 | import LocationServicesDialogBox from "react-native-android-location-services-dialog-box"; 178 | 179 | class SampleApp extends Component { 180 | state = { 181 | initialPosition: 'unknown', 182 | }; 183 | 184 | componentDidMount() { 185 | LocationServicesDialogBox.checkLocationServicesIsEnabled({ 186 | message: "

Use Location ?

This app wants to change your device settings:

Use GPS, Wi-Fi, and cell network for location

Learn more", 187 | ok: "YES", 188 | cancel: "NO", 189 | enableHighAccuracy: true, // true => GPS AND NETWORK PROVIDER, false => GPS OR NETWORK PROVIDER 190 | showDialog: true, // false => Opens the Location access page directly 191 | openLocationServices: true, // false => Directly catch method is called if location services are turned off 192 | preventOutSideTouch: false, //true => To prevent the location services popup from closing when it is clicked outside 193 | preventBackClick: false, //true => To prevent the location services popup from closing when it is clicked back button 194 | providerListener: true // true ==> Trigger "locationProviderStatusChange" listener when the location state changes 195 | }).then(function(success) { 196 | // success => {alreadyEnabled: true, enabled: true, status: "enabled"} 197 | navigator.geolocation.getCurrentPosition((position) => { 198 | let initialPosition = JSON.stringify(position); 199 | this.setState({ initialPosition }); 200 | }, error => console.log(error), { enableHighAccuracy: false, timeout: 20000, maximumAge: 1000 }); 201 | }.bind(this) 202 | ).catch((error) => { 203 | console.log(error.message); 204 | }); 205 | 206 | DeviceEventEmitter.addListener('locationProviderStatusChange', function(status) { // only trigger when "providerListener" is enabled 207 | console.log(status); // status => {enabled: false, status: "disabled"} or {enabled: true, status: "enabled"} 208 | }); 209 | } 210 | 211 | componentWillUnmount() { 212 | // used only when "providerListener" is enabled 213 | LocationServicesDialogBox.stopListener(); // Stop the "locationProviderStatusChange" listener. 214 | } 215 | 216 | render() { 217 | return ( 218 | 219 | 220 | Geolocation: {this.state.initialPosition} 221 | 222 | 223 | ); 224 | } 225 | } 226 | AppRegistry.registerComponent('SampleApp', () => SampleApp); 227 | ``` 228 | 229 | ### Props 230 | 231 | | Prop | Type | Default | Description | 232 | |-----------------------------------|-------------|-------------|------------------------------------------------------------------------------------------| 233 | |`message` |`HTML` |`null` |Dialog box content text | 234 | |`ok` |`String` |`null` |Dialog box ok button text | 235 | |`cancel` |`String` |`null` |Dialog box cancel button text | 236 | |`enableHighAccuracy` (optional) |`Boolean` |`true` |Provider switch (GPS OR NETWORK OR GPS AND NETWORK) | 237 | |`showDialog` (optional) |`Boolean` |`true` |Indicate whether to display the dialog box | 238 | |`openLocationServices` (optional) |`Boolean` |`true` |Indicate whether to display the location services screen | 239 | |`preventOutSideTouch` (optional) |`Boolean` |`true` |To prevent the location services window from closing when it is clicked outside | 240 | |`preventBackClick` (optional) |`Boolean` |`true` |To prevent the location services popup from closing when it is clicked back button | 241 | |`providerListener` (optional) |`Boolean` |`false` |Used to trigger `locationProviderStatusChange listener when the location state changes. | 242 | |`style` (optional) |`Object` |`{}` |Change colors| 243 | 244 | ### Methods 245 | 246 | | Name | Return | Return Value | 247 | |------------------------------------|--------------------|------------------| 248 | |`checkLocationServicesIsEnabled` | Promise | Object | 249 | |`forceCloseDialog` (optional using) | void | - | 250 | |`stopListener` (optional using) | void | - | 251 | -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | def safeExtGet(prop, fallback) { 4 | rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback 5 | } 6 | 7 | android { 8 | compileSdkVersion safeExtGet('compileSdkVersion', 26) 9 | buildToolsVersion safeExtGet('buildToolsVersion', '26.0.3') 10 | 11 | defaultConfig { 12 | minSdkVersion safeExtGet('minSdkVersion', 16) 13 | targetSdkVersion safeExtGet('targetSdkVersion', 26) 14 | } 15 | lintOptions { 16 | warning 'InvalidPackage' 17 | } 18 | } 19 | 20 | dependencies { 21 | compileOnly 'com.facebook.react:react-native:+' 22 | } 23 | -------------------------------------------------------------------------------- /android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/src/main/java/com/showlocationservicesdialogbox/LocationServicesDialogBoxModule.java: -------------------------------------------------------------------------------- 1 | package com.showlocationservicesdialogbox; 2 | 3 | import android.app.Activity; 4 | import android.app.AlertDialog; 5 | import android.content.*; 6 | import android.graphics.Color; 7 | import android.graphics.drawable.ColorDrawable; 8 | import android.location.LocationManager; 9 | import android.text.Html; 10 | import android.text.Spanned; 11 | import android.view.Window; 12 | import android.widget.Button; 13 | import com.facebook.react.bridge.*; 14 | import com.facebook.react.modules.core.DeviceEventManagerModule; 15 | 16 | public class LocationServicesDialogBoxModule extends ReactContextBaseJavaModule implements ActivityEventListener { 17 | private Promise promiseCallback; 18 | private ReadableMap map; 19 | private Activity currentActivity; 20 | private static final int ENABLE_LOCATION_SERVICES = 1009; 21 | private static AlertDialog alertDialog; 22 | private Boolean isReceive = false; 23 | private BroadcastReceiver providerReceiver = null; 24 | private ReactApplicationContext RNContext; 25 | 26 | LocationServicesDialogBoxModule(ReactApplicationContext reactContext) { 27 | super(reactContext); 28 | RNContext = reactContext; 29 | reactContext.addActivityEventListener(this); 30 | } 31 | 32 | @Override 33 | public void onNewIntent(Intent intent) { 34 | } 35 | 36 | @Override 37 | public String getName() { 38 | return "LocationServicesDialogBox"; 39 | } 40 | 41 | @ReactMethod 42 | public void checkLocationServicesIsEnabled(ReadableMap configMap, Promise promise) { 43 | promiseCallback = promise; 44 | map = configMap; 45 | currentActivity = getCurrentActivity(); 46 | checkLocationService(false); 47 | } 48 | 49 | @ReactMethod 50 | public void forceCloseDialog() { 51 | try { 52 | if (alertDialog != null && alertDialog.isShowing() && promiseCallback != null) { 53 | alertDialog.cancel(); 54 | } 55 | } catch (Exception ignored) {} 56 | } 57 | 58 | @ReactMethod 59 | public void stopListener() { 60 | isReceive = false; 61 | try { 62 | if (providerReceiver != null) { 63 | getReactApplicationContext().unregisterReceiver(providerReceiver); 64 | providerReceiver = null; 65 | } 66 | } catch (Exception ignored) { 67 | } 68 | } 69 | 70 | private void checkLocationService(Boolean activityResult) { 71 | if (currentActivity == null || map == null || promiseCallback == null) return; 72 | LocationManager locationManager = (LocationManager) currentActivity.getSystemService(Context.LOCATION_SERVICE); 73 | WritableMap result = Arguments.createMap(); 74 | 75 | Boolean isEnabled = this.isEnabled(locationManager); 76 | 77 | if (!isEnabled) { 78 | if (activityResult || map.hasKey("openLocationServices") && !map.getBoolean("openLocationServices")) { 79 | promiseCallback.reject(new Throwable("disabled")); 80 | if (map.hasKey("providerListener") && map.getBoolean("providerListener")) { 81 | startListener(); 82 | } 83 | } else if (!map.hasKey("showDialog") || map.getBoolean("showDialog")) { 84 | displayPromptForEnablingGPS(currentActivity, map, promiseCallback); 85 | } else { 86 | newActivity(currentActivity); 87 | } 88 | } else { 89 | if (map.hasKey("providerListener") && map.getBoolean("providerListener")) { 90 | startListener(); 91 | } 92 | 93 | result.putString("status", "enabled"); 94 | result.putBoolean("enabled", true); 95 | result.putBoolean("alreadyEnabled", !activityResult); 96 | 97 | promiseCallback.resolve(result); 98 | } 99 | } 100 | 101 | private void displayPromptForEnablingGPS(final Activity activity, final ReadableMap configMap, final Promise promise) { 102 | final AlertDialog.Builder builder = new AlertDialog.Builder(activity); 103 | 104 | final Spanned message = ( 105 | android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N ? 106 | Html.fromHtml(configMap.getString("message"), Html.FROM_HTML_MODE_LEGACY) : 107 | Html.fromHtml(configMap.getString("message")) 108 | ); 109 | 110 | builder.setMessage(message) 111 | .setPositiveButton(configMap.getString("ok"), 112 | new DialogInterface.OnClickListener() { 113 | public void onClick(DialogInterface dialogInterface, int id) { 114 | newActivity(activity); 115 | dialogInterface.dismiss(); 116 | } 117 | }) 118 | .setNegativeButton(configMap.getString("cancel"), 119 | new DialogInterface.OnClickListener() { 120 | public void onClick(DialogInterface dialogInterface, int id) { 121 | promise.reject(new Throwable("disabled")); 122 | dialogInterface.cancel(); 123 | } 124 | }); 125 | 126 | alertDialog = builder.create(); 127 | 128 | if (!configMap.hasKey("preventOutSideTouch") || configMap.getBoolean("preventOutSideTouch")) { 129 | alertDialog.setCanceledOnTouchOutside(false); 130 | } 131 | 132 | if (!configMap.hasKey("preventBackClick") || configMap.getBoolean("preventBackClick")) { 133 | alertDialog.setCancelable(false); 134 | } 135 | 136 | alertDialog.show(); 137 | 138 | if (configMap.hasKey("style")) { 139 | colorAdjustment(alertDialog, configMap.getMap("style")); 140 | } 141 | } 142 | 143 | private void colorAdjustment(AlertDialog dialog, ReadableMap colorMap) { 144 | Window window = dialog.getWindow(); 145 | 146 | if (window != null) { 147 | Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE); 148 | Button negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE); 149 | 150 | if (colorMap.hasKey("backgroundColor")) { 151 | window.setBackgroundDrawable(new ColorDrawable(Color.parseColor(colorMap.getString("backgroundColor")))); 152 | } 153 | 154 | if (colorMap.hasKey("positiveButtonTextColor")) { 155 | positiveButton.setTextColor(Color.parseColor(colorMap.getString("positiveButtonTextColor"))); 156 | } 157 | 158 | if (colorMap.hasKey("positiveButtonBackgroundColor")) { 159 | positiveButton.setBackgroundColor(Color.parseColor(colorMap.getString("positiveButtonBackgroundColor"))); 160 | } 161 | 162 | if (colorMap.hasKey("negativeButtonTextColor")) { 163 | negativeButton.setTextColor(Color.parseColor(colorMap.getString("negativeButtonTextColor"))); 164 | } 165 | 166 | if (colorMap.hasKey("negativeButtonBackgroundColor")) { 167 | negativeButton.setBackgroundColor(Color.parseColor(colorMap.getString("negativeButtonBackgroundColor"))); 168 | } 169 | } 170 | } 171 | 172 | private void newActivity(final Activity activity) { 173 | final String action = android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS; 174 | activity.startActivityForResult(new Intent(action), ENABLE_LOCATION_SERVICES); 175 | } 176 | 177 | private void startListener() { 178 | try { 179 | providerReceiver = new LocationProviderChangedReceiver(); 180 | getReactApplicationContext().registerReceiver(providerReceiver, new IntentFilter(LocationManager.PROVIDERS_CHANGED_ACTION)); 181 | isReceive = true; 182 | } catch (Exception ignored) { 183 | } 184 | } 185 | 186 | private Boolean isEnabled(LocationManager locationManager) { 187 | Boolean enabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); 188 | if (map != null) { 189 | if (map.hasKey("enableHighAccuracy") && map.getBoolean("enableHighAccuracy")) { 190 | // High accuracy needed. Require NETWORK_PROVIDER. 191 | enabled = enabled && locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); 192 | } else { 193 | // Either highAccuracy is not a must which means any location will suffice 194 | // or it is not specified which means again that any location will do. 195 | enabled = enabled || locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER); 196 | } 197 | } 198 | 199 | return enabled; 200 | } 201 | 202 | private void sendEvent() { 203 | if (isReceive) { 204 | LocationManager locationManager = (LocationManager) currentActivity.getSystemService(Context.LOCATION_SERVICE); 205 | WritableMap params = Arguments.createMap(); 206 | if (locationManager != null) { 207 | boolean enabled = this.isEnabled(locationManager); 208 | 209 | params.putString("status", (enabled ? "enabled" : "disabled")); 210 | params.putBoolean("enabled", enabled); 211 | 212 | if (RNContext != null) { 213 | RNContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit("locationProviderStatusChange", params); 214 | } 215 | } 216 | } 217 | } 218 | 219 | @Override 220 | public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) { 221 | if (requestCode == ENABLE_LOCATION_SERVICES) { 222 | currentActivity = activity; 223 | checkLocationService(true); 224 | } 225 | } 226 | 227 | private final class LocationProviderChangedReceiver extends BroadcastReceiver { 228 | @Override 229 | public void onReceive(Context context, Intent intent) { 230 | String action = intent.getAction(); 231 | 232 | if (action != null && action.matches("android.location.PROVIDERS_CHANGED")) { 233 | sendEvent(); 234 | } 235 | } 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /android/src/main/java/com/showlocationservicesdialogbox/LocationServicesDialogBoxPackage.java: -------------------------------------------------------------------------------- 1 | package com.showlocationservicesdialogbox; 2 | 3 | import com.facebook.react.ReactPackage; 4 | import com.facebook.react.bridge.JavaScriptModule; 5 | import com.facebook.react.bridge.NativeModule; 6 | import com.facebook.react.bridge.ReactApplicationContext; 7 | import com.facebook.react.uimanager.ViewManager; 8 | 9 | import java.util.ArrayList; 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | public class LocationServicesDialogBoxPackage implements ReactPackage { 14 | @Override 15 | public List createNativeModules(ReactApplicationContext reactApplicationContext) { 16 | List modules = new ArrayList(); 17 | modules.add(new LocationServicesDialogBoxModule(reactApplicationContext)); 18 | return modules; 19 | } 20 | 21 | // Deprecated RN 0.47 22 | public List> createJSModules() { 23 | return Collections.emptyList(); 24 | } 25 | 26 | @Override 27 | public List createViewManagers(ReactApplicationContext reactApplicationContext) { 28 | return Collections.emptyList(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webyonet/react-native-android-location-services-dialog-box/6bfb7be6175f6d09d8557092485e1ea017933ff6/demo.gif -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import { NativeModules } from 'react-native'; 2 | export default NativeModules.LocationServicesDialogBox; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-android-location-services-dialog-box", 3 | "version": "2.8.2", 4 | "description": "A react-native component for turn on the dialog box from android location services", 5 | "author": "webyonet ", 6 | "main": "index.js", 7 | "license": "MIT", 8 | "repository": { 9 | "type": "git", 10 | "url": "git@github.com:webyonet/react-native-android-location-services-dialog-box.git" 11 | }, 12 | "keywords": [ 13 | "react-component", 14 | "react-native", 15 | "android", 16 | "android-location-services", 17 | "geo-location", 18 | "location-services", 19 | "geo-location-dialog-box", 20 | "location-services-dialog-box", 21 | "react-native-location-services", 22 | "react-native-location-services-dialog-box" 23 | ], 24 | "peerDependencies": { 25 | "react-native": ">= 0.56.0" 26 | } 27 | } 28 | --------------------------------------------------------------------------------