Служба Android не обновляет местоположение
Мне нужно обновлять объединенное местоположение каждые 1 минуту и на каждом 5-метровом смещении (я знаю, что это плохо, но для проверки и показа в журнале), и я запускаю сервис нажатием кнопки. Как только кнопка нажата, я получаю местоположение в logcat, но только однажды. В соответствии с классом Service onLocationChanged должен вызываться каждые 1 минуту, но он никогда не вызывает снова, даже если мой GPS включается почти каждую минуту, а затем выключается через некоторое время, но все еще нет обновления местоположения в Logcat. Мне нужен класс обслуживания, чтобы сохранить местоположение обновления без влияния Пользовательский интерфейс или основной поток
Вот logcat, который показывает обновление местоположения только один раз
09-16 03:13:37.125 10419-10419/com.example.com.pro_working1 D/===Location Service===: Service onConnected Calling
09-16 03:13:37.125 10419-10419/com.example.com.pro_working1 D/===Location Service===: Start Location Update is Calling
09-16 03:13:38.315 10419-10419/com.example.com.pro_working1 D/===Location Service===: Service OnLocationChanged Calling
09-16 03:13:38.315 10419-10419/com.example.com.pro_working1 D/===Location Service===: Here is Updated Locations: Latitude 28.5XXXXX Longitude 77.2XXXXX
09-16 03:13:38.315 10419-10419/com.example.com.pro_working1 D/===Location Service===: Sending Location Starting Accuracy is: 37.5
Вот мой класс обслуживания
public class Location_Service_background extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
public static final String TAG = "===Location Service===";
GoogleApiClient apiClient;
Location mCurrentLocation;
LocationRequest locationRequest;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
GoogleApiSetup();
RequestLocationUpdates();
Log.d(TAG,"OnStartCommand Is Calling ");
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
throw new UnsupportedOperationException("Not yet implemented");
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
public void onDestroy() {
super.onDestroy();
if (apiClient.isConnected()){
Log.d(TAG,"Service On Destroy Calling and apiClient is Connected");
StopLocationUpdates();
apiClient.disconnect();
}
}
@Override
public void onLowMemory() {
super.onLowMemory();
}
@Override
public void onConnected(@Nullable Bundle bundle) {
Log.d(TAG,"Service onConnected Calling");
if (mCurrentLocation != null) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(apiClient);
}
else {
Log.d(TAG,"Start Location Update is Calling");
StartLocationUpdate();
}
}
@Override
public void onConnectionSuspended(int i) {
Log.d(TAG,"Service OnConnectionSuspended Calling");
apiClient.connect();
}
@Override
public void onLocationChanged(Location location) {
Log.d(TAG,"Service OnLocationChanged Calling");
mCurrentLocation=location;
Log.d(TAG,"Here is Updated Locations: Latitude "+mCurrentLocation.getLatitude()+"Longitude "+mCurrentLocation.getLongitude());
String Latitude= String.valueOf(mCurrentLocation.getLatitude());
String Longitude=String.valueOf(mCurrentLocation.getLongitude());
String Accuracy=String.valueOf(mCurrentLocation.getAccuracy());
Log.d(TAG,"Sending Location Starting"+" "+" Accuracy is: "+mCurrentLocation.getAccuracy());
}
@Override
public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
Log.d(TAG,"Connection Failed Called "+connectionResult);
}
private synchronized void GoogleApiSetup() {
apiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
apiClient.connect();
}
private void RequestLocationUpdates() {
locationRequest = new LocationRequest();
//1 Min = 60 seconds AND 1000 milliseconds in 1 second
locationRequest.setInterval(60 * 1000);//5 Min 300 x 1000=300000
locationRequest.setFastestInterval(60 * 1000);//2 Min
locationRequest.setSmallestDisplacement(5);
locationRequest.setMaxWaitTime(60*1000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
private void StopLocationUpdates() {
LocationServices.FusedLocationApi.removeLocationUpdates(apiClient, this);
}
private void StartLocationUpdate() {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
if (apiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(apiClient, locationRequest, this);
}
else {
Log.d(TAG,"GoogleApiClient is not connected yet.Please Try Again");
apiClient.connect();
}
}
}
3 ответа
Надеюсь, это поможет кому-то спасти разочарование по этому вопросу. Я использую FusedLocationAPI для запроса обновлений местоположения и GoogleApiClient. Я также делаю это из службы.
Вы не получаете никаких обновлений местоположения в свой временной интервал, потому что setSmallestDisplacement() имеет абсолютный приоритет над другими параметрами. Так что даже если у вас есть
locationRequestTimeInterval = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(1)
.setFastestInterval(1)
.setMaxWaitTime(1)
.setSmallestDisplacement(5);
это НИКОГДА не будет срабатывать до тех пор, пока не будет достигнут параметр smalllestDisplacement.
Решение этой проблемы - создать два отдельных запроса LocationRequest... один, который касается только расстояния, а другой - только времени, и использовать ваш единственный GoogleApiClient для создания 2 команд requestLocationUpdates, одну с помощью Time LocationRequest и другие с помощью Distance LocationRequest.
Итак, ваши 2 LocationRequests выглядят так:
locationRequestDistanceInterval = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setFastestInterval(0) // This MUST be set, otherwise no updates
.setSmallestDisplacement(LOCATION_REQUEST_MIN_DISTNACE);
locationRequestTimeInterval = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(PROVIDER_GPS_UPDATE_TIME_INTERVAL)
.setFastestInterval(PROVIDER_GPS_UPDATE_TIME_INTERVAL);
- обратите внимание, что значение setFastestInterval() ДОЛЖНО быть установлено в запросе расстояния, иначе запрос расстояния не будет запущен. Это не должно быть 0, но это поле должно быть установлено.
Затем в вашем GoogleApiClients onConnected() вы можете добавить два вызова requestLocationUpdates().
LocationServices.FusedLocationApi.requestLocationUpdates(mLocationClient, locationRequestDistanceInterval, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
// Handle your Distance based updates
});
LocationServices.FusedLocationApi.requestLocationUpdates(mLocationClient, locationRequestTimeInterval, new LocationListener() {
@Override
public void onLocationChanged(Location location) {
// Handle your Time based updates
}
});
Вы можете использовать одинаковые или отдельные LocationListeners для обработки ответов на каждый запрос. Надеюсь это поможет.
Предполагая, что вы фактически перемещаете устройство более чем на 5 метров между ожидаемыми обновлениями, я думаю, что может быть проблема с классом LocationRequest, где метод setSmallestDisplacement() просто не работает должным образом... или, по крайней мере, не работает работать как положено. (Я видел эти проблемы на других постах).
Вы всегда можете проверить расстояние самостоятельно, удалив setSmallestDisplacement(), и вместо этого выполните:
onLocationChanged(){
double distance = // [ calculate distance between current lat/long and previous lat/long ]
if (distance > 5 meters) {
// do your normal onLocationChanged() code here
}
}
Существует также возможность, что по какой-то причине FusedLocationProvider не может получить доступ к вашему GPS и вместо этого использует Wi-Fi или сотовую вышку... в этом случае 5 м слишком малы для указания расстояния. Ваши журналы говорят, что точность составляет 37,5 метра, так что это не кажется достаточно точным, чтобы можно было измерить 5 метров. Итак... может быть, у вас нет разрешения доступа FINE в вашем манифесте?
Также может ли быть проблема с неправильными разрешениями во время выполнения? Вы можете временно установить целевой SDK на 22, чтобы проверить это.
небольшая помощь, которая знает, что это можно использовать
int jarak = 10;
int interval = 5;
LocationRequest request = new LocationRequest();
request.setInterval(interval*1000); //update lokasi 10 detik
request.setFastestInterval(interval*1000); //dapat update dari aplikasi lain yg lebih cepat 10 detik
//request.setSmallestDisplacement(1); //diupdate jika berpindah 1 meter
request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
FusedLocationProviderClient client = LocationServices.getFusedLocationProviderClient(this);
int permission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
if(permission == PackageManager.PERMISSION_GRANTED) {
client.requestLocationUpdates(request, new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
List<Location> locationList = locationResult.getLocations();
if (locationList.size() > 0) {
Location locationCurrent = locationList.get(locationList.size() - 1);
double latitude = locationCurrent.getLatitude();
double longitude = locationCurrent.getLongitude();
double lastlatitude = Double.parseDouble(prefs.getString("lastlatitude","0"));
double lastlongitude = Double.parseDouble(prefs.getString("lastlongitude","0"));
Location startPoint=new Location("LokasiA");
startPoint.setLatitude(latitude);
startPoint.setLongitude(longitude);
Location endPoint = new Location("LokasiB");
endPoint.setLatitude(lastlatitude);
endPoint.setLongitude(lastlongitude);
double distance = startPoint.distanceTo(endPoint);
Log.d(tag, "location update last " + endPoint);
if(distance > jarak) {
Log.d(tag, "location update new" + startPoint);
Log.d(tag, "location dest " + distance);
SharedPreferences.Editor editor = prefs.edit();
editor.putString("lastlatitude", String.valueOf(latitude));
editor.putString("lastlongitude", String.valueOf(longitude));
editor.apply();
Log.i("getLatitude:",String.valueOf(locationCurrent.getLatitude()) );
Log.i("getLongitude:",String.valueOf(locationCurrent.getLongitude()) );
}
}
}
},null);
}