Android 最准确的位置 API

Android's most accurate Location API

为了工作,我的应用程序需要一个位置 API。 我打算使用 Mapbox 平台来定制它的设计(因为 Google Maps 就我而言,不提供这种级别的定制。

文档说我们应该在构建位置时使用 Google Play API 应用程序:

The Google Play services location APIs are preferred over the Android framework location APIs (android.location) as a way of adding location awareness to your app. If you are currently using the Android framework location APIs, you are strongly encouraged to switch to the Google Play services location APIs as soon as possible.

我的问题是: 就 GPS 精度而言,Google Play API 是最有效的 API 吗? 或者我应该使用 LocationManager 和 LocationListener 的方式吗?

我需要准确性。我应该使用哪一个? 谢谢

使用FusedLocationProviderApi and set LocationRequest priority to PRIORITY_HIGH_ACCURACY

这是最新的 API 以获取准确的位置,google 建议使用它。

检查准确性详细信息here

基本上Google播放服务API通过融合GPS+NetworkProvider+passive providers可以得到准确位置的智能。

在android中也有三种位置:

  1. GPS_PROVIDER
  2. NETWORK_PROVIDER
  3. PASSIVE_PROVIDER

因此,根据我的编码经验,我了解到如果您使用:

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 10, new MyLocationListener());

您将获得高达 14 位以上小数位的精度。

但是如果你像这样使用它们的融合:

LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, my_google_listener);

您将获得高达 6 到 7 位小数的精度。尝试一下 !!! reference

但请注意这里的一些事情,GPS 提供程序需要时间来获取位置,而 Google 定位要快得多,因为它从 API 调用其 google 服务器数据库获取数据。

GPS 离线工作,而 google 提供商通过移动或 wifi 数据获取位置。

根据我的经验,Google 服务位置 API 更适合用于以下方面:

  • 他们处理用户设置,选择最佳的可用位置提供商。如果您选择直接使用 LocationManager,您的代码将需要处理它。
  • 您可能希望用更少的电量获得更好的位置,因为 Google 会定期更新他们使用 WiFi、手机信号塔等确定位置的算法

根据我的经验,使用 Google 服务,在许多情况下,对于地图应用程序而言足够精确的位置(几十米)不需要 GPS 数据。不过,FusedLocationProvider 也可能是这种情况,电池使用数字可能是个例外。

总而言之,如果您没有理由不使用 Google 服务(例如 - 您定位到一个无法使用这些服务的国家/地区,或者想通过其他市场进行分销),您应该使用他们的服务位置 API.

您应该使用 LocationManager 以确保准确性。 你也可以使用这个 class.

//GPSTracker.java
import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.util.Log;

public class GPSTracker extends Service implements LocationListener {

private final Context mContext;

// flag for GPS status
boolean isGPSEnabled = false;

// flag for network status
boolean isNetworkEnabled = false;

// flag for GPS status
boolean canGetLocation = false;

Location location; // location
double latitude; // latitude
double longitude; // longitude
float bearing; // bearing

// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters

// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute

// Declaring a Location Manager
protected LocationManager locationManager;

public GPSTracker(Context context) {
    this.mContext = context;
    getLocation();
}

public Location getLocation() {
    try {
        locationManager = (LocationManager) mContext
                .getSystemService(LOCATION_SERVICE);

        // getting GPS status
        isGPSEnabled = locationManager
                .isProviderEnabled(LocationManager.GPS_PROVIDER);

        // getting network status
        isNetworkEnabled = locationManager
                .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

        if (!isGPSEnabled && !isNetworkEnabled) {
            // no network provider is enabled
        } else {
            this.canGetLocation = true;
            if (isNetworkEnabled) {
                locationManager.requestLocationUpdates(
                        LocationManager.NETWORK_PROVIDER,
                        MIN_TIME_BW_UPDATES,
                        MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                Log.d("Network", "Network");
                if (locationManager != null) {
                    location = locationManager
                            .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                    if (location != null) {
                        latitude = location.getLatitude();
                        longitude = location.getLongitude();
                        bearing = location.getBearing();
                    }
                }
            }
            // if GPS Enabled get lat/long using GPS Services
            if (isGPSEnabled) {
                if (location == null) {
                    locationManager.requestLocationUpdates(
                            LocationManager.GPS_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    Log.d("GPS Enabled", "GPS Enabled");
                    if (locationManager != null) {
                        location = locationManager
                                .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                        if (location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                            bearing = location.getBearing();
                        }
                    }
                }
            }
        }

    } catch (Exception e) {
        e.printStackTrace();
    }

    return location;
}

/**
 * Stop using GPS listener
 * Calling this function will stop using GPS in your app
 * */
public void stopUsingGPS(){
    if(locationManager != null){
        locationManager.removeUpdates(GPSTracker.this);
    }
}

/**
 * Function to get latitude
 * */
public double getLatitude(){
    if(location != null){
        latitude = location.getLatitude();
    }

    // return latitude
    return latitude;
}

/**
 * Function to get longitude
 * */
public double getLongitude(){
    if(location != null){
        longitude = location.getLongitude();
    }

    // return longitude
    return longitude;
}

public float getBearing() {
    if (location != null) {
        bearing = location.getBearing();
    }
    return bearing;
}

/**
 * Function to check GPS/wifi enabled
 * @return boolean
 * */
public boolean canGetLocation() {
    return this.canGetLocation;
}

/**
 * Function to show settings alert dialog
 * On pressing Settings button will lauch Settings Options
 * */
public void showSettingsAlert(){
    AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

    // Setting Dialog Title
    alertDialog.setTitle("GPS is settings");

    // Setting Dialog Message
    alertDialog.setMessage("GPS is not enabled. Do you want to go to settings menu?");

    // On pressing Settings button
    alertDialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog,int which) {
            Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
            mContext.startActivity(intent);
        }
    });

    // on pressing cancel button
    alertDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int which) {
            dialog.cancel();
        }
    });

    // Showing Alert Message
    alertDialog.show();
}

@Override
public void onLocationChanged(Location location) {
}

@Override
public void onProviderDisabled(String provider) {
}

@Override
public void onProviderEnabled(String provider) {
}

@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}

@Override
public IBinder onBind(Intent arg0) {
    return null;
}

}

//MainActivity.java
GPSTracker gps = new GPSTracker(MainActivity.this);

FusedLocationProviderApi is deprecated.You should use FusedLocationProviderClient 并且您应该添加 ACCESS_FINE_LOCATION 权限,而不是 ACCESS_COARSE_LOCATION 以获得最准确的位置。

并阅读 this 文章以了解为什么 FusedLocationProviderClient 是最佳解决方案。