How to programmatically enable and disable GPS in Ionic Framework or Cordova

天大地大妈咪最大 提交于 2020-01-02 06:42:20

问题


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!


回答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.




回答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....




回答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 :-)




回答4:


After a research, I realized that turning on/off location inside the app is not possible with Ionic (at least not for now), so the best choice is open the device location settings, because you can change not only the status of your GPS, you can change the power and precision too.

You can do that using cordova-diagnostic-plugin, a plugin (with a nice documentation) to manipulate the device settings like wifi, bluetooth, GPS.

I hope it helps!




回答5:


Was testing this plugin Location Accuracy on Ionic 3, the location is enabled without going through the setting page, which answers that it's possible to enable GPS programmatically. This is the example of the code I used after navigating into the modal page by checking if the location is enabled using Diagnostic plugin.

location-auth.ts

import { Component } from '@angular/core';
import { IonicPage,
         ViewController } from 'ionic-angular';
import { LocationAccuracy } from '@ionic-native/location-accuracy';

@IonicPage({
  name: 'location-auth'
})
@Component({
  selector: 'page-location-auth',
  templateUrl: 'location-auth.html',
})
export class LocationAuthPage {
  constructor(private locationAccuracy: LocationAccuracy,
              public viewCtrl: ViewController) {}

  requestAccuracy() {
    this.locationAccuracy.canRequest().then((canRequest: boolean) => {
      if(canRequest) {
        this.locationAccuracy.request(this.locationAccuracy.REQUEST_PRIORITY_HIGH_ACCURACY).then(() => {
            console.log('Request successful.')
            this.closeModal();
          },
          error => {
            console.log('Error requesting location permissions', error)
            this.closeModal();
          }
        );
      }
    });
  }

  closeModal() {
    this.viewCtrl.dismiss();
  }
}

location-auth.html

<ion-header>
  <ion-navbar color="primary">
    <ion-title>GPS Authorization</ion-title>
  </ion-navbar>
</ion-header>


<ion-content padding>
  <p>Your Location is not enabled yet, please turn on your gps location.</p>
  <button large
          ion-button
          block
          (click)="requestAccuracy()">Turn on your GPS</button>
</ion-content>

So far I've testing on Android phone. Let me know if iOS works the way it is.



来源:https://stackoverflow.com/questions/34766481/how-to-programmatically-enable-and-disable-gps-in-ionic-framework-or-cordova

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!