因此,在我的Android传感器应用程序中,我有一个服务(前台),它在不同的进程中连续运行,并记录单独的传感器数据(加速计,磁力计,GPS)。我已经使用了一个周期为100毫秒的计时器来获取和写入不同传感器的各种CSV文件中的数据。问题是数据记录不一致,即计时器不能正常工作或者其他情况。它跳过一些间隔,例如几百毫秒或有时甚至几秒,而它应该每秒记录十个样本。我已经为传感器定义了自定义类,并且它们正在正常工作。Android传感器数据采集服务与定时器不一致
这里是我的服务代码:
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;
}
}
您是否获得partial_lock? https://developer.android.com/training/scheduling/wakelock.html如果你的屏幕被锁定,CPU就进入睡眠状态。为此,您需要获取部分锁定。 – utengr
如果这些延迟不频繁,那么也是正常的,因为计时器不能保证确切的时间间隔。比方说,如果你每隔20毫秒就要求它发射一次,它将不会在这个时间间隔内一直发射,因为它取决于CPU的负载以及设备中的其他情况。 – utengr
这种行为会导致几毫秒的延迟。例如,对于活动识别通常是可以接受的延迟。如果它频繁发生然后使用部分锁。 – utengr