如何在 Ionic Framework 或 Cordova 中以编程方式启用和禁用 GPS

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

我的问题很简单。我需要一种使用 Ionic 应用程序内的按钮打开和关闭 GPS 的方法。我查看了文档并阅读了这个 ng-cordova 插件 http://ngcordova.com/docs/plugins/geolocation/ 但他们似乎没有这个功能。我只是遗漏了什么,或者这在 Ionic Framework 中是否可行?谢谢!

据我所知,您的应用无法直接禁用 GPS。

如果您试图让用户禁用 GPS,我通过向 localStorage 添加一个设置来实现此目的,用户可以在我的应用程序的设置页面上更改该设置。每次我在我的位置工厂中检查 GPS 时,我都会检查设置和 运行 如果设置被禁用,则错误回调。

可能有某种调用可以自动打开您设备上的位置设置页面,因为我看到其他应用程序可以这样做,但我不确定 Cordova/Ionic 是否支持它。

经过研究,我意识到 Ionic 无法在应用程序内打开 on/off 位置(至少目前不能),因此最好的选择是打开设备位置设置,因为您不仅可以更改 GPS 的状态,还可以更改功率和精度。

您可以使用 cordova-diagnostic-plugin 插件(带有很好的文档)来操作设备设置,例如 wifi、蓝牙、GPS。

希望对您有所帮助!

我想根据我的要求自动打开GPS。
所以我使用了cordova-plugin-request-location-accuracy
当GPS关闭时,它要求用户打开GPS..这对我很有帮助..
Ionic1
https://github.com/dpa99c/cordova-plugin-request-location-accuracy

Ionic2
https://ionicframework.com/docs/native/location-accuracy/
最好的问候....

正在测试此插件 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

位置-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();
  }
}

位置-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>

到目前为止,我已经在 Android phone 上进行了测试。让我知道 iOS 是否按原样工作。

据我所知,控制设备位置是不可能的,因为没有任何 Ionic 或 Cordova 插件可用于此目的。可以使用 Geolocation plugin 获取设备位置。但这在设备 GPS 关闭的情况下不起作用。我已经设法解决了使用 JSInterface 桥启用设备定位的问题。此解决方案仅适用于 ionic android 平台,老实说,我建议仅在打开设备 GPS 对您的应用程序至关重要时才使用此解决方案。

说明: Google LocationServices 提供启用设备位置。我在离子平台和原生平台之间架起了一座桥梁。我的离子页面使用此桥请求设备位置。例如:NativeBridge.functionNameInActivity

请求设备位置的本机函数<----->JSInterface Bridge<---->Ionic 函数

1.下面是扩展 CordovaActivity 的 MainActivity 的代码:

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。定位服务 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。您的 JS 控制器文件的代码:

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。在 build.gradle:

的依赖项中添加以下行

compile 'com.google.android.gms:play-services-location:10.0.1'

5.向您的清单添加权限

<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.在清单中声明服务:

<service android:name=".LocationService"></service>

调用此函数时,您会看到一个类似的对话框,要求启用设备定位。

同样,我建议仅在启用用户位置对您的应用程序功能极其重要时才使用此功能,因为它需要大量工作。欢迎大家批评指正:-)