服务中的Android传感器数据采集与计时器不一致

服务中的Android传感器数据采集与计时器不一致,android,service,timer,sensors,file-writing,Android,Service,Timer,Sensors,File Writing,因此,在我的Android传感器应用程序中,我有一个服务(前台),它以不同的流程连续运行,并记录不同传感器的数据(加速计、磁强计、GPS)。我使用了一个周期为100毫秒的计时器来获取和写入不同传感器的各种CSV文件中的数据。问题是数据记录不一致,即计时器工作不正常或有问题。它跳过一些时间间隔,比如几毫秒,有时甚至几秒钟,而它应该每秒记录十个样本。我已经为传感器定义了自定义类,它们工作正常 以下是我的服务代码: package com.example.ark.ark.Services; impo

因此,在我的Android传感器应用程序中,我有一个服务(前台),它以不同的流程连续运行,并记录不同传感器的数据(加速计、磁强计、GPS)。我使用了一个周期为100毫秒的计时器来获取和写入不同传感器的各种CSV文件中的数据。问题是数据记录不一致,即计时器工作不正常或有问题。它跳过一些时间间隔,比如几毫秒,有时甚至几秒钟,而它应该每秒记录十个样本。我已经为传感器定义了自定义类,它们工作正常

以下是我的服务代码:

package com.example.ark.ark.Services;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;

import java.text.SimpleDateFormat;

import android.os.Build;
import android.os.Environment;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.support.v7.app.NotificationCompat;

import com.example.ark.ark.Constants;
import com.example.ark.ark.R;
import com.example.ark.ark.Sensors.Accelerometer;
import com.example.ark.ark.Sensors.Gps;
import com.example.ark.ark.Sensors.Magnetometer;
import com.example.ark.ark.Sensors.Rotation;
import com.example.ark.ark.activity.MainActivity;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

import static com.example.ark.ark.Constants.*;

/**
 * Created by ark on 12/8/17.
 */

@RequiresApi(api = Build.VERSION_CODES.N)
public class DataRecording extends Service {
    private Magnetometer magnetometer;
    private Accelerometer accelerometer;
    private Gps gps;
    private Rotation rot;
    private Timer myTimer, gpsTimer;
    //frequency variables
    private int acc_mag_freq = 100;
    private int gps_freq = 2000;

    SimpleDateFormat time = new SimpleDateFormat(TIMESTAMP_FORMAT);
    SimpleDateFormat time1 = new SimpleDateFormat("dd-MM-yyyy_HH:mm:ss");

