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

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

ただいまの
回答率

91.37%

  • Java

    10445questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Android

    5156questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

  • Android Studio

    2707questions

    Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

ボタンでの加速度とジャイロセンサのCSV保存

解決済

回答 1

投稿 2017/11/27 16:12 ・編集 2017/11/30 01:19

  • 評価
  • クリップ 0
  • VIEW 120

suport

score 1

前提・実現したいこと

Androidのアプリをつくっていて、加速度とジャイロセンサの値を時刻とともにCSVで実機に保存したいのですが、うまくいかず困っています。また、START STOP のボタンで加速度とジャイロセンサの記録を開始・終了させれるようにしたいのですが、そこもうまくいっていません。どなたか教えていただけると嬉しいです。

発生している問題・エラーメッセージ

エラーはないんですけど、CSVで保存するときに時刻も一緒に保存したい。
start stop ボタンが表示されない。

該当のソースコード

Javaなど

public class MainActivity extends AppCompatActivity implements Runnable, SensorEventListener {
    SensorManager mSensorManager;
    Sensor mLinearAcc;
    Sensor mGyro;
    TextView tv;
    Handler h;
    float kx, ky, kz;
    float gx, gy, gz;

//センサーを使うための準備
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mSensorManager =
                (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        mLinearAcc = mSensorManager.
                getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
        mGyro = mSensorManager.
                getDefaultSensor(Sensor.TYPE_GYROSCOPE);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        LinearLayout ll = new LinearLayout(this);
        setContentView(ll);

        tv = new TextView(this);
        ll.addView(tv);

        h = new Handler();

        h.postDelayed(this, 800);

    
   Button button2 = (Button) findViewById(R.id.button2);
    button2.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
        // ボタンクリックしたときの処理

        }
        });
    }

//センサーで得る値が変わるたびに行う動作
    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_LINEAR_ACCELERATION) {
            kx = event.values[0];
            ky = event.values[1];
            kz = event.values[2];
            Log.d("MainActivity",
                    "x=" + String.valueOf(event.values[0]) +
                            "y=" + String.valueOf(event.values[1]) +
                            "z=" + String.valueOf(event.values[2]));
            System.out.println("xの加速度 : " + kx
                    + "yの加速度 : " + ky
                    + "zの加速度 : " + kz);
            try {
                //出力先を作成する
                FileWriter fw = new FileWriter(Environment.getExternalStorageDirectory().getPath()+"/Kasokudo.csv", true);
                PrintWriter pw = new PrintWriter(new BufferedWriter(fw));

                //内容を指定する
                pw.print(kx );
                pw.print(",");
                pw.print(ky );
                pw.print(",");
                pw.print(kz );
                pw.println();

                //ファイルに書き出す
                pw.close();

                //終了メッセージを画面に出力する
                System.out.println("出力が完了しました。");

            } catch (IOException ex) {
                //例外時処理
                ex.printStackTrace();
            }

        } else if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
            gx = event.values[0];
            gy = event.values[1];
            gz = event.values[2];
            Log.d("MainActivity",
                    "X=" + String.valueOf(event.values[0]) +
                            "Y=" + String.valueOf(event.values[1]) +
                            "Z=" + String.valueOf(event.values[2]));
            System.out.println("Xのジャイロ :" + gx
                    + "Yのジャイロ :" + gy
                    + "Zのジャイロ :" + gz);
            try {
                //出力先を作成する
                FileWriter fw = new FileWriter(Environment.getExternalStorageDirectory().getPath()+"/Gyro.csv", true);
                PrintWriter pw = new PrintWriter(new BufferedWriter(fw));

                //内容を指定する

                pw.print(gx );
                pw.print(",");
                pw.print(gy );
                pw.print(",");
                pw.print(gz );
                pw.println();

                //ファイルに書き出す
                pw.close();

                //終了メッセージを画面に出力する
                System.out.println("出力が完了しました。");

            } catch (IOException ex) {
                //例外時処理
                ex.printStackTrace();
            }

        }
        }



    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    //データの更新時間間隔の設定
    @Override
    protected void onResume() {
        super.onResume();
        mSensorManager.registerListener(this, mLinearAcc, SensorManager.SENSOR_DELAY_NORMAL);
        mSensorManager.registerListener(this, mGyro, SensorManager.SENSOR_DELAY_NORMAL);
    }

    //実機での表示
    @Override
    public void run() {
        tv.setText("Xの加速度 : " + kx*100 + "\n"
                + "Yの加速度 : " + ky*100 + "\n"
                + "Zの加速度 : " + kz*100 + "\n"
                + "Xのジャイロ :" + gx + "\n"
                + "Yのジャイロ :" + gy + "\n"
                + "Zのジャイロ :" + gz + "\n"
        );
        h.postDelayed(this, 800);

    }
   }

