歩数計をつくってみる 2020/08/09
加速度センサーを使って歩数計をつくってみました。

問題1:
液晶が真っ暗になった省電力モードでは、歩数のカウントをしません。
対策:省電力モードにならないようにする。
    画面を暗くして電力の消費を抑える。

問題2:
正確に歩数をカウントしているかわからない。
対策:足が着地したときに音を出して確認できるようにする。

PedometerView.javaのソースです。

package net.sadaji.pedometer;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.RectF;

public class PedometerView  extends View{
    private MainActivity m_MainActivity;
    private int m_steps = 0;
    PedometerView(Context cntext){
        super(cntext);
        m_MainActivity = (MainActivity)cntext;
        //消費電力を節約するため背景は黒にする
        setBackgroundColor(Color.BLACK);
    }

    @Override
    protected void onDraw(Canvas canvas){
        //String  str;
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        drawSteps(canvas, paint, m_steps);//歩数の表示
        m_steps++;
    }

    //歩数の表示
    private void drawSteps(Canvas canvas, Paint paint, int steps){
        String str = String.format("%d 歩",  steps);
        int width = getWidth();
        RectF rc = new RectF();
        int padding = 60;
        rc.left = padding;
        rc.top = 360;
        rc.right = width  - padding;
        rc.bottom = rc.top + 140;
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        paint.setColor(Color.rgb(255, 255, 0));
        canvas.drawRoundRect(rc, 60, 60, paint);

        paint.setTextSize(98);
        paint.setColor(Color.rgb(0, 0, 0));
        float textWidth = paint.measureText(str);
        int x = (int)(rc.left + ((rc.right  - rc.left) - textWidth) / 2);
        Paint.FontMetrics metrics = new Paint.FontMetrics();
        float textHeight = paint.getFontMetrics(metrics);
        int y = (int)(rc.bottom - ((rc.bottom  - rc.top) - textHeight) / 2 );
        y -= metrics.descent;
        canvas.drawText(str, x, y, paint);
        paint.setStyle(Paint.Style.STROKE);
        canvas.drawRoundRect(rc, 60, 60, paint);
    }

}
非常にシンプルなソースです。次にMainActivity.javaのソースです。

package net.sadaji.pedometer;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.util.Log;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    private SensorManager manager;
    private SensorEventListener listener;
    private List list;
    PedometerView m_PedomterView;
    long m_prevTime;
    MediaPlayer mp;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //viewの生成とセット
        m_PedomterView = new PedometerView(this);
        setContentView(m_PedomterView);
        //スリープモードにしない
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        //スクリーンを暗くする
        LayoutParams lp = getWindow().getAttributes();
        lp.screenBrightness = 0.01F;
        getWindow().setAttributes(lp);
        //前回検出した時刻を控える
        m_prevTime = System.currentTimeMillis();
        //メディアプレイヤー作成
        mp = MediaPlayer.create(this, R.raw.pedo);

        manager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        list = manager.getSensorList(Sensor.TYPE_ACCELEROMETER);
        //加速度センサーのイベントリスナーの作成
        listener = new SensorEventListener() {
            public void onSensorChanged(SensorEvent event) {
                double g_X = (double)event.values[0];
                double g_Y = (double)event.values[1];
                double g_Z = (double)event.values[2];
                double grv = Math.sqrt(g_X * g_X + g_Y * g_Y + g_Z *g_Z);
                long currentTime = System.currentTimeMillis();
                //Log.d("currentTime",String.format("%d",  currentTime));
                //加速度が一定数こえたか スマホに応じて要調整
                if(grv > 12.5){
                    //前回検出した時刻より一定時間経過したか 要調整
                    if(currentTime - m_prevTime > 300.0){
                        //歩数の表示
                        m_PedomterView.invalidate();
                        m_prevTime = currentTime;
                        //音を出す
                        mp.start();
                    }
                }
            }

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

    @Override
    protected void onResume() {
        super.onResume();
        if (list.size() > 0) {
            manager.registerListener(listener, list.get(0),
                    SensorManager.SENSOR_DELAY_NORMAL);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
 //       manager.unregisterListener(listener, list.get(0));
    }
}
足が着地した加速度を12.5以上とします。 更に前回検出した時間から現在が300ms以上経っていることで着地を検出します。(300ms以下では着地とみなさない)
着地を検出すると,
PedometerViewに再描画をさせる
音を出します
実際Xperia Aceで試してみました。3000歩くらい歩きました。足が着地すると確認音が正常に鳴りました。

確認音はpedo.mp3

リソースにrawフォルダを作成し、そこにpeedo.mp3を貼り付けます。それなりに仕上がっていますので、興味ある方はこれをベースに応用を作ってみてください。