    //Declaring file variables
    private File sdDirectory = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + DIRECTORY);
    File accDirectory = new File(sdDirectory + Constants.DIRECTORY_ACC);
    File magDirectory = new File(sdDirectory + Constants.DIRECTORY_MAG);
    File gpsDirectory = new File(sdDirectory + Constants.DIRECTORY_GPS);
    File rotationDirectory = new File(sdDirectory + Constants.DIRECTORY_ROTATION);
    private File datafile_Rot;
    private File dataFile_Acc;
    private File dataFile_Mag;
    private File dataFile_Gps;
    private FileOutputStream dataOutputStream_Acc, dataOutputStream_Mag, dataOutputStream_Gps, dataOutputStream_Rot;

    private StringBuilder data_Acc = new StringBuilder();
    private StringBuilder data_Mag = new StringBuilder();
    private StringBuilder data_Gps = new StringBuilder();
    private StringBuilder data_Rot = new StringBuilder();
    private String mode = new String();
    private String acc_name, mag_name, rot_name, gps_name, user = "";

    @Override
    public void onCreate() {
        Intent notify = new Intent(this, MainActivity.class);
        PendingIntent pendingintent = PendingIntent.getActivity(this, 0, notify, 0);

        Notification notification = new NotificationCompat.Builder(this)
                .setSmallIcon(R.mipmap.icon_1_round)
                .setContentTitle("Mobility")
                .setContentText("Recording Data")
                .setContentIntent(pendingintent).build();

        startForeground(1337, notification);
        //Creating objects of the different sensor's class
        magnetometer = new Magnetometer(this);
        accelerometer = new Accelerometer(this);
        gps = new Gps(this);
        rot = new Rotation(this);

        data_Gps.append("\n");
        data_Acc.append("\n");
        if (magnetometer.isMagAvailable()) {
            data_Rot.append("\n");
            data_Mag.append("\n");
        }


        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        super.onStartCommand(intent, flags, startId);

        if (intent != null && intent.getExtras() != null) {
            user = intent.getExtras().getString("username");
            String t = intent.getExtras().getString("acc_mag_freq");
            String r = intent.getExtras().getString("gps_freq");
            mode = intent.getExtras().getString("mode");
            acc_mag_freq = Integer.parseInt(t);
            gps_freq = Integer.parseInt(r);
        }

        //Creating variables for file names
        acc_name = user + "_" + time1.format(new Date()) + "_" + Constants.DATA_FILE_NAME_ACC;
        gps_name = user + "_" + time1.format(new Date()) + "_" + Constants.DATA_FILE_NAME_GPS;
        mag_name = user + "_" + time1.format(new Date()) + "_" + Constants.DATA_FILE_NAME_MAG;
        rot_name = user + "_" + time1.format(new Date()) + "_" + Constants.DATA_FILE_NAME_ROTATION;

        dataFile_Acc = new File(accDirectory, acc_name);
        if (magnetometer.isMagAvailable()) {
            dataFile_Mag = new File(magDirectory, mag_name);
            if (mode.equals("1"))
                datafile_Rot = new File(rotationDirectory, rot_name);
        }
        dataFile_Gps = new File(gpsDirectory, gps_name);

        try {
            dataOutputStream_Acc = new FileOutputStream(dataFile_Acc, true);
            if (magnetometer.isMagAvailable()) {
                dataOutputStream_Mag = new FileOutputStream(dataFile_Mag, true);
                if (datafile_Rot != null)
                    dataOutputStream_Rot = new FileOutputStream(datafile_Rot, true);
            }

            dataOutputStream_Gps = new FileOutputStream(dataFile_Gps, true);

        } catch (IOException e) {
            e.printStackTrace();
        }

        myTimer = new Timer();
        myTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                getDataSensors();
            }

        }, 0, acc_mag_freq);
        gpsTimer = new Timer();
        gpsTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                getDataGps();
            }
        }, 0, gps_freq);
        return START_STICKY;
    }

    public void getDataGps() {
        data_Gps.append(time.format(new Date()));
        data_Gps.append(",");
        float[] gpsreading = gps.getReading();
        data_Gps.append(String.format("%.10f", gpsreading[0]));
        data_Gps.append(",");
        data_Gps.append(String.format("%.10f", gpsreading[1]));
        data_Gps.append("\n");
        try {
              dataOutputStream_Gps.write(data_Gps.toString().getBytes());

            data_Gps.setLength(0);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void getDataSensors() {
        data_Acc.append(time.format(new Date()));
        data_Acc.append(",");
        if (magnetometer.isMagAvailable()) {
            data_Mag.append(time.format(new Date()));
            data_Mag.append(",");
            if (mode == "1") {
                data_Rot.append(time.format(new Date()));
                data_Rot.append(",");
            }
        }
        float[] acc = accelerometer.getLastReading();
        float[] mag = magnetometer.getLastReading();
        float[] rotVal = rot.getLastReading();
        //accelerometer data_Acc
        data_Acc.append(String.format("%.3f", acc[0]));
        data_Acc.append(",");
        data_Acc.append(String.format("%.3f", acc[1]));
        data_Acc.append(",");
        data_Acc.append(String.format("%.3f", acc[2]));
        //data_Acc.append(",");
        if (magnetometer.isMagAvailable()) {
            //magnetometer data_Acc
            data_Mag.append(String.format("%.3f", mag[0]));
            data_Mag.append(",");
            data_Mag.append(String.format("%.3f", mag[1]));
            data_Mag.append(",");
            data_Mag.append(String.format("%.3f", mag[2]));
            //data_Acc.append(",");
            // write this data_Acc to file
            data_Mag.append("\n");
            if (mode == "1") {
                data_Rot.append(String.format("%.3f", rotVal[0]));
                data_Rot.append(",");
                data_Rot.append(String.format("%.3f", rotVal[1]));
                data_Rot.append(",");
                data_Rot.append(String.format("%.3f", rotVal[2]));
                //data_Acc.append(",");
                // write this data_Acc to file
                data_Rot.append("\n");
            }
        }
        data_Acc.append("\n");
        try {

            dataOutputStream_Acc.write(data_Acc.toString().getBytes());
            if (magnetometer.isMagAvailable()) {
                dataOutputStream_Mag.write(data_Mag.toString().getBytes());
                if (mode == "1") {
                    dataOutputStream_Rot.write(data_Rot.toString().getBytes());
                }
            }
            data_Acc.setLength(0);
            data_Rot.setLength(0);
            data_Mag.setLength(0);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
}

据我所知,Android并不是为支持硬实时事件而设计的,所以我不认为你能以任何方式实现这一点


无论如何,我认为你可以尝试使用并定义该服务,如果你可以在你的应用程序中使用这些东西,据我所知,它不会确保每100毫秒执行一次数据检索,但它可能会更定期地执行。

据我所知,Android的设计不支持硬实时事件,所以我不认为你能以任何方式做到这一点


无论如何,我认为你可以尝试使用并定义服务,如果你可以在你的应用程序中使用这些东西,据我所知,它不会确保每100毫秒执行一次数据检索,但它可能会定期执行。

我只使用前景服务。我只使用前景服务。你获得部分锁定了吗?如果屏幕被锁定,cpu将进入睡眠状态。为此,您需要获取部分锁。如果这些延迟不频繁,那么这也是正常的,因为计时器不能保证精确的时间间隔。比如说,如果你让它每20毫秒触发一次,它不会一直按这个时间间隔触发,因为这取决于CPU负载和设备中发生的其他事情。这种行为会导致几毫秒的延迟。例如,对于活动识别来说,延迟通常是可以接受的。如果经常发生,则使用部分锁定。您是否获得了部分锁定?如果屏幕被锁定,cpu将进入睡眠状态。为此,您需要获取部分锁。如果这些延迟不频繁,那么这也是正常的,因为计时器不能保证精确的时间间隔。比如说,如果你让它每20毫秒触发一次,它不会一直按这个时间间隔触发,因为这取决于CPU负载和设备中发生的其他事情。这种行为会导致几毫秒的延迟。例如,对于活动识别来说,延迟通常是可以接受的。如果频繁发生,则使用部分锁定。