Question:
I am writing one application. I need to define the "shaking" of the device. How to implement this?
Answer:
- Add an indication of the use of the sensor – accelerometer to the manifest
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
- Create a class that implements the
SensorEventListener
interface in theSensorEventListener
methodonSensorChanged
handle the sensor readings. For example like this:
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
public class ShakeDetector implements SensorEventListener {
private static final float SHAKE_THRESHOLD_GRAVITY = 2.7F;
private static final int SHAKE_SLOP_TIME_MS = 500;
private static final int SHAKE_COUNT_RESET_TIME_MS = 3000;
private OnShakeListener mListener;
private long mShakeTimestamp;
private int mShakeCount;
public void setOnShakeListener(OnShakeListener listener) {
this.mListener = listener;
}
public interface OnShakeListener {
public void onShake(int count);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// ignore
}
@Override
public void onSensorChanged(SensorEvent event) {
if (mListener != null) {
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
float gX = x / SensorManager.GRAVITY_EARTH;
float gY = y / SensorManager.GRAVITY_EARTH;
float gZ = z / SensorManager.GRAVITY_EARTH;
float gForce = (float)Math.sqrt(gX * gX + gY * gY + gZ * gZ);
if (gForce > SHAKE_THRESHOLD_GRAVITY) {
final long now = System.currentTimeMillis();
if (mShakeTimestamp + SHAKE_SLOP_TIME_MS > now) {
return;
}
if (mShakeTimestamp + SHAKE_COUNT_RESET_TIME_MS < now) {
mShakeCount = 0;
}
mShakeTimestamp = now;
mShakeCount++;
mListener.onShake(mShakeCount);
}
}
}
}
- Now you can use this class to show a dialogue in the activity after shaking the device. To do this, create an object of the
SensorManager
class, from it get an instance of theSensor
class, which, together with our implementation ofSensorEventListener
pass to theSensorManager#registerListener()
method. Here is the activation code:
public class BaseActivity extends AppCompatActivity {
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private ShakeDetector mShakeDetector;
private AlertDialog.Builder mDialogBuilder;
private AlertDialog mAlertDialog;
@Override
public void onResume() {
super.onResume();
mSensorManager.registerListener(mShakeDetector, mAccelerometer, SensorManager.SENSOR_DELAY_UI);
}
@Override
public void onPause() {
mSensorManager.unregisterListener(mShakeDetector);
super.onPause();
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mShakeDetector = new ShakeDetector();
mShakeDetector.setOnShakeListener(new ShakeDetector.OnShakeListener() {
@Override
public void onShake(int count) {
if (mAlertDialog == null || !mAlertDialog.isShowing()) {
mDialogBuilder = new AlertDialog.Builder(BaseActivity.this);
mDialogBuilder.setMessage("Ух-ты!")
.setCancelable(false)
.setNegativeButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
});
mAlertDialog = mDialogBuilder.create();
mAlertDialog.show();
}
}
});
}
}