Android onLocationChanged() 接收更新,但位置永远不会改变



我正在编写一个简单的Android导航应用程序,它最终将显示用户当前位置与另一点之间的直线距离,但我无法让GPS定位服务正常工作。 我有一个实现LocationListener并在onLocationChanged()中更新UI的活动。 但是一旦我在设备上启动应用程序(通过Android Studio),GPS就会得到修复并显示一次位置,然后永远不会更新。 从不。 甚至当我出去走动时也不会。 当我旋转屏幕,导致活动重新注册为侦听器时,我有时会看到位置的变化,但有时看不到。 将额外的代码放入onLocationChanged()中,可以显示onLocationChanged()正在被调用,但实际的位置数据根本没有改变。

似乎在一两秒钟内得到了修复,让我认为它只是吐出缓存的位置。 但有时,在启动应用程序时,在停止更新之前,我会看到几秒钟的实际更新和实际数据。 另外,在将手机插回计算机时,我有时会看到一个更新。 当我外出时,甚至在系统设置菜单中清除应用程序的缓存数据并返回应用程序时也会发生这种情况。 会有一些更新,然后它在一个位置定居并拒绝进一步更新。

奇怪的是,两个小时前它工作得很好。 从那时起,我添加到代码中的唯一内容是 UI 元素。

我使用的设备是诺基亚X2,因此无法切换到较新的Google Play服务API。 在日志中,当我第一次获得LocationManager时,我看到"D/ContextImpl:BYDSafe:new BYDSafeLocationManager"。 谷歌搜索它绝对没有结果,所以我假设这是诺基亚专有的类。 如果这个类是我问题的原因,那么有什么方法可以迫使Android给我股票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();
    }
}

一看,你的代码看起来是正确的。我建议测试两件事。

  1. 在所有情况下注册侦听器,而不仅仅是在检查已启用的提供程序为肯定的情况下。这使您可以确定,无论设备上发生什么情况,您都会侦听更新(例如,用户可以在后台通过任何第三方应用程序启用提供程序)

  2. 尝试将 manager.requestLocationUpdates 中的时间参数也更改为 0 。我记得我也遇到了一些问题,0,0 值最终是最好的。

希望这有帮助

每当Activity extends时,您都必须在onCreate()方法中启动所有必需的组件。

在您的情况下,您已经启动了除LocationManager之外的所有TextView

只需在 onCreate() 方法中添加以下代码即可。

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

或者,您可以在onCreate()(如TextView)之外声明LocationManager,以防您需要将其部署到任何地方(等onResume内部)。

最新更新