Android GPS 查询位置数据不正确

2022-01-22 00:00:00 gps android java

我没有为此使用模拟位置...事实上,代码在上周运行良好.

I am not using mock locations for this... In fact the code was working fine just last week.

我有一个应用程序,它收集 GPS 数据并使用应用程序本身生成的 X、Y 坐标输出谷歌地图链接.我不是 100% 确定它为什么不能按应有的方式工作,但是当我请求应用程序根据手机提供的 GPS 位置创建谷歌地图链接时,它告诉我我距离我的点 5 - 6 个街区起源(我当时实际上在哪里)不是我想要它做的事情

I have an app that gathers GPS data and spits out a google maps link using X,Y coordinates generated by the application itself. I am not 100% sure why its not working the way it should be but when I request the app to make a google maps link based on the GPS location provided by the phone it tells me I am 5 - 6 blocks away from my point of origin (Where I actually am at the time) Not quite what I want it to do

已知:

  • 我已设置适当的权限
  • 上周所有代码都运行良好

这是收集 GPS 信息的代码:

Here is the code to gather the GPS info:

        Toast.makeText(context, "Gathering GPS Data...", Toast.LENGTH_SHORT).show();
    gps = new gpsTracker(Settings.this);
    if(gps.canGetLocation()){
        try{
            gps.getLocation();
            lon = gps.getLongitude();
            lat = gps.getLatitude();
            Toast.makeText(getApplicationContext(), "Your location is - 
lat: " + lat + "
lon: " + lon, Toast.LENGTH_LONG).show();
        }
        catch(Exception  e){}
    }
    else{
        gps.showSettingsAlert();
    }

以上所有内容均来自:

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

// 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;
            // First get location from Network Provider
            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();
                    }
                }
            }
            // 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();
                        }
                    }
                }
            }
        }

    } 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;
}

/**
 * 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;
}

推荐答案

根据指定的[4-5个块的差异],您可能正在从networkProviderlocation仅代码>.

From what is specified[difference of 4-5 blocks], you may be obtaining the location from networkProvider only.

有了问题中提到的这个 gpsTracker 代码,
需要进行一些修改,而不是按原样使用代码:

With this gpsTracker code mentioned in the question,
there are a few modifications required, instead of using the code as it is:

1.有 2 个 if 循环来验证 location 的来源是否启用并且没有 'else':

1. There are 2 if loops which verify the source of location is enabled or not and No 'else':

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

这意味着当您可以从两个来源获取 location 时,应用程序将完成两倍的工作.此外,获得的location 的来源总是模棱两可.

This means the application is going to do twice the work when you can obtain the location from both sources. Further, the source of location obtained always remains ambiguous.

当您只需要近似的 location 时,这很好,它主要不应该为空.

This is good when you just need approximate location which should not be null majorly.

如果你只想使用这个类来获取location,请尝试根据需求构造if-else,并确保如果不会重复>location 已获取.
Eg. 如果 GPS 的偏好更高,适用于您的情况,将 if 移到上方并将带有 else 的网络条件,例如:

If you want to use only this class to obtain location, try structuring the if-else according to requirement and ensuring that its not going to repeat if the location is obtained.
Eg. if GPS is on a higher preference, applies in your case, shift that if above and put the network condition with an else like:

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

根据您的要求,我建议删除网络提供商部分并仅从 GPS 获取 location,尤其是在视线不成问题的情况下.

For your requirement, i suggest removing the network provider part and obtaining the location only from GPS, esp if line of sight is not a problem.

当您的代码工作正常时,它必须从 GPS 获取位置并将其设置在对象中.但是因为有两个if"而没有else",所以你永远不会知道location是来自网络还是GPS——你可以检查 location.getProvider() 里面的条件canGetLocation()

When your code was working fine, it must be fetching the location from GPS and setting it in the object. But because of the two "if" and no "else", you'l never know whether location obtained is from Network or GPS - you can check location.getProvider() inside the condition of canGetLocation()

2.此外,您可以记录消息或提示针对某个特定来源的某些操作...例如:
在这部分:

2. Also, you can log the message or prompt some action for one particular source...like:
In this part:

 if (!isGPSEnabled && !isNetworkEnabled) {
            // no network provider is enabled
        }    

只需将其分成两个不同的 if(s) 并相应地编码.到目前为止,这里没有任何反应,因此除非您从外部检查,否则您不会知道两者是否都被禁用.

just separate it into two different if(s) and code accordingly. As of now, nothing happens here so you wouldn't know if both are disabled unless you check it externally.

建议:试试 LocationClient 哪个检索当前位置 使用 GooglePlayServices.我发现它更可靠和有用.检查这个 Fused Location Provider example,设置 LocationRequest 对象 根据您的要求是关键.

Suggestion: Try the LocationClient which uses GooglePlayServices for Retrieving Current Location . I have found it more reliable and useful. Check this Fused Location Provider example, setting LocationRequest object according to your requirement is the key.

另一个更新:刚刚遇到:关于堆栈溢出的有用问题 - 获取用户位置的好方法

Another update: just came across: useful ques on stack overflow - Good way of getting the users location

任何查找此问题/答案的人的更新
关于LocationClient的建议;
com 下不再找到 LocationClient.google.android.gms.location,参考:
Android 播放服务 6.5:LocationClient 丢失

相关文章