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
Check If Application Is Installed - Android
How to Install an Apk File in the Android Emulator
Android Spinner: Get the Selected Item Change Event
Force "Portrait" Orientation Mode
Notification Icon with the New Firebase Cloud Messaging System
How to Use Opencv in Using Gradle
Changing the Background Drawable of the Searchview Widget
Eclipse Error: R Cannot Be Resolved to a Variable
Is There a Broadcast Action for Volume Changes
Separate Back Stack For Each Tab in Android Using Fragments
Android Starting Service At Boot Time , How to Restart Service Class After Device Reboot
Android: How to Validate Edittext Input
How to Get the Resource Id of an Image If I Know Its Name
Deleting a Gallery Image After Camera Intent Photo Taken