如何在 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 实现了几个接口,这增加了一些混乱(这些方法在这里做什么?等)
不知道。也许它有用。无论如何,祝您的应用程序好运。
您好,我正在创建一个 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 实现了几个接口,这增加了一些混乱(这些方法在这里做什么?等)
不知道。也许它有用。无论如何,祝您的应用程序好运。