Reputation: 1
I recently developed a wear app to collect sensor data (accelerometer) from my Galaxy watch 4 smartwatch. The idea is, once the start button is pressed the data collection will start and will continue even if the app goes to background at the mentioned fequency say 50Hz. Then it will stop only when the stop button is pressed.
I used foreground service to ensure that data collection keeps going in any situation. Please consider that in my case, I cant even miss data of a single second. However, even with foreground service, data collection is being interrupted very frequently. Only with WAKE_LOCK, I am getting the continous data collection. But I want it to do in the background. Any idea? I am attaching the code for the froeground service. The mainActivity just invokes it on a button click.
public class SensorDataService extends Service implements SensorEventListener {
private SensorManager sensorManager;
private Sensor accelerometer;
private boolean isRecording; // Flag for recording state
private File gpxfile;
String DATA = "";
String dateCurrent;
String ax, ay, az, gx, gy, gz, mx, my, mz;
private FileWriter writer;
private static final int NOTIFICATION_ID = 1;
private static final String CHANNEL_ID = "SensorServiceChannel";
private Context context;
private final IBinder binder = new LocalBinder();
public class LocalBinder extends Binder {
SensorDataService getService() {
return SensorDataService.this;
}
}
@Override
public void onCreate() {
super.onCreate();
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent != null && intent.getAction() != null) {
if (intent.getAction().equals("START_COLLECTION")) {
startRecording();
} else if (intent.getAction().equals("STOP_COLLECTION")) {
stopRecording();
}
}
return START_STICKY; // Flag to restart the service if killed
}
private void createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChannel = new NotificationChannel(
CHANNEL_ID,
"Sensor Service Channel",
NotificationManager.IMPORTANCE_DEFAULT
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChannel);
}
}
private Notification createNotification() {
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this,
0, notificationIntent, 0);
return new NotificationCompat.Builder(this, CHANNEL_ID)
.setContentTitle("Sensor Service")
.setContentText("Collecting sensor data")
.setSmallIcon(R.mipmap.ic_launcher)
.setContentIntent(pendingIntent)
.build();
}
@Override
public IBinder onBind(Intent intent) {
return binder;
}
public void processSensorData(SensorEvent event) {
// Process sensor data (e.g., log data or perform actions)
if (isRecording) {
long date = System.currentTimeMillis();
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy, HH:mm:ss");
dateCurrent = sdf.format(date);
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
ax = String.valueOf(event.values[0]);
ay = String.valueOf(event.values[1]);
az = String.valueOf(event.values[2]);
}
DATA = dateCurrent + "," + ax + "," + ay + "," + az + "\n";
try {
writer.write(DATA); // Write data to file
writer.flush(); // Ensure data is written to disk immediately
} catch (IOException e) {
e.printStackTrace();
// Handle errors here (display a toast or log a message)
}
}
}
public void startRecording() {
if (sensorManager != null) {
// Create notification channel (required for Android Oreo and above)
this.writer = MainActivity.getWriter();
this.gpxfile = MainActivity.getFile();
context = this;
createNotificationChannel();
// Create notification for foreground service
Notification notification = createNotification();
// Start foreground service with the given notification
startForeground(NOTIFICATION_ID, notification);
sensorManager.registerListener(this, accelerometer, 40000);
isRecording = true;
Log.d("Service", "Recording started");
}
}
public void stopRecording() {
if (sensorManager != null) {
stopForeground(true);
sensorManager.unregisterListener(this);
isRecording = false;
try {
writer.close(); // Close the file
Toast.makeText(context, "File saved", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
// Handle errors here (display a toast or log a message)
}
}
}
@Override
public void onSensorChanged(SensorEvent event) {
if (isRecording) {
processSensorData(event);
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Handle sensor accuracy changes (optional)
}
@Override
public void onDestroy() {
super.onDestroy();
sensorManager.unregisterListener(this);
Log.d("Destroy", "...................");
}
}
Upvotes: 0
Views: 143