IntentService STICKY and sensor monitoring stops when it shouldn't in Android
-
14-11-2019 - |
문제
In my application onCreate I check some conditions and then I start an Activity like this:
Intent startIntent = new Intent(getApplicationContext(), EnableLocationProviderActivity.class);
startIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getApplicationContext().startActivity(startIntent);
From that Activity I start an IntentService which register some listeners for the sensors, it is started as STICKY meaning it should be stopped explicitly. That IntentService monitors the sensors.
My problem is that when I come back to the first Activity the sensors are not sensing anymore (I put a Log.v in onSensorChanged (the start showing data, and then it stops).
Why it could be that it stops if I didn't stopped it explicitly? Moreover I see sometimes OnDestroy of the IntentService being called, but again, How can it being called if it's STICKY and I didn't call stopself() and didn't stopped in any other way?
Thanks! Guillermo.
EDIT
This is the code of the IntentService (which should be running all the time, despite if the cellphone goes to sleep or the home button is pressed (I know about battery and everything else, the user will be warned about this and will have the oportunity to close the application when he wants.
The service is called from MainActivity like this:
Intent startIntent = new Intent(GdpTesisApplication.getInstance().getApplicationContext(), SensingService.class);
startService(startIntent);
And the service code is this one:
public class SensingService extends IntentService implements SensorEventListener {
private float[] mAccelerationValues;
private SensorManager mSensorManager = null;
String sensorType = "";
public SensingService(String name) {
super(name);
setIntentRedelivery(true);
}
public SensingService() {
super("SensingService");
setIntentRedelivery(true);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.v(ApplicationName,"SensingService.onStartCommand");
super.onStartCommand(intent, flags, startId); // If this is not written then onHandleIntent is not called.
return START_STICKY;
}
@Override
public void onCreate() {
super.onCreate();
Log.v(ApplicationName, "SensingService.onCreate");
initialize();
}
private void initialize() {
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); // This must be in onCreate since it needs the Context to be created.
mAccelerationValues = new float[3];
Log.v(ApplicationName, "Opening Location Service from Sensing Service");
LocationService myLocation = new LocationService();
myLocation.getLocation(this, locationResult);
}
@Override
public void onDestroy() {
Log.v(ApplicationName, "SensingService.onDestroy");
super.onDestroy();
if (mSensorManager != null) {
mSensorManager.unregisterListener(this);
}
}
@Override
protected void onHandleIntent(Intent intent) {
Log.v(ApplicationName, "SensingService.onHandleIntent");
if (mSensorManager != null) {
registerListeners();
}
}
public LocationResult locationResult = new LocationResult() {
@Override
public void gotLocation(final Location location) {
if (location != null) {
Log.v(ApplicationName, "Location != null : (" + location.getLatitude() + "," + location.getLongitude() + ")");
} else {
Log.v(ApplicationName, "Location == null : (0,0)");
}
}
};
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent currentEvent) {
if (currentEvent.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) {
return;
}
synchronized (this) {
float[] accelVals = null;
float totalForce = 0.0f;
int sensor = currentEvent.sensor.getType();
System.arraycopy(currentEvent.values, 0, mAccelerationValues, 0, 3); // We use System.arraycopy because of this:
switch (sensor) {
case Sensor.TYPE_ACCELEROMETER:
sensorType = "Accelerometer";
totalForce = SensorsHelpers.getTotalForceInGs(mAccelerationValues);
break;
case Sensor.TYPE_LINEAR_ACCELERATION:
sensorType = "LinearAcceleration";
totalForce = SensorsHelpers.getTotalForceInGs(mAccelerationValues) + 1;
break;
case Sensor.TYPE_GRAVITY:
totalForce = SensorsHelpers.getTotalForceInGs(mAccelerationValues);
sensorType = "Gravity";
break;
}
Log.v(ApplicationName,DateHelper.GetUTCdatetimeFromDate(new Date()) + " - from sensingService");
}
}
private void registerListeners() {
Log.v(ApplicationName, "Registering sensors listeners");
mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION), SensorManager.SENSOR_DELAY_UI);
mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY),SensorManager.SENSOR_DELAY_UI);
mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_UI);
}
}
UPDATE 2
Now I've added this on the method onCreate:
int NOTIFICATION_ID = 1;
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 1, intent, 0);
Notification notification = new Notification(R.drawable.ic_dialog_info, "Running in the Foregound", System.currentTimeMillis());
notification.setLatestEventInfo(this, "Title", "Text", pi);
notification.flags = notification.flags | Notification.FLAG_ONGOING_EVENT;
startForeground(NOTIFICATION_ID, notification);
to start it as startForground, but it puts the icon in the notification bar, then onDestroy is called in the service and the notification icon goes away.
I'm desperate now! Please help in this one!
Thanks! Guillermo.
해결책 2
Ok, I saw a reply to another question, and there is a guy who said it's a bug in Android, I followed his suggestion to move the code to onCreate instead of onHandleIntent and it worked! So, if no one show to me it's a problem with my code, for me it will be a bug. Thanks!
다른 팁
As per IntentService documentation:
the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work
Also, according to the same documentation, you're not supposed to override onStartCommand()
and onDestroy()
in your IntentService
, I assume because it implements its own special behavior as specified above. Maybe you need to extend Service
instead of IntentService
.