如何在 getAccuracy() 低于 100 时停止处理程序

How to stop handler when getAccuracy() is lower than 100

您好,我正在创建一个 android 地图应用程序,它将获取用户位置,但是当用户打开他们的地图时,有时位置不准确,并且会慢慢查明您的位置。

这个我试过了。但它仍然调用处理程序并且 TOASTS 不会停止。

private LocationManager locationManager;

private Handler handler = new Handler();

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

locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

 locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000, 0, new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {

        }

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

        }

        @Override
        public void onProviderEnabled(String provider) {
              handler.postDelayed(runnable,3000);
        }

        @Override
        public void onProviderDisabled(String provider) {

            handler.removeCallbacks(runnable);
        }
    });

      private Runnable runnable = new Runnable() {
    @Override
    public void run() {

      getCurrentLocation();

        Toast.makeText(mapsPage.this, "GETTING LOCATION", Toast.LENGTH_SHORT).show();

        handler.postDelayed(this, 3000);
    }
};

   private void getCurrentLocation() {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return;
    }
    Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
    if (location != null) {
        longitude = location.getLongitude();
        latitude = location.getLatitude();

        moveMap();

        Integer loc = Math.round(location.getAccuracy());
        textings.setText(Integer.toString(loc));

        if(loc <= 100)
    {
        handler.removeCallbacks(runnable);

        Toast.makeText(mapsPage.this, "HANDLER STOPPED", Toast.LENGTH_SHORT).show();
    }

    }
}

//Function to move the map
private void moveMap() {

    LatLng latLng = new LatLng(latitude, longitude);

    mMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
    mMap.animateCamera(CameraUpdateFactory.zoomTo(17));
    mMap.addMarker(new MarkerOptions().position(latLng).draggable(false));

}

我添加了一个处理程序,它将 运行 每 5 秒检查一次用户位置,当 getAccuracy 数据等于或小于 100 时它将停止。我该怎么做?

getCurrentLocation 可能会调用 handler.removeCallbacks(runnable);,但是 运行nable 总是会在之后立即调用 handler.postDelayed(this, 3000);

为了解决这个问题,Runnable 必须有一些条件来检查它是否应该再次 post 自己。

一个解决方案是使 getCurrentLocation return 成为一个布尔值,指示它是否成功(足够):

private boolean getCurrentLocation() {
    if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && 
            ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
        return false;
    }
    Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
    if (location != null) {
        longitude = location.getLongitude();
        latitude = location.getLatitude();

        moveMap();

        Integer loc = Math.round(location.getAccuracy());
        textings.setText(Integer.toString(loc));

        if(loc <= 100) {
            handler.removeCallbacks(runnable);
            Toast.makeText(mapsPage.this, "HANDLER STOPPED", Toast.LENGTH_SHORT).show();
            return true;
        }
    }
    return false;
}

然后在你的 Runnable 检查你是否需要另一个 运行:

@Override
public void run() {
    if(!getCurrentLocation()) {
        handler.postDelayed(this, 3000);
    }
}

但是,综上所述,您应该只检查 LocationListener 的 onLocationChanged 中的 Location,如果该位置足够准确,则执行一些操作。那么你根本不需要Runnable。

您绝对应该接受 RobCo 的答案是正确的,因为它直接解决了您的问题并且还提供了额外的关键见解(即您根本不需要 Runnable)。

但是,我很好奇 RobCo 的方法会是什么样子,所以我创建了一种可能的实现方式。

事实证明,如果我们避免使用 Runnable 并改为依赖 Google 的回调,我们可以仅使用较新的位置提供程序 API (LocatonServices.FusedLocationApi) .旧的 LocationManager API 可以被淘汰。

因此,在此实现中,我让 Google 位置服务触发回调 if/when 位置更改(而不是使用来自客户端的定期轮询):

public class MainActivity extends AppCompatActivity implements
        ActivityCompat.OnRequestPermissionsResultCallback, GoogleApiClient.OnConnectionFailedListener,
        GoogleApiClient.ConnectionCallbacks,
        com.google.android.gms.location.LocationListener {

    private static final String TAG = MainActivity.class.getSimpleName();

    private static final int PERMISSION_REQUEST_CODE = 10001;
    public static final int LOCATION_UPDATE_INTERVAL = 5000; // milliseconds
    private GoogleApiClient googleApiClient;

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

        googleApiClient = new GoogleApiClient.Builder(this, this, this)
                .enableAutoManage(this, this)
                .addApi(LocationServices.API)
                .build();

        googleApiClient.connect();
    }

    private void requestPermission() {
        ActivityCompat.requestPermissions(this,
                new String[]{ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_CODE);
    }

    private void initLocationServices() {
        try {
            // make initial, synchronous request for current location
            Location location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
            if (location != null) {
                moveMap(location);
            }

            // request future location updates which will come in as callbacks later, when available
            LocationRequest locationRequest = new LocationRequest();
            locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
            locationRequest.setInterval(LOCATION_UPDATE_INTERVAL);
            LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
        } catch (SecurityException se) {
            Log.w(TAG, "App does not have sufficient permission to request location. " +
                    "Requesting permission now...");
            requestPermission();
        }
    }

    private void moveMap(Location location) {
        Log.v(TAG, "moveMap");

        // TODO: actual map moving code goes here
    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.e(TAG, "Connection failed:" + connectionResult.getErrorMessage());
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == PERMISSION_REQUEST_CODE && grantResults[0] == PERMISSION_GRANTED && grantResults[1] == PERMISSION_GRANTED) {
            Log.v(TAG, "User granted permission. Will request current location.");
            initLocationServices();
        } else {
            Log.w(TAG, "User did not grant permission. Cannot request location. Cannot proceed.");
        }
    }

    @Override
    public void onLocationChanged(Location newLocation) {
        Log.v(TAG, "onLocationChanged:" + newLocation.toString());
        moveMap(newLocation);
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        if ((ActivityCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PERMISSION_GRANTED)
                && (ActivityCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) == PERMISSION_GRANTED)) {
            initLocationServices();
        } else {
            Log.w(TAG, "onCreate: requesting sufficient permission from user");
            requestPermission();
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.v(TAG, "onConnectionSuspended");
    }
}

这个特定实现的一个缺点是 MainActivity 实现了几个接口,这增加了一些混乱(这些方法在这里做什么?等)

不知道。也许它有用。无论如何,祝您的应用程序好运。