How to Refresh App Upon Shaking the Device

How to refresh app upon shaking the device?

Here is an example code.
Put this into your activity class:

  /* put this into your activity class */
private SensorManager mSensorManager;
private float mAccel; // acceleration apart from gravity
private float mAccelCurrent; // current acceleration including gravity
private float mAccelLast; // last acceleration including gravity

private final SensorEventListener mSensorListener = new SensorEventListener() {

public void onSensorChanged(SensorEvent se) {
float x = se.values[0];
float y = se.values[1];
float z = se.values[2];
mAccelLast = mAccelCurrent;
mAccelCurrent = (float) Math.sqrt((double) (x*x + y*y + z*z));
float delta = mAccelCurrent - mAccelLast;
mAccel = mAccel * 0.9f + delta; // perform low-cut filter
}

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

@Override
protected void onResume() {
super.onResume();
mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
}

@Override
protected void onPause() {
mSensorManager.unregisterListener(mSensorListener);
super.onPause();
}

And add this to your onCreate method:

    /* do this in onCreate */
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mSensorManager.registerListener(mSensorListener, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
mAccel = 0.00f;
mAccelCurrent = SensorManager.GRAVITY_EARTH;
mAccelLast = SensorManager.GRAVITY_EARTH;

You can then ask "mAccel" wherever you want in your application for the current acceleration, independent from the axis and cleaned from static acceleration such as gravity.
It will be approx. 0 if there is no movement, and, lets say >2 if the device is shaked.

Based on the comments - to test this:

if (mAccel > 12) {
Toast toast = Toast.makeText(getApplicationContext(), "Device has shaken.", Toast.LENGTH_LONG);
toast.show();
}

Notes:

The accelometer should be deactivated onPause and activated onResume to save resources (CPU, Battery).
The code assumes we are on planet Earth ;-) and initializes the acceleration to earth gravity. Otherwise you would get a strong "shake" when the application starts and "hits" the ground from free-fall. However, the code gets used to the gravitation due to the low-cut filter and would work also on other planets or in free space, once it is initialized.
(you never know how long your application will be in use...;-)

How to do: Shake your iphone to refresh feature

A quick search reveals this question:

How do I detect when someone shakes an iPhone?

Then when you detect the shake you perform your "refresh" method;

How to detect shake event with android?

From the code point of view, you need to implement the SensorListener:

public class ShakeActivity extends Activity implements SensorListener

You will need to acquire a SensorManager:

sensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);

And register this sensor with desired flags:

sensorMgr.registerListener(this,
SensorManager.SENSOR_ACCELEROMETER,
SensorManager.SENSOR_DELAY_GAME);

In your onSensorChange() method, you determine whether it’s a shake or not:

public void onSensorChanged(int sensor, float[] values) {
if (sensor == SensorManager.SENSOR_ACCELEROMETER) {
long curTime = System.currentTimeMillis();
// only allow one update every 100ms.
if ((curTime - lastUpdate) > 100) {
long diffTime = (curTime - lastUpdate);
lastUpdate = curTime;

x = values[SensorManager.DATA_X];
y = values[SensorManager.DATA_Y];
z = values[SensorManager.DATA_Z];

float speed = Math.abs(x+y+z - last_x - last_y - last_z) / diffTime * 10000;

if (speed > SHAKE_THRESHOLD) {
Log.d("sensor", "shake detected w/ speed: " + speed);
Toast.makeText(this, "shake detected w/ speed: " + speed, Toast.LENGTH_SHORT).show();
}
last_x = x;
last_y = y;
last_z = z;
}
}
}

The shake threshold is defined as:

private static final int SHAKE_THRESHOLD = 800;

There are some other methods too, to detect shake motion. look at this link.(If that link does not work or link is dead, look at this web archive.).

Have a look at this example for android shake detect listener.

Note: SensorListener is deprecated. we can use SensorEventListener instead. Here is a quick example using SensorEventListener.

Thanks.

Android Shake Event

so, thinking about your problem, i was initially considering to "tweak" the constant values of your listener (MIN_FORCE, MIN_TIME... etc) in order to create some "resistance" for the event, so it wouldn't be fired excessively. Then i realized it was a stupid idea, since there is a much better solution... just unbind the event handler when the shake event occurs, and then re-bind it when the user dismisses the dialog. To do this, use the same code provided in the answer you used for the onResume and onPause methods:

this to bind the listener:

    mSensorManager.registerListener(mSensorListener,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);

and this to unbind it:

mSensorManager.unregisterListener(mSensorListener);

Implementing a shake event

I think this might makes things easier for you.

Create a new Class called Shaker and add this.

public class Shaker {
private SensorManager mgr = null;
private long lastShakeTimestamp = 0;
private double threshold = 1.0d;
private long gap = 0;
private Shaker.Callback cb = null;

public Shaker(Context ctxt, double threshold, long gap, Shaker.Callback cb) {
this.threshold = threshold * threshold;
this.threshold = this.threshold * SensorManager.GRAVITY_EARTH
* SensorManager.GRAVITY_EARTH;
this.gap = gap;
this.cb = cb;

mgr = (SensorManager) ctxt.getSystemService(Context.SENSOR_SERVICE);
mgr.registerListener(listener,
mgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);
}

public void close() {
mgr.unregisterListener(listener);
}

private void isShaking() {
long now = SystemClock.uptimeMillis();
try {
if (lastShakeTimestamp == 0) {
lastShakeTimestamp = now;

if (cb != null) {
cb.shakingStarted();
}
} else {
lastShakeTimestamp = now;
}
} catch (NullPointerException e) {

}
}

private void isNotShaking() {
long now = SystemClock.uptimeMillis();

if (lastShakeTimestamp > 0) {
if (now - lastShakeTimestamp > gap) {
lastShakeTimestamp = 0;

if (cb != null) {
cb.shakingStopped();
}
}
}
}

public interface Callback {
void shakingStarted();

void shakingStopped();
}

private final SensorEventListener listener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent e) {
if (e.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
double netForce = e.values[0] * e.values[0];

netForce += e.values[1] * e.values[1];
netForce += e.values[2] * e.values[2];

if (threshold < netForce) {
isShaking();
} else {
isNotShaking();
}
}
}

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

In your Activity implement Shaker.Callback and use the methods shakingStarted() and shakingStopped() to actually do something.



Related Topics



Leave a reply



Submit