Reputation: 3945
I followed the basic android documentation to implement a Service
, triggered repeatedly by AlarmManager
every 40 seconds. Inside the service I register GPS listener, and if I don't get fix within 30 seconds I call stopSelf()
, this in order to avoid 2 "concurrent" services running together. However if I do have fix within less then 30 seconds, I perform some logic and after I done I call stopSelf()
- Assuming it all will take less then 40 seconds so again I have no issues of "concurrent" services running...
When I log print the order of execution of various Service methods it doesn't make any sense:
onCreate
is called only once, while onStartCommand
is triggered every 40 seconds.Activity
also registered and do have GPS fix interfere here? (I testing outdoors and the activity does get fix)This is my implementation - Pretty much straightforward googles android documentation:
public class DirectionService extends Service implements Constants {
private LocationManager mLocationManager;
private LocationListener mLocationListeners;
private Context mContext;
private Looper mServiceLooper;
private ServiceHandler mServiceHandler;
@Override
public IBinder onBind(Intent arg0) {
return null; //not binding
}
@Override
public void onCreate() {
HandlerThread thread = new HandlerThread("ServiceStartArguments", Process.THREAD_PRIORITY_BACKGROUND);
thread.start();
mServiceLooper = thread.getLooper();
mServiceHandler = new ServiceHandler(mServiceLooper);
mContext = getApplicationContext();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
//For each start request, send a message to start a job and deliver the start ID so we know which request we're stopping when we finish the job
Message msg = mServiceHandler.obtainMessage();
msg.arg1 = startId;
mServiceHandler.sendMessage(msg);
return START_STICKY;
}
//Handler that receives messages from the thread
private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}
/**
* The real work done after we have (first) fixed location and from there we stop the service.
* Therefore we pass the start id.
*/
@Override
public void handleMessage(final Message msg) {
if (mLocationManager == null) {
mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
mLocationListeners = new LocationListener(msg.arg1);
}
try {
mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, GPS_UPDATE_TIME, 0, mLocationListeners);
mLocationManager.addGpsStatusListener(mGPSStatusListener);
} catch (Exception e) {
stopSelf(msg.arg1);
}
//Start timer for GPS to get fix location. Else we might have new concurrent instance of service
new CountDownTimer(30000, 15000) {
public void onTick(long millisUntilFinished) {}
public void onFinish() {
stopSelf(msg.arg1);
}
}.start();
}
}
GpsStatus.Listener mGPSStatusListener = new GpsStatus.Listener() {
public void onGpsStatusChanged(int event) {
switch (event)
{
case GpsStatus.GPS_EVENT_FIRST_FIX:
if (ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
|| ContextCompat.checkSelfPermission(mContext, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (mLocationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER) != null) {
isGpsFixed = true;
}
}
break;
default:
break;
}
}
};
private class LocationListener implements android.location.LocationListener {
private int startId;
public LocationListener(int startId) {
this.startId = startId;
}
@Override
public void onLocationChanged(Location location) {
if (isGpsFixed == true && location.getLongitude() != 0.0 && location.getLatitude() != 0.0 && isAlreadySentToCheck == false) {
isAlreadySentToCheck = true;
startLogic(startId);
}
}
@Override
public void onProviderDisabled(String provider) {}
@Override
public void onProviderEnabled(String provider) {}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {}
}
private void startLogic(final int startId) {
//...
stopSelf(startId);
}
@Override
public void onDestroy() {
super.onDestroy();
if (mLocationManager != null) {
try {
mLocationManager.removeUpdates(mLocationListeners);
} catch (Exception ex) {}
}
}
Upvotes: 0
Views: 1090
Reputation: 2088
your service running many time because of start_sticky
if your service is killed by Android due to low memory, and Android clears some memory, then...
STICKY: ...Android will restart your service, because that particular flag is set.
NOT_STICKY: ...Android will not care about starting again, because the flag tells Android it shouldn't bother.
REDELIVER_INTENT: ...Android will restart the service AND redeliver the same intent to onStartCommand() of the service, because, again, of the flag.
suggest to your start_not_sticky
Upvotes: 2