ようやくそれっぽいものができたので公開してみる。
[Android]加速度センサーのノイズ除去とSensorFragment | DevAchieve
もうちょっと面白みがあると良いんだけど何も思いつかなかったから
android.hlidskialf.com/blog/code/android-shake-detection-listener を
パクってシェイクを検知する Activity を作った。
SensorActivity.java | wada811/AndroidLibrary-wada811
public class SensorActivity extends FragmentActivity implements SensorCallbackProvider { final SensorActivity self = this; private static final int SPEED_THRESHOLD = 25; private static final int SHAKE_TIMEOUT = 500; private static final int SHAKE_DURATION = 1000; private static final int SHAKE_COUNT = 3; private int mShakeCount = 0; private long mLastTime = 0; private long mLastAccel = 0; private long mLastShake = 0; private float mLastX, mLastY, mLastZ = 0; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); ArrayList<Integer> sensorTypes = new ArrayList<Integer>(); sensorTypes.add(Sensor.TYPE_LINEAR_ACCELERATION); SensorFragment sensorFragment = SensorFragment.newInstance(sensorTypes); getSupportFragmentManager().beginTransaction().add(sensorFragment, SensorFragment.TAG).commit(); } @Override public SensorCallback getSensorCallback(){ return new SensorCallback(){ @Override public void onLinearAccelerationSensorChanged(float x, float y, float z){ LogUtils.v("x: " + String.format("%+01.2f", x) + ", y: " + String.format("%+01.2f", y) + ", z: " + String.format("%+01.2f", z)); boolean isShaked = detectShake(x, y, z); if(isShaked){ AndroidUtils.showToast(self, "shaked!"); } } }; } public boolean detectShake(float x, float y, float z){ boolean isShaked = false; // シェイク時間のチェック long now = System.currentTimeMillis(); if(mLastTime == 0){ mLastTime = now; } // SHAKE_TIMEOUT までに次の加速を検知しなかったら mShakeCount をリセット if(now - mLastAccel > SHAKE_TIMEOUT){ mShakeCount = 0; } // 速度を算出する long diff = now - mLastTime; float speed = Math.abs(x + y + z - mLastX - mLastY - mLastZ) / diff * 10000; LogUtils.d("speed: " + speed); if(speed > SPEED_THRESHOLD){ // mShakeCount の加算、SHAKE_COUNT を超えているかのチェック // 最後のシェイク時間から SHAKE_DURATION 経過しているかチェック if(++mShakeCount >= SHAKE_COUNT && now - mLastShake > SHAKE_DURATION){ mLastShake = now; mShakeCount = 0; isShaked = true; } // SPEED_THRESHOLD を超える速度を検出した時刻をセット mLastAccel = now; } mLastTime = now; mLastX = x; mLastY = y; mLastZ = z; return isShaked; } }それぞれの閾値が適切かどうかはわからないです。
歩いていて手に持った端末が振られたことを検知していたから Xperia A にはちょうどいいかもしれません。
<ポイント>これを調整するの難しそうです。
1.機種によって加速度センサーの閾値が違う。
2.機種によって加速度センサーの搭載位置が違う。
→同じくらいの強さで振っても機種によって取得できる値がまったく違う。
3.端末持つ位置でも当然変わってくる。
加速度センサーを利用した自社Androidアプリ『鮭 – Shake』をリリース!! | R-Labs
収集した実測値の標準偏差を算出して調整幅のMAX値とMIN値を決定しています。これが一番良い対処法かもしれません。
加速度センサーを利用した自社Androidアプリ『鮭 – Shake』をリリース!! | R-Labs
このへんは調整だからコスパと重要度と精度を天秤にかけてあげなければいけなさそうです。