Android Wear OS - 如何确保后台连续/不间断的传感器数据收集?

问题描述 投票:0回答:1

我最近开发了一款穿戴应用程序,用于从我的 Galaxy watch 4 智能手表收集传感器数据(加速度计)。这个想法是,一旦按下开始按钮,数据收集就会开始,即使应用程序以上述频率(例如 50Hz)进入后台,数据收集也会继续。然后只有按下停止按钮才会停止。

我使用前台服务来确保数据收集在任何情况下都能持续进行。请考虑一下,就我而言,我什至不能错过一秒钟的数据。然而,即使有前台服务,数据收集也经常被中断。只有使用 WAKE_LOCK,我才能获得连续的数据收集。但我希望它在后台进行。有什么想法吗?我附上前台服务的代码。 mainActivity 只需单击按钮即可调用它。

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", "...................");

    }
}
wear-os android-sensors foreground-service
1个回答
0
投票

您最终找到解决方案了吗?我也有同样的问题

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.