質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.92%

Androidの加速度センサの値を一定間隔で取得する方法

解決済

回答 1

投稿

  • 評価
  • クリップ 2
  • VIEW 7,832
退会済みユーザー

退会済みユーザー

Androidの加速度センサの値を一定間隔(約200ms)で取得し、CSV形式で値を保存するアプリを作成しているのです。
しかし、取得間隔が一定にならず困っています。
何か良い方法があれば教えていただけないでしょうか。
宜しくお願い致します。

以下、MainActivity.java

public class  MainActivity extends AppCompatActivity implements SensorEventListener {
    private Sensor accSensor;
    private TextView mX;
    private TextView mY;
    private TextView mZ;
    private SensorManager mManager;
    public int button_flag = 0;

    long eventOccuredTimeMilli = -1;
    long eventOccuredTimeNano = -1;

    //sensorChangedで更新される情報(加速度,ジャイロ)

    ArrayList<String> accX = new ArrayList<String>();
    ArrayList<String> accY = new ArrayList<String>();
    ArrayList<String> accZ = new ArrayList<String>();

    ArrayList<String> timeStamp_forAcc = new ArrayList<String>();//UNIX時間
    ArrayList<String> timeStamp_Time_forAcc = new ArrayList<String>();//時間

    //書き込み用の情報
    ArrayList<String> accX_w = new ArrayList<String>();
    ArrayList<String> accY_w = new ArrayList<String>();
    ArrayList<String> accZ_w = new ArrayList<String>();

    ArrayList<String> timeStamp_forAcc_w = new ArrayList<String>();//UNIX時間
    ArrayList<String> timeStamp_Time_forAcc_w = new ArrayList<String>();//時間

    //時間(年.月.日_時:分:秒)
    SimpleDateFormat sdf = new SimpleDateFormat("yy.MM.dd_HH:mm:ss");

    //時間(年.月.日_時:分:秒:ミリ秒)
    SimpleDateFormat sdf1 = new SimpleDateFormat("yy.MM.dd_HH:mm:ss:SSS");

    //計測開始時間に使用する変数
    String start_time;

    //ファイル名の確認時に使用
    String last_fileName;

    String tmp_fileName;//評価対象のファイルを保存するときのやつ



