我最近开发了一款穿戴应用程序,用于从我的 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", "...................");
}
}
您最终找到解决方案了吗?我也有同样的问题