(15) 加速度センサーを使ってみる。

投稿者: | 2018年10月2日

この記事は最終更新から 1114日 が経過しています。

1. やりたいこと

(14) 実機のセンサーの実装有無を確認する。 では所有している実機に加速度センサーが付いていることを確認した。

今回は実際に加速度センサーを使ってみたい。

とは言っても、いきなりボールを転がすのはハードルが高い。

まずは…
実機を傾けたときのセンサーの出力値を表示してみる。

2. やってみる!

(1) 加速度センサーの仕様

加速度センサーは、実機を傾けたときの X, Y, Z軸方向の加速度を計測・出力してくれる。

よって…
今回作るアプリでは、各軸の加速度 3値を表示する。

(2) 画面レイアウト

こんな感じ。

(3) プログラミング

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements SensorEventListener {
    private SensorManager m_sensorManager;
    private TextView m_val_x_TextView;
    private TextView m_val_y_TextView;
    private TextView m_val_z_TextView;

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

        m_sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        m_val_x_TextView = findViewById(R.id.val_x);
        m_val_y_TextView = findViewById(R.id.val_y);
        m_val_z_TextView = findViewById(R.id.val_z);
    }

    @Override protected void onResume() {
        super.onResume();
        // Event Listener登録
        Sensor accel = m_sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        m_sensorManager.registerListener(this, accel, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override protected void onPause() {
        super.onPause();
        // Event Listener登録解除
        m_sensorManager.unregisterListener(this);
    }

    @Override public void onSensorChanged(SensorEvent event) {
        if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
            m_val_x_TextView.setText(String.format("%.3f", event.values[0]));
            m_val_y_TextView.setText(String.format("%.3f", event.values[1]));
            m_val_z_TextView.setText(String.format("%.3f", event.values[2]));
        }
    }

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

(4) 実行結果

1) X軸

・水平状態が0
・左回転(反時計回り)がプラス方向
・右回転(時計回り)がマイナス方向

左 90度回転
右 90度回転

2) Y軸

・水平状態が0
・手前に向かって回転がプラス方向
・奥に向かって回転がマイナス方向

手前 90度回転
奥 90度回転

3. 応用

(1) 問題点&改善案

上記のプログラムでは onSensorChanged でイベントが入るたびに描画を更新していた。
これが実に重たい。

よって…
onSensorChanged ではセンサーの値を退避するだけにする。
退避した値の描画は、周期ハンドラを使って 200ms周期で実行する。

これで軽くなるはずだ。

(2) プログラミング

・200ms周期で X, Y, Z表示値を更新するようにした。
・TextView::setText()は無効領域を作るようで、再描画のための View::invalid()コールは必要なかった。

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity implements SensorEventListener {
    private SensorManager m_sensorManager;
    private TextView m_val_x_TextView, m_val_y_TextView, m_val_z_TextView;
    private float m_sensor_val_x, m_sensor_val_y, m_sensor_val_z;
    private Runnable m_runnable;
    private final Handler m_handler = new Handler();

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

        m_sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
        m_val_x_TextView = findViewById(R.id.val_x);
        m_val_y_TextView = findViewById(R.id.val_y);
        m_val_z_TextView = findViewById(R.id.val_z);
        m_sensor_val_x = m_sensor_val_y = m_sensor_val_z = 0;
        StartCyclicHandler();       // 周期ハンドラ開始
    }

    @Override protected void onResume() {
        super.onResume();
        // Event Listener登録
        Sensor accel = m_sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        m_sensorManager.registerListener(this, accel, SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override protected void onPause() {
        super.onPause();
        m_sensorManager.unregisterListener(this);   // Event Listener登録解除
        StoptCyclicHandler();       // 周期ハンドラ停止
    }

    @Override public void onSensorChanged(SensorEvent event) {
        if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
            m_sensor_val_x = event.values[0];
            m_sensor_val_y = event.values[1];
            m_sensor_val_z = event.values[2];
        }
    }

    protected void StartCyclicHandler(){
        m_runnable = new Runnable() {
            @Override public void run() {
                m_val_x_TextView.setText(String.format("%.3f", m_sensor_val_x));
                m_val_y_TextView.setText(String.format("%.3f", m_sensor_val_y));
                m_val_z_TextView.setText(String.format("%.3f", m_sensor_val_z));
                m_handler.postDelayed(this, 200);    // 200msスリープ
            }
        };
        m_handler.post(m_runnable);     // スレッド起動
    }
    protected void StoptCyclicHandler() {
        m_handler.removeCallbacks(m_runnable);
    }

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

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です


日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)