У меня есть LocationService, который начинается onResume()
из MainActivity и останавливает onDestroy()
.Невозможно получить текущее местоположение LocationListener
@Override
protected void onResume() {
super.onResume();
//Start the service using alaram manager
//If its not running currently
if (isLocationServiceRunning(this)) {
am = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(this, LocationService.class);
pi = PendingIntent.getService(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
am.cancel(pi);
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime(), 1 * 60 * 1000, pi);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (isLocationServiceRunning(this)) {
stopService(new Intent(this, LocationService.class));
if (am != null && pi != null) {
am.cancel(pi);
}
}
}
LocationService.java
public class LocationService extends Service implements LocationListener {
public static double curLat = 0.0;
public static double curLng = 0.0;
private LocationManager mgr;
private String best;
private Location location;
private Location currentBestLocation;
private static final int TWO_MINUTES = 1000 * 60 * 2;
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
mgr = (LocationManager) getSystemService(LOCATION_SERVICE);
boolean gps_enabled = mgr
.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (gps_enabled) {
// If GPS is enabled, set criteria as ACCURACY_FINE
// and get the best provider(which usually will be GPS_PROVIDER)
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
best = mgr.getBestProvider(criteria, true);
// getLastKnownLocation so that user don't need to wait
location = mgr.getLastKnownLocation(best);
if (location == null) {
// request for a single update, and try again.
// Later will request for updates every 10 mins
mgr.requestSingleUpdate(criteria, this, null);
location = mgr
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
}
if (location != null) {
// If the GPS gives a location, update curLat and curLng
dumpLocation(location);
} else {
// If the location is still null, go for NETWORK_PROVIDER
best = LocationManager.NETWORK_PROVIDER;
location = mgr.getLastKnownLocation(best);
if (location != null) {
// If the NETWORK gives a location, update curLat and curLng
dumpLocation(location);
}
}
// Register the Location Manager for updates, with both the
// providers
// Since GPS updates are expensive, we ask update every 10 mins and
// unregister updates if GPS is disabled in onProviderDisabled
// callback
mgr.requestLocationUpdates(LocationManager.GPS_PROVIDER,
10 * 60 * 1000, 50, this);
// NETWORK_PROVIDER updates every 20 secs
mgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
20 * 1000, 0, this);
return START_NOT_STICKY;
} else {
// If GPS is disables, go with NETWORK_PROVIDER
best = LocationManager.NETWORK_PROVIDER;
location = mgr.getLastKnownLocation(best);
if (location != null) {
dumpLocation(location);
}
// Register NETWORK_PROVIDER for updates every 20 secs
mgr.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,
20 * 1000, 0, this);
return START_NOT_STICKY;
}
}
private void dumpLocation(Location l) {
// Called to update the curLat and curLng.
currentBestLocation = l;
SimpleDateFormat s = new SimpleDateFormat("dd/MM/yyyy:hh:mm:ss",
Locale.ENGLISH);
String format = s.format(l.getTime());
try {
Geocoder coder = new Geocoder(this);
List<Address> address;
Address location = null;
address = coder.getFromLocation(l.getLatitude(), l.getLongitude(),
1);
location = address.get(0);
} catch (Exception e) {
Log.e("Exception while getting address", e.getMessage() + "");
}
curLat = l.getLatitude();
curLng = l.getLongitude();
}
@Override
public void onLocationChanged(Location location) {
// called when location is changed, since we registered Location
// Providers
// for updates
if (isBetterLocation(location, currentBestLocation)) {
dumpLocation(location);
} else {
Log.d("Not a Better Location", "Ignore");
}
}
@Override
public void onProviderDisabled(String provider) {
// Check if best(the currently being used provider) is not null
if (best != null) {
// if best and disabled provider are same, the remove updates
if ((provider.equalsIgnoreCase(LocationManager.GPS_PROVIDER) && best
.equals(LocationManager.GPS_PROVIDER))
|| provider
.equalsIgnoreCase(LocationManager.NETWORK_PROVIDER)
&& best.equals(LocationManager.NETWORK_PROVIDER)) {
if (mgr != null) {
mgr.removeUpdates(this);
}
}
}
}
@Override
public void onProviderEnabled(String provider) {
// This will be taken care in the onStartCommand where if gps_enabled
// case is used.
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
// No need to care about, because any thing like OUT_OF_SERVICE occurs,
// location being fetched will be null and such cases are handled above.
if ((provider.equals(LocationManager.GPS_PROVIDER))
&& (LocationProvider.OUT_OF_SERVICE == status)) {
if (mgr != null) {
mgr.removeUpdates(this);
}
}
}
@Override
public void onDestroy() {
super.onDestroy();
// triggered when we call stopService(LocationService);
// which is done in onDestroy of MainActivity
// Because LocationService must be stopped
// when application is closed to avoid data usage
if (mgr != null) {
mgr.removeUpdates(this);
}
}
protected boolean isBetterLocation(Location location,
Location currentBestLocation) {
if (currentBestLocation == null) {
// A new location is always better than no location
return true;
}
// Check whether the new location fix is newer or older
long timeDelta = location.getTime() - currentBestLocation.getTime();
boolean isSignificantlyNewer = timeDelta > TWO_MINUTES;
boolean isSignificantlyOlder = timeDelta < -TWO_MINUTES;
boolean isNewer = timeDelta > 0;
// If it's been more than two minutes since the current location, use
// the new location
// because the user has likely moved
if (isSignificantlyNewer) {
return true;
// If the new location is more than two minutes older, it must be
// worse
} else if (isSignificantlyOlder) {
return false;
}
// Check whether the new location fix is more or less accurate
int accuracyDelta = (int) (location.getAccuracy() - currentBestLocation
.getAccuracy());
boolean isLessAccurate = accuracyDelta > 0;
boolean isMoreAccurate = accuracyDelta < 0;
boolean isSignificantlyLessAccurate = accuracyDelta > 200;
// Check if the old and new location are from the same provider
boolean isFromSameProvider = isSameProvider(location.getProvider(),
currentBestLocation.getProvider());
// Not significantly newer or older, so check for Accuracy
if (isMoreAccurate) {
// If more accurate return true
return true;
} else if (isNewer && !isLessAccurate) {
// Same accuracy but newer, return true
return true;
} else if (isNewer && !isSignificantlyLessAccurate
&& isFromSameProvider) {
// Accuracy is less (not much though) but is new, so if from same
// provider return true
return true;
}
return false;
}
// Checks whether two providers are the same
private boolean isSameProvider(String provider1, String provider2) {
if (provider1 == null) {
return provider2 == null;
}
return provider1.equals(provider2);
}
}
служба, безусловно, начинается и останавливается, как и ожидалось, и я могу видеть расположение деталей в журнале, которые хорошо.
Проблемы, если когда я перехожу к полному другому месту (300 миль), то curLat и curLng значения до сих пор остается, как и старые, когда я открываю приложение.
Это потому, что я не запускаю службу, когда устройство находится в движении (потому что мое приложение не работает)?
Потому что, когда я открываю какое-то другое приложение, например FourSquare (которое получает правильное местоположение), а затем снова открывает мое приложение, оно показывает правильное местоположение.
Что еще нужно сделать, чтобы правильно обновить местоположение.
Почему вы не начинаете свою службу в oncraete, а не в onresume , когда приложение не находится в стеке ОС, оно будет инициализировано, и 1-й вызванный метод будет создан после этого, если приложение будет отдыхать на заднем плане при повторной обработке onresume будет так что попробуйте его в oncreate, а просто в onresume –
Я думаю, islocationservice возвращает false, также попробуйте с возвратом Service.START_STICKY; –
@UsmanKurd 'onCreate()' в конечном итоге вызывает 'onResume()'. Более того, у меня нет проблем при запуске службы. Проблема заключается в том, что служба не обновляет местоположение. –