XML
コード

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.user.kakunin.MainActivity">

    LinearLayout ll = new LinearLayout(this);
    tv = new TextView(this);
    ll.addView(tv);

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="スタートで保存開始、ストップで保存終了します"
        android:textAppearance="@style/TextAppearance.AppCompat.Body2"
        android:textSize="20sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.524" />

    <Button
        android:id="@+id/button2"
        android:layout_width="88dp"
        android:layout_height="48dp"
        android:layout_marginBottom="85dp"
        android:layout_marginLeft="77dp"
        android:layout_marginStart="77dp"
        android:layout_marginTop="87dp"
        android:text="Start"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView"
        app:layout_constraintVertical_bias="0.0"
        tools:layout_constraintBottom_creator="1"
        tools:layout_constraintLeft_creator="1"
        tools:layout_constraintTop_creator="1" />

    <Button
        android:id="@+id/button3"
        android:layout_width="88dp"
        android:layout_height="48dp"
        android:layout_marginEnd="52dp"
        android:layout_marginRight="73dp"
        android:text="Stop"
        app:layout_constraintBottom_toBottomOf="@+id/button2"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="@+id/button2"
        app:layout_constraintVertical_bias="0.0"
        tools:layout_constraintBottom_creator="1"
        tools:layout_constraintRight_creator="1"
        tools:layout_constraintTop_creator="1" />

</android.support.constraint.ConstraintLayout>

試したこと

課題に対してアプローチしたことを記載してください

補足情報(言語/FW/ツール等のバージョンなど)

より詳細な情報

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • keicha_hrs

    2017/11/28 23:29

    JavaコードとXMLをそれぞれ囲ってください。また、そのときにそれぞれの1行目を```Java、```XMLのように言語指定すれば、それに最適化した強調表示がされるので見やすくなります。

    キャンセル

  • suport

    2017/11/30 01:05

    コードを直してみたのですが(自分なりに...)最後のボタンのsetOnClickListenerでシンボル’setOnClickListener’が見つかりませんとエラーが出ました。あと、もう一つ聞きたいことがあるのですが、このボタンを押したら加速度とジャイロの値が表示されるようにするためには //ボタンをクリックしたときの処理 のところにはどのように書いたらいいのでしょうか? 初心者なんでいろいろわからないことだらけなので教えてほしいです。

    キャンセル

  • suport

    2017/11/30 01:20

    setOnClicListennerの件は解決しました。

    キャンセル

回答 1

checkベストアンサー

+1

エラーはないんですけど、CSVで保存するときに時刻も一緒に保存したい。

ここだけ「丸投げ」なのがすごく不思議に映るのだけど、ここまでいろいろ調べて作り上げたのでしょうから、時刻の取得の仕方も調べませんか?そんな難しい話ではありません。

start stop ボタンが表示されない。

onCreateの処理がおかしいです。

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 中略

        LinearLayout ll = new LinearLayout(this);
        setContentView(ll);

        tv = new TextView(this);
        ll.addView(tv);

        // 中略
    }


要点以外を端折るとこういう流れになっていますが、setContentViewはアクティビティ全体を描画するメソッドです。これでは、XMLによるレイアウトが一瞬で上書きされて消えてしまいます。ボタンが消えてしまうのもそのためです。このTextViewはXMLによるデザインの方に配置しましょう。

それから、最後にある

class  Button extends AppCompatActivity {


このクラスは完全に意味不明です。除去しましょう。

ボタンをクリックしたときの処理は

        Button button2 = findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // ボタンクリックしたときの処理
            }
        });


のように実装しましょう(先の意味不明クラスが存在したままだとエラーになってしまう)。

とりあえずこの辺りまで取り組んで検証してみては?


(12/01 20:50 追記)

測定開始はSensorManager#registerListener、測定停止はSensorManager#unregisterListenerで行えます。ですから、これをSTARTボタンとSTOPボタンを押したときのそれぞれで実行すればいいでしょう。ついでにHandlerで行っている描画処理もHandler#removeCallbacksで止めておきましょう。

それから、画面が閉じられたときもSTOPボタンを押したときと同じように測定とHandlerを止めておいた方がいいでしょう。そのためにonPauseを実装しておきます。

