How to programmatically enable and disable GPS in Ionic Framework or Cordova
Solution 1
As far as I'm aware there isn't the ability to directly disable GPS from your app.
If you are trying to allow the user to disable GPS, I achieved this by adding a setting to localStorage
that the user can change on the settings page in my app. Every time I check for GPS in my location factory, I check against the setting and run the error callback if the setting was disabled.
There may be some sort of call which can automatically open the location settings page on your device as I have seen other apps do this, but I'm not sure if that is supported in Cordova/Ionic yet.
Solution 2
I wanna open GPS automatically according to my requirements.
So I used cordova-plugin-request-location-accuracy
When GPS is off, it request user to open GPS..It's very helpful for me..
Ionic1
https://github.com/dpa99c/cordova-plugin-request-location-accuracy
Ionic2
https://ionicframework.com/docs/native/location-accuracy/
Best Regards....
Solution 3
As far as I know controlling the device location is not possible as there isn't any Ionic or Cordova plugin available for this purpose. One can get the device position using the Geolocation plugin. But this doesn't work in case the device GPS is off. I have managed a work around to enable device location using a JSInterface bridge. This solution is valid only for the ionic android platform and honestly I would recommend using this only if turning on the device GPS is extremely crucial to your application.
Explanation: Google LocationServices gives us a provision of enabling device location. I have created a bridge between ionic and native platform. My ionic page requests for the device location using this bridge. ex: NativeBridge.functionNameInActivity
Native function requesting device position<----->JSInterface Bridge<---->Ionic function
1. Below is the code for the MainActivity which extends CordovaActivity:
public class MainActivity extends CordovaActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, ResultCallback<LocationSettingsResult> {
public static Context mContext;
private Intent mIntent;
private final int REQUEST_CODE_LOCATION = 101;
private final int REQUEST_CODE_LOCATION_SETTINGS = 102;
protected GoogleApiClient mGoogleApiClient;
protected LocationRequest locationRequest;
public static double LATITUDE, LONGITUDE;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mContext = getApplicationContext();
loadUrl(launchUrl);
mIntent = new Intent(this, LocationService.class);
final WebView webView = (WebView) appView.getEngine().getView();
webView.addJavascriptInterface(this.getJavaScriptHandler(), "NativeBridge");
}
@Override
public void onDestroy() {
super.onDestroy();
stopService(mIntent);
}
public void configureLocationClient() {
final int intervalInSecs = 30;
final int fastestIntervalInSecs = 5;
final int milliSecondMultiplier = 1000;
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
mGoogleApiClient.connect();
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(intervalInSecs * milliSecondMultiplier);
locationRequest.setFastestInterval(fastestIntervalInSecs * milliSecondMultiplier);
}
public void checkLocationPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE_LOCATION);
} else {
configureLocationClient();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_LOCATION_SETTINGS) {
if (resultCode == RESULT_OK) {
startService(mIntent);
} else {
//Display a message requesting location access for further operations
}
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
Map<String, Integer> perms;
switch (requestCode) {
case REQUEST_CODE_LOCATION:
perms = new HashMap<String, Integer>();
perms.put(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
for (int i = 0; i < permissions.length; i++) {
perms.put(permissions[i], grantResults[i]);
}
if (perms.get(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
//Start location fetching service
configureLocationClient();
} else {
// Location Permission Denied
DisplayUtils.displayToast(mContext, AppConstants.MSG_PERMISSIONS_LOCATION);
return;
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
@Override
public void onConnected(@Nullable Bundle bundle) {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(
mGoogleApiClient,
builder.build()
);
result.setResultCallback(this);
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
}
@Override
public void onResult(@NonNull LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
/*Start location fetching service*/
startService(mIntent);
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
/*Location settings are not satisfied. Show the user a dialog by calling startResolutionForResult(), and check the result in onActivityResult().*/
try {
status.startResolutionForResult(MainActivity.this, REQUEST_CODE_LOCATION_SETTINGS);
} catch (IntentSender.SendIntentException e) {
e.printStackTrace();
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
/*Location settings unavailable*/
break;
default:
break;
}
}
public JavaScriptHandler getJavaScriptHandler() {
return new JavaScriptHandler(this.getApplicationContext());
}
/***
* Javascript handler
***/
public class JavaScriptHandler {
CordovaActivity parentActivity;
private Context mContext;
public JavaScriptHandler(final CordovaActivity activity) {
this.parentActivity = activity;
}
public JavaScriptHandler(final Context context) {
this.mContext = context;
}
@JavascriptInterface
public boolean ifLocationPermissionGranted() {
return ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED;
}
@JavascriptInterface
public boolean ifLocationAccessible() {
LocationManager mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
return mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
@JavascriptInterface
public void startLocationService() {
checkLocationPermission();
}
@JavascriptInterface
public String getLatitude() {
return String.valueOf(LATITUDE);
}
@JavascriptInterface
public String getLongitude() {
return String.valueOf(LONGITUDE);
}
}
}
2. Location Service class:
public class LocationService extends Service {
private static String TAG = "TAG-LocationService";
private LocationManager mLocationManager;
private static final int LOCATION_INTERVAL = 2000;
private static final float LOCATION_DISTANCE = 0f;
private class LocationListener implements android.location.LocationListener {
Location mLastLocation;
public LocationListener(String provider) {
mLastLocation = new Location(provider);
}
@Override
public void onLocationChanged(Location location) {
mLastLocation.set(location);
if (location != null) {
MainActivity.LATITUDE = mLastLocation.getLatitude();
MainActivity.LONGITUDE = mLastLocation.getLongitude();
}
}
@Override
public void onProviderDisabled(String provider) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
}
LocationListener[] mLocationListeners = new LocationListener[]{
new LocationListener(LocationManager.GPS_PROVIDER), new LocationListener(LocationManager.NETWORK_PROVIDER),
};
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
@Override
public void onCreate() {
initializeLocationManager();
try {
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[1]);
} catch (SecurityException ex) {
ex.printStackTrace();
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
}
try {
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
mLocationListeners[0]);
} catch (SecurityException ex) {
ex.printStackTrace();
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
}
}
@Override
public void onDestroy() {
super.onDestroy();
if (mLocationManager != null) {
for (int i = 0; i < mLocationListeners.length; i++) {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
mLocationManager.removeUpdates(mLocationListeners[i]);
}
}
}
}
private void initializeLocationManager() {
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
}
}
}
3. Code for your JS controller file:
MyDemoApp.controller('LocationController', function ($scope, $cordovaToast, $ionicPopup) {
$scope.goForIt = function () {
if (NativeBridge.ifLocationPermissionGranted()) {
if (NativeBridge.ifLocationAccessible()) {
$scope.getDevicePosition();
} else {
$scope.showLocationAlert();
}
} else {
$scope.showLocationAlert();
}
}
$scope.getDevicePosition = function () {
var positionLatitude = parseFloat(NativeBridge.getLatitude());
var positionLongitude = parseFloat(NativeBridge.getLongitude());
}
$scope.showLocationAlert = function () {
var confirmPopup = $ionicPopup.confirm({
title: 'Location Service required for further operation',
template: 'Grant permission to access Location?'
});
confirmPopup.then(function (res) {
if (res) {
NativeBridge.startLocationService();
} else {
$cordovaToast.showShortCenter("Location access required");
}
});
};
});
4. Add below line in the dependencies of your build.gradle:
compile 'com.google.android.gms:play-services-location:10.0.1'
5. Add permission to your manifest
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-feature android:name="android.hardware.location.gps" />
6. Declare Service in your manifest:
<service android:name=".LocationService"></service>
On calling this function, you will see a similar dialog asking to enable device location.
Again, I would recommend using this only if enabling the user location is extremely important to your app functionality because its a lot of work. Feel free to criticize :-)
balfonso
Updated on April 17, 2020Comments
-
balfonso about 4 years
My problem is simple. I need a way to turn on and off GPS using a button inside an Ionic app. I've check the docs and read this ng-cordova plugin http://ngcordova.com/docs/plugins/geolocation/ but they don't seem have this funcction. Am I just missing something or is this even possible in Ionic Framework? Thanks!
-
balfonso over 8 yearsHi @SM3RKY! From what I understand on your answer.. you have a GPS (on/off) on your app's settings page. This settings is independent from the device's GPS settings. So in short, your app's GPS settings works only if the Device's GPS settings is already on but still you won't be able to turn on the device's GPS settings. It's kind of like telling your app to use or not to use the GPS even if it's enabled. Am I correct?
-
SM3RKY over 8 yearsYes that is correct, Is that what you are looking for, or are you trying to enable the device GPS setting from the app of it is disabled, as I am unsure as to whether you can do the latter
-
balfonso over 8 yearsOriginally I've wanted a direct on/off for the GPS inside the app. But after @Joerg commented, I realized I needed to make some more research and I finally came to the conclusion that the latter (to open the settings page) would be the best option. I haven't applied that though on my app yet. I've moved on to other tasks in the mean time but will definitely apply it later. At this point, I feel that there might already be a plugin for this but haven't made any searches if in fact Ionic and Cordova has this. Thanks for the help btw :D
-
SM3RKY over 8 yearsGreat, When you do sort out a way to open the settings page for location please post it here as I would be interested in that too. Good luck! :)
-
AbhiRam almost 6 yearsPlease see my problem stackoverflow.com/questions/51380699/…
-
Kapil Soni about 5 years@sawpyae its working perfectly but if we have to store any value from this.locationAccuracy.request this function its not working perfectly?
-
Kapil Soni about 5 yearsSanket: hi sir....how to manage below scenario: suppose alert is open then we have click ok button and gps is enable but then we have disable the gps agin then click harware back button of my mobile now alert is not open again please tell me how to manage above scenario?
-
Terry Windwalker almost 2 years@AbhiRam Question seems removed.