    public void onAccuracyChanged(Sensor sensor, int n) {
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mManager = (SensorManager)this.getSystemService(SENSOR_SERVICE);
        accSensor = this.mManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        Button start_btn = (Button) findViewById(R.id.button);
        Button stop_btn = (Button) findViewById(R.id.button2);

        start_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                sdf.applyPattern("yy.MM.dd_HH:mm:ss");
                start_time = sdf.format(System.currentTimeMillis());

                button_flag = 1;

                initialize();
                last_fileName = "";
            }
        });

        stop_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                button_flag = 0;

                copy_information();
                save_route();
                initialize();
            }
        });

        mX = (TextView)this.findViewById(R.id.textView1);
        mY = (TextView)this.findViewById(R.id.textView2);
        mZ = (TextView)this.findViewById(R.id.textView3);


    }


    @Override
    protected void onPause() {
        super.onPause();
        this.mManager.unregisterListener((SensorEventListener)this, this.accSensor);
    }

    protected void onResume() {
        super.onResume();
        this.mManager.registerListener((SensorEventListener) this, this.accSensor, SensorManager.SENSOR_DELAY_NORMAL);
    }

    public void onSensorChanged(SensorEvent sensorEvent) {

        //UNIX時間
        if (eventOccuredTimeMilli < 0){
            eventOccuredTimeMilli = System.currentTimeMillis();
            eventOccuredTimeNano = sensorEvent.timestamp;
        }

        long unixtime = eventOccuredTimeMilli
                + (sensorEvent.timestamp - eventOccuredTimeNano) / 1000000;
        if (sensorEvent.sensor.getType() ==  Sensor.TYPE_ACCELEROMETER) {
            if(button_flag==1){

                    Log.d("SENSOR_DATA", "TYPE_ACCELEROMETER1 = " + String.valueOf(sensorEvent.values[0]));
//                    Log.d("SENSOR_DATA", "TYPE_ACCELEROMETER2 = " + String.valueOf(sensorEvent.values[1]));
//                    Log.d("SENSOR_DATA", "TYPE_ACCELEROMETER3 = " + String.valueOf(sensorEvent.values[2]));

                    mX.setText("加速度センサーX:" + String.valueOf(sensorEvent.values[0]));
                    mY.setText("加速度センサーY:" + String.valueOf(sensorEvent.values[1]));
                    mZ.setText("加速度センサーZ:" + String.valueOf(sensorEvent.values[2]));

                accX.add(String.format("%3.2f", sensorEvent.values[0]));
                accY.add(String.format("%3.2f", sensorEvent.values[1]));
                accZ.add(String.format("%3.2f", sensorEvent.values[2]));


                timeStamp_forAcc.add(String.valueOf(unixtime));
                timeStamp_Time_forAcc.add(sdf1.format(unixtime));

            }else{
                mX.setText("止まっていますX");
                mY.setText("止まっていますY");
                mZ.setText("止まっていますZ");
            }
        }
    }

    public void copy_information() {


        accX_w = new ArrayList(accX);
        accY_w = new ArrayList(accY);
        accZ_w = new ArrayList(accZ);


        timeStamp_forAcc_w = new ArrayList(timeStamp_forAcc);
        timeStamp_Time_forAcc_w = new ArrayList(timeStamp_Time_forAcc);

    }

    //ArrayListを初期化
    public void initialize() {

        accX.clear();
        accY.clear();
        accZ.clear();


        timeStamp_forAcc.clear();
        timeStamp_Time_forAcc.clear();

        eventOccuredTimeMilli = -1;
        eventOccuredTimeNano = -1;
    }

    /*書き込み関係*/
    public void save_route() {
        String txt_name = "soukoukiroku";
        String filePath;

        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            filePath = Environment.getExternalStorageDirectory().toString();
        }else{
            filePath = Environment.getDataDirectory().toString();
        }

        File file_route_acc = new File(filePath + "/acc_log/" + txt_name);
        file_route_acc.getParentFile().mkdir();

        String str;
        sdf.applyPattern("yy.MM.dd_HH:mm:ss");
        str = sdf.format(System.currentTimeMillis());

        txt_name = start_time + "-" + str + ".csv";

        //初めての書き込みなら、そのままtxt_nameのファイル名で書き込み。それ以外ならリネーム後書き込み。
        if(last_fileName != ""){
            ArrayList<String> list = new ArrayList<String>();
            list.add("/acc_log/");
            for(int i=0; i < list.size(); i++){
                File file = new File( filePath + list.get(i) + last_fileName );
                if (file.exists()) {
                    //リネーム
                    File file2 = new File(filePath + list.get(i) + txt_name);
                }
            }
        }
        last_fileName = txt_name;

        if(!start_time.equals(str)) {

            tmp_fileName = txt_name;

            // 別スレッドで時間のかかる処理を実行
            new Thread(new Runnable() {
                @Override

                public void run() {
                    //ここではセンサデータを書き込み
                    writeCSV_route();

                }
            }).start();

        }
    }

    //    センサデータ書き込み
    public void writeCSV_route() {

        String str;
        String filePath;
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            filePath = Environment.getExternalStorageDirectory().toString();
        }else{
            filePath = Environment.getDataDirectory().toString();
        }

        //センサデータを書き込む部分

        //acc書き込み
        try {
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filePath + "/acc_log/" + tmp_fileName, true), "UTF-8"));
            //             addDebugMessage("acc書きこみ開始 filePath: " + filePath + "/acc/" + tmp_fileName + "  timeStamp.size(): " + timeStamp_forAcc.size());
            for (int i = 0; i < timeStamp_forAcc_w.size(); i++) {
                str = timeStamp_forAcc_w.get(i) + "," + timeStamp_Time_forAcc_w.get(i) + "," + accX_w.get(i) + "," + accY_w.get(i) + "," + accZ_w.get(i);
                bw.write(str);
                bw.newLine();
//                                Log.d("MainActivity", "writeCSV_route_acc    i: " + i + "    str: " + str + "    filePath: " + filePath + "/acc_test/" + tmp_fileName);
            }
            bw.close();
        }catch (Exception e) {
        }



        timeStamp_forAcc_w.clear();
        timeStamp_Time_forAcc_w.clear();

        accX_w.clear();
        accY_w.clear();
        accZ_w.clear();

    }

}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

onSensorChangedは名前の通りセンサーの値が変化したら呼ばれます。
そのため更新が一定の間隔になることはありません。

onSensorChangedを使ってセンサー値の最新値に更新するだけにし、Handler等を使って保存処理を定期実行でファイルに書き込むようにしましょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/09/30 12:06

    回答ありがとうございます。
    Handlerを使って定期実行を行い、保存処理をするようにします。
    Handlerを追加する場所ですが、onSensorChanged内に追加すればよいでしょうか。

    キャンセル

  • 2016/09/30 14:21

    場合によりますが、Activityのライフサイクルで定期実行を同期するならフィールド変数にすべきですね。

    キャンセル

  • 2016/09/30 17:00

    わかりました。
    フィールド変数で追加するようにします。
    ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る