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!
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....
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 :-)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With