简体   繁体   中英

Android onLocationChanged() receiving updates, but location never changes

I'm writing a simple Android navigation app, which will eventually show the straight-line distance between the user's current location and another point, but I can't get the GPS location service to work properly. I have an Activity that implements LocationListener and updates the UI in onLocationChanged(). But once I start the app on the device (via Android Studio), the GPS gets a fix and displays the location once, and then never updates afterward. Never. Not even when I go outside and walk around. When I rotate the screen, causing the Activity to reregister itself as a listener, I sometimes see a change in the location, but sometimes I don't. Putting additional code into onLocationChanged() reveals that onLocationChanged() is being called, but the actual location data is not changing at all.

It seems to be getting a fix in one or two seconds, making me think that it's just spitting out the cached location. But sometimes, on starting the app, I'll see a couple seconds of actual updates with actual data, before it stops updating. Also, on plugging the phone back into the computer, I'll sometimes see one update. And this even happens when I go outside, clear the app's cached data in the system settings menu, and return to the app. There will be a few updates, and then it settles on one location and refuses to update further.

The weird part is that it worked just fine two hours ago. The only things I've added to my code since then are UI elements.

The device I'm using is a Nokia X2, so switching to the newer Google Play Services API is not an option. In the logs, I see "D/ContextImpl: BYDSafe: new BYDSafeLocationManager" when I first get the LocationManager. Googling for it turns up absolutely nothing, so I assume this is some Nokia proprietary class. If this class is the cause of my problems, then is there any way I can force Android to give me the stock Android LocationManager?

public class NavScreen extends Activity implements LocationListener {

    private TextView latField;
    private TextView longField;
    private TextView altField;
    private TextView beField;
    private TextView spField;
    private TextView luField;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_nav_screen);

        latField = (TextView)(findViewById(R.id.latitudeField));
        longField = (TextView)(findViewById(R.id.longitudeField));
        altField = (TextView)(findViewById(R.id.altitudeField));
        beField = (TextView)(findViewById(R.id.bearingField));
        spField = (TextView)(findViewById(R.id.speedField));
        luField = (TextView)(findViewById(R.id.lastUpdateField));
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.nav_screen, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onResume()
    {
        super.onResume();
        LocationManager manager = (LocationManager)(getSystemService(Context.LOCATION_SERVICE));
        if(manager.isProviderEnabled(LocationManager.GPS_PROVIDER))
        {
            manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1, 0, this);
        }
        else
        {
            Toast.makeText(this, "Please enable GPS", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onPause()
    {
        super.onPause();
        LocationManager manager = (LocationManager)(getSystemService(Context.LOCATION_SERVICE));
        manager.removeUpdates(this);
    }

    //Location callbacks

    @Override
    public void onLocationChanged(Location location) {
        String lat = String.format("%f", location.getLatitude());
        String lon = String.format("%f", location.getLongitude());
        String alt = String.format("%f", location.getAltitude());
        String bearing = String.format("%f", location.getBearing());
        String speed = String.format("%f", location.getSpeed());

        latField.setText("Latitude: " + lat);
        longField.setText("Longitude: " + lon);
        altField.setText("Altitude: " + alt + "m");
        beField.setText("Bearing: " + bearing + " degrees");
        spField.setText("Speed: " + speed + " m/s");
        luField.setText("Last update: " + new Date(System.currentTimeMillis()).toString());
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        switch(status)
        {
            case LocationProvider.OUT_OF_SERVICE:
                Log.d("DEBUG", provider + " out of service");
                Toast.makeText(this, provider + " out of service", Toast.LENGTH_SHORT).show();
                break;
            case LocationProvider.TEMPORARILY_UNAVAILABLE:
                Log.d("DEBUG", provider + " temp. unavailable");
                Toast.makeText(this, provider + " temp. unavilable", Toast.LENGTH_SHORT).show();
                break;
            case LocationProvider.AVAILABLE:
                Log.d("DEBUG", provider + " available");
                Toast.makeText(this, provider + " available", Toast.LENGTH_SHORT).show();
                break;
            default:
        }
    }

    @Override
    public void onProviderEnabled(String provider) {
        Toast.makeText(this, provider + " enabled", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onProviderDisabled(String provider) {
        Toast.makeText(this, provider + " disabled", Toast.LENGTH_SHORT).show();
    }
}

on first look, your code looks correctly. I suggest to test two things.

  1. register listener in all cases, not only if your check on enabled provider is positive. This makes you sure, that you'll listen for updates no matter what happen on device (for example user may enable provider by any 3rd party app on background)

  2. try to change time parameter in manager.requestLocationUpdates also to 0 . I remember that I also had some problems with it and 0, 0 values was best in the end.

Hope this helps

You have to initiate all your required component in onCreate() method whenever extends an Activity .

In your case you have initiated all TextView except LocationManager .

Simply add the following code inside the onCreate() method.

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    ...
    LocationManger l = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
    //time interval needs to be multiplied by 1000 as millisecond is the actual unit.
    l.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1*1000, 0, this);
    this.onLocationChanged(null);//It is now initiated whenever app started
}

Or you can declare the LocationManager outside onCreate() like your TextView in case you need to deploy it anywhere (etc. inside onResume ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM