I am trying to read sensor data from my phone. I have started a service, which created a HandlerThread to collect sensor data. The thread registers the sensor for a short while and unregisters it. When I stop the service, however, the thread keeps running, and I see print statements working. How do I stop this? This is my service code.
package com.example.myapplication;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaPlayer;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
@RequiresApi(api = Build.VERSION_CODES.O)
public class SenseService extends Service {
private Looper serviceLooper;
private ServiceHandler serviceHandler;
private Context context;
private HandlerThread thread;
private final class ServiceHandler extends Handler implements SensorEventListener {
private SensorManager sensorManager;
private Sensor mLight;
private LocalDateTime currTime;
private String senseTime;
private String FILENAME="sensordata";
private FileOutputStream fos;
public ServiceHandler(Looper looper){
super(looper);
}
@Override
public void handleMessage(Message msg) {
try {
currTime = java.time.LocalDateTime.now();
String newFileName = currTime.toString()+FILENAME+".csv";
fos = openFileOutput(newFileName, Context.MODE_APPEND);
} catch (FileNotFoundException e) {
System.out.println("did not open file");
e.printStackTrace();
}
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
try {
do {
sensorManager.registerListener(this, mLight, 10000000);
Thread.sleep(2000);
System.out.println("thread sleeping");
sensorManager.unregisterListener(this);
Thread.sleep(5000);
} while (true);
}catch (InterruptedException e) {
e.printStackTrace();
} {
}
stopSelf(msg.arg1);
}
@Override
public void onSensorChanged(SensorEvent event) {
float lux = event.values[0];
String val = Float.toString(lux);
senseTime = java.time.LocalDateTime.now().toString();
System.out.println(Float.toString(lux));
val = senseTime+","+val+"\n";
try {
fos.write(val.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
}
@Override
public void onCreate(){
thread = new HandlerThread("ServiceStartArguments");
thread.start();
serviceLooper = thread.getLooper();
serviceHandler = new ServiceHandler(serviceLooper);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Toast.makeText(this, "service starting", Toast.LENGTH_SHORT).show();
Message msg = serviceHandler.obtainMessage();
msg.arg1 = startId;
serviceHandler.sendMessage(msg);
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "service done", Toast.LENGTH_SHORT).show();
System.out.println("Stopping service");
thread.quitSafely();
stopSelf();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
You use large amount of delays to put the threads into the sleep state. Also you are using an infinite loop without any condition to break the loop here:
do {
sensorManager.registerListener(this, mLight, 10000000);
Thread.sleep(2000);
System.out.println("thread sleeping");
sensorManager.unregisterListener(this);
Thread.sleep(5000);
} while (true); // Define a condition or interrupt the thread
In this condition the handlerthread's looper will not quit until the all messages in the queue are handled. But with your implementation it will always be occupied with the first message due to that infinite loop.
You must either somehow interrupt the threads or put a condition to that infinite loop if you want that all messages be handled when you quit safely from handler thread.
Or if no further processing needed when the service is stopped, you can try the quit()
method instead of quitSafely()
.