その代わり、ボタンを押したときに測定開始するのだから、現状のコードにあるonResumeの中身は空っぽにしておきます。

    final Button button2 = findViewById(R.id.button2);
    final Button button3 = findViewById(R.id.button3);
    button3.setEnabled(false);  // STOPボタンをグレーアウトして無効化する

    button2.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
                mSensorManager.registerListener(MainActivity.this, mLinearAcc, SensorManager.SENSOR_DELAY_NORMAL);
                mSensorManager.registerListener(MainActivity.this, mGyro, SensorManager.SENSOR_DELAY_NORMAL);
                mHandle.postDelayed(MainActivity.this, 800);
                button2.setEnabled(false);  // STARTボタンを無効化
                button3.setEnabled(true);   // STOPボタンを有効化
            }
        });
    }
    button3.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
                mSensorManager.unregisterListener(MainActivity.this);
                mHandle.removeCallbacks(MainActivity.this);
                button2.setEnabled(true);   // STARTボタンを有効化
                button3.setEnabled(false);  // STOPボタンを無効化
            }
        });
    }

    @Override
    protected void onPause() {
        super.onPause();
        mSensorManager.unregisterListener(MainActivity.this);
        mHandle.removeCallbacks(MainActivity.this);
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

投稿 2017/11/28 23:28

編集 2017/12/01 21:29

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/11/30 17:11

    回答に対するコメントはこちらに書いてください。

    キャンセル

  • 2017/12/01 20:15

    このボタンを押したら加速度とジャイロの値が表示されるようにするためには //ボタンをクリックしたときの処理 のところにはどのように書いたらいいのでしょうか?

    キャンセル

  • 2017/12/01 20:56

    STARTボタンを押したとき、STOPボタンを押したとき、それに加えて必要な処理を回答欄に書きました。

    ただ、このプログラムはまだこれでは動かせません。Environment.getExternalStorageDirectoryで得られる場所に書き込みを行うには、AndroidManifest.xmlにストレージ読み書きの許可を得る記述を行い、さらにRuntime Permissionと呼ばれる仕組みによって読み書き許可を得るコードを記述しなければなりません。それはRuntime Permissionというキーワードで調べれば、資料は出てくるはずです。

    それからレイアウトXMLの修正ね。結果を表示するTextViewをレイアウト側に移しましょうとは書きましたが、それであのような記述をされるということは、デザインとXMLの関係を全くわかっていないということですよね。それを一から説明するのはちょっと辛いですよ。さすがに入門本や入門サイトくらいは修めてくれないと・・・。

    キャンセル

  • 2017/12/01 21:19

    Runtime Permissionによるパーミッションリクエストの公式の資料です。サンプルコードもあります。
    https://developer.android.com/training/permissions/requesting.html

    キャンセル

  • 2017/12/04 18:20 編集

    一つ提案ですが、
    FileWriter fw = new FileWriter(Environment.getExternalStorageDirectory().getPath()+"/Kasokudo.csv", true);
    ではなく
    FileWriter fw = new FileWriter(getExternalFilesDir(null)+"/Kasokudo.csv", true);
    としたらどうですかね。これならば、Runtime Permissionなどという難しいことを考えなくても、書き込みはできます。ファイルが書き込まれる場所が、
    <内部ストレージ>/Android/data/<パッケージ名>/files/
    の下になるのでちょっと深くなりますが、普通のファイルマネージャーで閲覧できる場所ではあります。とりあえず「ファイルに記録できる」という結果を出したければ、これの方がてっとり早いんじゃないかなと。Runtime Permissionはその次のステージでいいんじゃないですかね。

    (12/04 18:20 getExternalFilesDir()の出力先パスを間違えたので訂正)

    キャンセル

  • 2017/12/04 15:20

    ありがとうございます。何回も質問して申し訳ないのですが、このボタンを押して3秒後に何らかの合図(音など)を実装させるにはどのように書き込んだらよいのでしょうか?

    キャンセル

  • 2017/12/05 00:35 編集

    質問の追加は原則やめましょう。キリがなくなるので。これは回答しますが。

    今も使っているHandler#postDelayedを使えばいいでしょう。すでにMainActivytにRunnableをimplementsしているので、それとは別にMainActivityの内部クラスとして

    private class PushButtonNotify implements Runnable {
    @Override
    public void run() {
    // 合図する処理
    }
    }

    のようにでも実装して、ボタンを押した処理の中で

    mHandler.postDelayed(new PushButtonNotify(), 3000);

    のように記述すればいいんじゃないでしょうか。

    キャンセル

  • 2017/12/06 13:41

    ありがとうございました。

    キャンセル

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

ただいまの回答率

91.37%

関連した質問

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

  • Java

    10445questions

    Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

  • Android

    5156questions

    Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

  • Android Studio

    2707questions

    Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。