package at.wada811.android.library.demos.fragment; import android.hardware.Sensor; import android.os.Bundle; import android.support.v4.app.FragmentActivity; import android.widget.TextView; import at.wada811.android.library.demos.R; import at.wada811.app.fragment.SensorFragment; import at.wada811.app.fragment.SensorFragment.SensorCallback; import at.wada811.app.fragment.SensorFragment.SensorCallbackProvider; import at.wada811.utils.AndroidUtils; import at.wada811.utils.LogUtils; import java.util.ArrayList; /** * [Android]端末が振られたことを加速度センサーから検出する | DevAchieve * http://wada811.blogspot.com/2013/12/android-shake-detection.html */ 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; private TextView mText1; private TextView mText2; private TextView mText3; @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_sensor); ArrayList<Integer> sensorTypes = new ArrayList<Integer>(); sensorTypes.add(Sensor.TYPE_LINEAR_ACCELERATION); SensorFragment sensorFragment = SensorFragment.newInstance(sensorTypes); getSupportFragmentManager().beginTransaction().add(sensorFragment, SensorFragment.TAG).commit(); mText1 = (TextView)findViewById(R.id.text1); mText2 = (TextView)findViewById(R.id.text2); mText3 = (TextView)findViewById(R.id.text3); } @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)); int iX = (int)(x * 1000) / 100; int iY = (int)(y * 1000) / 100; int iZ = (int)(z * 1000) / 100; int dX = iX - (int)(mLastX * 1000) / 100; int dY = iY - (int)(mLastY * 1000) / 100; int dZ = iZ - (int)(mLastZ * 1000) / 100; mText1.setText("x: " + iX + "(" + dX + ")"); mText2.setText("y: " + iY + "(" + dY + ")"); mText3.setText("z: " + iZ + "(" + dZ + ")"); 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; } }