2017-09-15 6 views
1

私のAndroidセンサーアプリケーションでは、別のプロセスで連続して実行され、別々のセンサーのデータ(加速度計、磁力計、GPS)を記録するサービス(フォアグラウンド)を持っています。私は、さまざまなセンサーのさまざまなCSVファイルにデータをフェッチして書き込むために、100ミリ秒のタイマーを使用しました。問題は、データの記録に一貫性がない、すなわちタイマーが正常に動作していないことなどです。 1秒間に10サンプルを記録する必要がありますが、いくつかの間隔を数100 ms、場合によっては数秒間スキップします。私はセンサー用のカスタムクラスを定義しており、正しく動作しています。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; 
    } 
} 
+0

あなたはpartial_lockを取得しましたか? https://developer.android.com/training/scheduling/wakelock.html画面がロックされると、CPUはスリープ状態になります。そのためには、部分ロックを取得する必要があります。 – utengr

+0

これらの遅延が頻繁でない場合は、タイマーが正確な時間間隔を保証しないため、これも正常です。 20ミリ秒ごとに起動するように要求すると、CPU負荷やデバイスで何が起きているかによって異なります。 – utengr

+0

このような現象は、数ミリ秒の遅延を引き起こします。通常は、例えば活動認識のための許容遅延である。頻繁に起こっている場合は、部分ロックを使用します。 – utengr

答えて

0

私の知る限りは、Androidはハードリアルタイムのイベントをサポートするように設計されていないので、私はあなたがどのような方法でそれを達成することができないと思います知っています。

とにかく、alarmsを使用して、サービスでforeground serviceと定義すると、アプリでこれらの機能を使用できれば、データ取得が100ミリ秒ごとに確実に実行されることはありませんより定期的にそれを行う可能性が高い。

+0

私は前景サービスのみを使用しています。 –

関連する問題