CoderNinja
CoderNinja

Reputation: 1

Android Wear Os - How to ensure continous/uninterrpted sensor data collection in the background?

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

Answers (0)

Related Questions