Android Fall Detection Issue - java

I'm trying to implement a simple fall detection algorithm using android's accelerometer.
The current acceleration of the phone is stored in mAccel and if a sudden shake is detected Timer t begins. Inside the Timer are two CountDownTimers.
The firstTimer is used to register a "fall" if the user hasn't moved in the last 5 seconds and the secondTimer to confirm that fall if the user hasn't pressed a button (not implemented yet).
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
mGravity = event.values.clone();
float x = mGravity[0];
float y = mGravity[1];
float z = mGravity[2];
mAccelLast = mAccelCurrent;
mAccelCurrent = (float) Math.sqrt(x * x + y * y + z * z);
float delta = mAccelCurrent - mAccelLast;
mAccel = mAccel * 0.9f + delta;
mAccel = abs(mAccel);
textView.setText("a:"+mAccel);
if (abs(mAccel) > 5.0f) { // Shake detection
t();
}
}
}
public void t () {
firstTimer = new CountDownTimer(5000, 1000) { //fall registration timer
#Override
public void onTick(long millisUntilFinished) {
//if there is movement before 5 seconds pass cancel the timer
if (abs(mAccel) > 2.0f) {
firstTimer.cancel();
firstTimer = null;
}
}
#Override
public void onFinish() {
toast.show();
secondTimer = new CountDownTimer(30*1000, 1000) { //fall confirmation timer
#Override
public void onTick(long millisUntilFinished) {
textView2.setText("" + millisUntilFinished / 1000);
}
#Override
public void onFinish() {
Toast toast = Toast.makeText(getApplicationContext(),
"Fall Registered!", Toast.LENGTH_LONG);
toast.show();
}
}.start();
}
}.start();
}
The main issue is that most timesfirstTimer is accessed, it gets cancelled due to the mAccel being over the 2.0 threshold, while it is decelerating.
I tried to use Timer.schedule() to delay the activation of firstTimer until after the acceleration value has "rested" but it won't work with it.

I created a new Timer object mTimer and this seems to work on every case.
CountDownTimer firstTimer = new CountDownTimer(5000, 1000) { //fall registration timer
#Override
public void onTick(long millisUntilFinished) {
//if there is movement before 5 seconds pass cancel the timer
if (abs(mAccel) > 2.0f) {
Toast toast = Toast.makeText(getApplicationContext(),
"Fall not Detected", Toast.LENGTH_SHORT);
toast.show();
firstTimer.cancel();
}
}
#Override
public void onFinish() {
Toast toast = Toast.makeText(getApplicationContext(),
"Fall Detected!", Toast.LENGTH_SHORT);
toast.show();
secondTimer.start();
}
};
CountDownTimer secondTimer = new CountDownTimer(30*1000, 1000) {
//fall confirmation timer
#Override
public void onTick(long millisUntilFinished) {
textView2.setText("" + millisUntilFinished / 1000);
}
#Override
public void onFinish() {
Toast toast = Toast.makeText(getApplicationContext(),
"Fall Registered!", Toast.LENGTH_LONG);
toast.show();
}
};
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
mGravity = event.values.clone();
float x = mGravity[0];
float y = mGravity[1];
float z = mGravity[2];
mAccelLast = mAccelCurrent;
mAccelCurrent = (float) Math.sqrt(x * x + y * y + z * z);
float delta = mAccelCurrent - mAccelLast;
mAccel = mAccel * 0.9f + delta;
mAccel = abs(mAccel);
textView.setText("a:"+mAccel);
if (abs(mAccel) > 5.0f) { // Shake detection
mTimer.schedule(new TimerTask() {
//start after 2 second delay to make acceleration values "rest"
#Override
public void run() {
firstTimer.start();
}
}, 2000);
}
}
}

Related

counter.Cancel(); isn't executed in OnStop(); method

I have a CounterTimer which starts when an Api is successful. if a user presses the KeyEvent.KEYCODE_HOME CounterTimer must cancel but instead of cancelling it keeps running
This is how i start the counter
private void countDownStart(String event_date_time) {
String[] tokens = event_date_time.split(":");
int secondsToMs = Integer.parseInt(tokens[2]) * 1000;
int minutesToMs = Integer.parseInt(tokens[1]) * 60000;
int hoursToMs = Integer.parseInt(tokens[0]) * 3600000;
long total = secondsToMs + minutesToMs + hoursToMs;
timer = new CountDownTimer(total, 1000) {
public void onTick(long millisUntilFinished) {
int seconds = (int) (millisUntilFinished / 1000) % 60;
int minutes = (int) ((millisUntilFinished / (1000 * 60)) % 60);
int hours = (int) ((millisUntilFinished / (1000 * 60 * 60)) % 24);
CountDown.setVisibility(View.VISIBLE);
CountDown.setText(String.format("%02d:%02d:%02d", hours, minutes, seconds));
}
public void onFinish() {
CountDown.setVisibility(View.VISIBLE);
CountDown.setText("00:00:00");
loader.showProgressBar();
startActivity(new Intent(mContext, Questions.class));
}
};
timer.start();
}
and this is what I used to cancel. I've tried with both onStop and KeyEvent.KEYCODE_HOME
#Override
protected void onStop() {
System.out.println("count: onStop Called");
loader.hideProgressBar();
if (timer != null) {
timer.cancel();
}
super.onStop();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_HOME)) {
loader.hideProgressBar();
System.out.println("KEYCODE_HOME");
if (timer != null) {
timer.cancel();
}
return true;
}
return false;
}
What could be possibly wrong here?

How to Animate Text from a Shake Event

I currently have an app that allows the user to shake the phone and different texts appear from an array. However, the text keeps displaying too fast, and if the user keeps shaking the phone, the text keeps changing. How do i do the following:
1) Animate the text so after the phone is shaken, the text appears slowly as a fade?
How do I implement a delay on the shake so that the user has a wait a few seconds before shaking the phone?
I have already implemented this for a button that is clicked, however nothing seems to work with Sensor Manager.
protected final SensorEventListener sensorListener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
float x = sensorEvent.values[0];
float y = sensorEvent.values[1];
float z = sensorEvent.values[2];
acelLast = acelVal;
acelVal = (float) Math.sqrt((double) (x*x + y*y + z*z));
float delta = acelVal - acelLast;
shake = shake * 0.9f + delta;
if (shake > 12) {
int randomNum = new Random().nextInt(answersArray.length);
ball_text.setText(answersArray[randomNum]);
ball_text.setVisibility(View.VISIBLE);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
// Sensor Section //
You'll need to animate your textview's alpha value change.
You'll need to keep track of the last time the user shaked and use that for checking.
Something along the following lines should work,
long previousTime = 0;
protected final SensorEventListener sensorListener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
float x = sensorEvent.values[0];
float y = sensorEvent.values[1];
float z = sensorEvent.values[2];
acelLast = acelVal;
acelVal = (float) Math.sqrt((double) (x*x + y*y + z*z));
float delta = acelVal - acelLast;
shake = shake * 0.9f + delta;
if (shake > 12) {
//Fade in text if difference between previous and current time is > 2 seconds
if (System.currentTimeMillis() - previousTime > 2000) {
previousTime = System.currentTimeMillis();
//Use AlphaAnimation
Animation fadeInAnimation = new AlphaAnimation(0, 1);
fadeInAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
int randomNum = new Random().nextInt(answersArray.length);
ball_text.setText(answersArray[randomNum]);
ball_text.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationEnd(Animation animation) {}
#Override
public void onAnimationRepeat(Animation animation) {}
});
fadeInAnimation.setInterpolator(new DecelerateInterpolator());
fadeInAnimation.setDuration(1000);
ball_text.startAnimation(fadeInAnimation);
/*
//This should work, but it doesn't, I'll prob tinker with it on some weekend, I'll update the answer if I figure out the issue
ball_text.animate()
.withStartAction(new Runnable() {
#Override
public void run() {
int randomNum = new Random().nextInt(answersArray.length);
ball_text.setText(answersArray[randomNum]);
ball_text.setAlpha(0f);
ball_text.setVisibility(View.VISIBLE);
}
})
.alpha(1f)
//Fade in over a duration of 1 second
.setDuration(1000)
.start()
*/
} else {
//If it's less than 2 seconds since last shake, inform user to wait
//For eg,
Toast.makeText(context, "Wait mate", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};

synchronized countdown timer- android development

I have an app that has one countdown timer that should show up the same for every user when they open the app. In order to do this, I have based the time that the users' phones show on Epoch time. I do the following calculations to (what I thought would...) ensure that each phone shows the same time, and that the countdown clock is continuous and accurate. However, every time I open the app up, the clock is at a totally different time, when I think it should be continuously counting down and resetting. What's wrong? I have included my code below:
private static final int COUNTDOWN_DURATION = 30; //time in seconds
private static final long BASE_TIME = 1470729402L; //an arbitrary Epoch time that I have picked as a reference point
private TextView tvTimer;
private Long currentTimeMillis;
private int finalTime;
private boolean firstTime;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState)
//set up basics
...
//set up timer
tvTimer = (TextView) findViewById(R.id.tvTimer);
firstTime = true;
setCurrentTime();
}
private void setCurrentTime() {
currentTimeMillis = System.currentTimeMillis();
long currentTimeSecs = currentTimeMillis/1000;
long timeDiff = currentTimeSecs - BASE_TIME;
//determines what spot the countdown timer is at when the app is started
finalTime = (int) (timeDiff % COUNTDOWN_DURATION);
resetTimer();
}
public void resetTimer(){
if (firstTime) {
CountDownTimer countDownTimer = new CountDownTimer(finalTime * 1000, 1000) {
public void onTick(long millisUntilFinished) {
tvTimer.setText(" " + millisUntilFinished / 1000 + " ");
}
public void onFinish() {
resetTimer();
}
};
countDownTimer.start();
firstTime = false;
}
else {
CountDownTimer countDownTimer = new CountDownTimer(COUNTDOWN_DURATION * 1000, 1000) {
public void onTick(long millisUntilFinished) {
tvTimer.setText(" " + millisUntilFinished / 1000 + " ");
}
public void onFinish() {
resetTimer();
}
};
countDownTimer.start();
}
}

disable a thread on click

I am working on app that calculate time when specific app run, to save ram, I want to stop some of the threads by using check box. i want a command when I press the check box the thread stops even "if condition" is right"
the if conditon of detecting app :
if (MainActivity.tgbutton.isChecked())
{
if (packageName.equals("com.facebook.katana"))
{
if (f==1)
{
}
else
{
// Toast.makeText(getApplicationContext(),"fb on", Toast.LENGTH_SHORT).show();
f=1;
facebook = true;
startTimef = SystemClock.uptimeMillis();
customHandlerf.postDelayed(updateTimerThreadfacebook, 0);
}
}
else
{
if(f==1)
{
//Toast.makeText(getApplicationContext(),"fb off", Toast.LENGTH_SHORT).show();
facebook = false;
timeSwapBufff += timeInMillisecondsf;
customHandlerf.removeCallbacks(updateTimerThreadfacebook);
f=2;
}
}
}
the check box :
blabla.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (((CheckBox) v).isChecked()) {
// what to write here to disable thread???
}
}
});
the thread itself :
private Runnable updateTimerThreadfacebook = new Runnable() {
public void run() {
if (facebook = true)
{
timeInMillisecondsf = SystemClock.uptimeMillis() - startTimef;
updatedTimef = timeSwapBufff + timeInMillisecondsf;
int secsf = (int) (updatedTimef / 1000);
int minsf = secsf / 60;
secsf = secsf % 60;
MainActivity.facebook.setText("" + minsf + ":" + String.format("%02d", secsf));
customHandlerf.postDelayed(this, 0);
}
}
};
you should use value on your run method
public class MyClass implements Runnable{
boolean signal=false;
public setisFinish(boolean sig)
{
signal = sig;
}
#Override
public void run()
{
if(!signal)
//Do SomeThing
}
public void foo()
{
System.out.println("foo");
}
}
and in your click listener
blabla.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (((CheckBox) v).isChecked()) {
myThread.setisFinish(true);
}
}
});
this code resume your thread and you can start it whenever you whant and if you want interrupt your thread use this code
myThread.interrupt();
Overwrap your Runnable object with Thread class:
private Thread updateTimerThreadfacebook = new Thread(new Runnable() {
public void run() {
if (facebook = true) {
timeInMillisecondsf = SystemClock.uptimeMillis() - startTimef;
updatedTimef = timeSwapBufff + timeInMillisecondsf;
int secsf = (int) (updatedTimef / 1000);
int minsf = secsf / 60;
secsf = secsf % 60;
MainActivity.facebook.setText("" + minsf + ":" + String.format("%02d", secsf));
customHandlerf.postDelayed(this, 0);
}
}
});
when you want to stop it use interrupt method.
updateTimerThreadfacebook.interrupt();

How to detect shake event [duplicate]

How can I detect a shake event with android? How can I detect the shake direction?
I want to change the image in an imageview when shaking occurs.
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.
Google helps a lot.
/* The following code was written by Matthew Wiggins
* and is released under the APACHE 2.0 license
*
* http://www.apache.org/licenses/LICENSE-2.0
*/
package com.hlidskialf.android.hardware;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.content.Context;
import java.lang.UnsupportedOperationException;
public class ShakeListener implements SensorListener
{
private static final int FORCE_THRESHOLD = 350;
private static final int TIME_THRESHOLD = 100;
private static final int SHAKE_TIMEOUT = 500;
private static final int SHAKE_DURATION = 1000;
private static final int SHAKE_COUNT = 3;
private SensorManager mSensorMgr;
private float mLastX=-1.0f, mLastY=-1.0f, mLastZ=-1.0f;
private long mLastTime;
private OnShakeListener mShakeListener;
private Context mContext;
private int mShakeCount = 0;
private long mLastShake;
private long mLastForce;
public interface OnShakeListener
{
public void onShake();
}
public ShakeListener(Context context)
{
mContext = context;
resume();
}
public void setOnShakeListener(OnShakeListener listener)
{
mShakeListener = listener;
}
public void resume() {
mSensorMgr = (SensorManager)mContext.getSystemService(Context.SENSOR_SERVICE);
if (mSensorMgr == null) {
throw new UnsupportedOperationException("Sensors not supported");
}
boolean supported = mSensorMgr.registerListener(this, SensorManager.SENSOR_ACCELEROMETER, SensorManager.SENSOR_DELAY_GAME);
if (!supported) {
mSensorMgr.unregisterListener(this, SensorManager.SENSOR_ACCELEROMETER);
throw new UnsupportedOperationException("Accelerometer not supported");
}
}
public void pause() {
if (mSensorMgr != null) {
mSensorMgr.unregisterListener(this, SensorManager.SENSOR_ACCELEROMETER);
mSensorMgr = null;
}
}
public void onAccuracyChanged(int sensor, int accuracy) { }
public void onSensorChanged(int sensor, float[] values)
{
if (sensor != SensorManager.SENSOR_ACCELEROMETER) return;
long now = System.currentTimeMillis();
if ((now - mLastForce) > SHAKE_TIMEOUT) {
mShakeCount = 0;
}
if ((now - mLastTime) > TIME_THRESHOLD) {
long diff = now - mLastTime;
float speed = Math.abs(values[SensorManager.DATA_X] + values[SensorManager.DATA_Y] + values[SensorManager.DATA_Z] - mLastX - mLastY - mLastZ) / diff * 10000;
if (speed > FORCE_THRESHOLD) {
if ((++mShakeCount >= SHAKE_COUNT) && (now - mLastShake > SHAKE_DURATION)) {
mLastShake = now;
mShakeCount = 0;
if (mShakeListener != null) {
mShakeListener.onShake();
}
}
mLastForce = now;
}
mLastTime = now;
mLastX = values[SensorManager.DATA_X];
mLastY = values[SensorManager.DATA_Y];
mLastZ = values[SensorManager.DATA_Z];
}
}
}
You can also take a look on library Seismic
public class Demo extends Activity implements ShakeDetector.Listener {
#Override protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
ShakeDetector sd = new ShakeDetector(this);
// A non-zero delay is required for Android 12 and up (https://github.com/square/seismic/issues/24)
int sensorDelay = SensorManager.SENSOR_DELAY_GAME
sd.start(sensorManager, sensorDelay);
TextView tv = new TextView(this);
tv.setGravity(CENTER);
tv.setText("Shake me, bro!");
setContentView(tv, new LayoutParams(MATCH_PARENT, MATCH_PARENT));
}
#Override public void hearShake() {
Toast.makeText(this, "Don't shake me, bro!", Toast.LENGTH_SHORT).show();
}
}
There are a lot of solutions to this question already, but I wanted to post one that:
Doesn't use a library depricated in API 3
Calculates the magnitude of the acceleration correctly
Correctly applies a timeout between shake events
Here is such a solution:
// variables for shake detection
private static final float SHAKE_THRESHOLD = 3.25f; // m/S**2
private static final int MIN_TIME_BETWEEN_SHAKES_MILLISECS = 1000;
private long mLastShakeTime;
private SensorManager mSensorMgr;
To initialize the timer:
// Get a sensor manager to listen for shakes
mSensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE);
// Listen for shakes
Sensor accelerometer = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
if (accelerometer != null) {
mSensorMgr.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
SensorEventListener methods to override:
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
long curTime = System.currentTimeMillis();
if ((curTime - mLastShakeTime) > MIN_TIME_BETWEEN_SHAKES_MILLISECS) {
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
double acceleration = Math.sqrt(Math.pow(x, 2) +
Math.pow(y, 2) +
Math.pow(z, 2)) - SensorManager.GRAVITY_EARTH;
Log.d(APP_NAME, "Acceleration is " + acceleration + "m/s^2");
if (acceleration > SHAKE_THRESHOLD) {
mLastShakeTime = curTime;
Log.d(APP_NAME, "Shake, Rattle, and Roll");
}
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Ignore
}
When you are all done
// Stop listening for shakes
mSensorMgr.unregisterListener(this);
Since SensorListener is deprecated so use the following code:
/* 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();
}
Then:
/* 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;
The question with full details could be found here:
Android: I want to shake it
This is for Kotlin and use SensorEventListener
Create new class ShakeDetector
class ShakeDetector : SensorEventListener {
private var mListener: OnShakeListener? = null
private var mShakeTimestamp: Long = 0
private var mShakeCount = 0
fun setOnShakeListener(listener: OnShakeListener?) {
mListener = listener
}
interface OnShakeListener {
fun onShake(count: Int)
}
override fun onAccuracyChanged(
sensor: Sensor,
accuracy: Int
) { // ignore
}
override fun onSensorChanged(event: SensorEvent) {
if (mListener != null) {
val x = event.values[0]
val y = event.values[1]
val z = event.values[2]
val gX = x / SensorManager.GRAVITY_EARTH
val gY = y / SensorManager.GRAVITY_EARTH
val gZ = z / SensorManager.GRAVITY_EARTH
// gForce will be close to 1 when there is no movement.
val gForce: Float = sqrt(gX * gX + gY * gY + gZ * gZ)
if (gForce > SHAKE_THRESHOLD_GRAVITY) {
val now = System.currentTimeMillis()
// ignore shake events too close to each other (500ms)
if (mShakeTimestamp + SHAKE_SLOP_TIME_MS > now) {
return
}
// reset the shake count after 3 seconds of no shakes
if (mShakeTimestamp + SHAKE_COUNT_RESET_TIME_MS < now) {
mShakeCount = 0
}
mShakeTimestamp = now
mShakeCount++
mListener!!.onShake(mShakeCount)
}
}
}
companion object {
/*
* The gForce that is necessary to register as shake.
* Must be greater than 1G (one earth gravity unit).
* You can install "G-Force", by Blake La Pierre
* from the Google Play Store and run it to see how
* many G's it takes to register a shake
*/
private const val SHAKE_THRESHOLD_GRAVITY = 2.7f
private const val SHAKE_SLOP_TIME_MS = 500
private const val SHAKE_COUNT_RESET_TIME_MS = 3000
}
}
Your main Activity
class MainActivity : AppCompatActivity() {
// The following are used for the shake detection
private var mSensorManager: SensorManager? = null
private var mAccelerometer: Sensor? = null
private var mShakeDetector: ShakeDetector? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initSensor()
}
override fun onResume() {
super.onResume()
// Add the following line to register the Session Manager Listener onResume
mSensorManager!!.registerListener(
mShakeDetector,
mAccelerometer,
SensorManager.SENSOR_DELAY_UI
)
}
override fun onPause() { // Add the following line to unregister the Sensor Manager onPause
mSensorManager!!.unregisterListener(mShakeDetector)
super.onPause()
}
private fun initSensor() {
// ShakeDetector initialization
// ShakeDetector initialization
mSensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
mAccelerometer = mSensorManager!!.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
mShakeDetector = ShakeDetector()
mShakeDetector!!.setOnShakeListener(object : OnShakeListener {
override fun onShake(count: Int) { /*
* The following method, "handleShakeEvent(count):" is a stub //
* method you would use to setup whatever you want done once the
* device has been shook.
*/
Toast.makeText(this#MainActivity, count.toString(), Toast.LENGTH_SHORT).show()
}
})
}
}
Finally add this code to Manifests to make sure the phone has an accelerometer
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
You can use Seismic:
See the code here:
https://github.com/square/seismic/blob/master/library/src/main/java/com/squareup/seismic/ShakeDetector.java
Do the following:
private float xAccel, yAccel, zAccel;
private float xPreviousAccel, yPreviousAccel, zPreviousAccel;
private boolean firstUpdate = true;
private final float shakeThreshold = 1.5f;
private boolean shakeInitiated = false;
SensorEventListener mySensorEventListener;
SensorManager mySensorManager;
Put this in onCreate method.
mySensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mySensorManager.registerListener(mySensorEventListener,
mySensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
And now the main part.
private boolean isAccelerationChanged() {
float deltaX = Math.abs(xPreviousAccel - xAccel);
float deltaY = Math.abs(yPreviousAccel - yAccel);
float deltaZ = Math.abs(zPreviousAccel - zAccel);
return (deltaX > shakeThreshold && deltaY > shakeThreshold)
|| (deltaX > shakeThreshold && deltaZ > shakeThreshold)
|| (deltaY > shakeThreshold && deltaZ > shakeThreshold);
}
private void updateAccelParameters(float xNewAccel, float yNewAccel, float zNewAccel) {
if (firstUpdate) {
xPreviousAccel = xNewAccel;
yPreviousAccel = yNewAccel;
zPreviousAccel = zNewAccel;
firstUpdate = false;
}else{
xPreviousAccel = xAccel;
yPreviousAccel = yAccel;
zPreviousAccel = zAccel;
}
xAccel = xNewAccel;
yAccel = yNewAccel;
zAccel = zNewAccel;
}
private void executeShakeAction() {
//this method is called when devices shakes
}
public void onSensorChanged(SensorEvent se) {
updateAccelParameters(se.values[0], se.values[1], se.values[2]);
if ((!shakeInitiated) && isAccelerationChanged()) {
shakeInitiated = true;
}else if ((shakeInitiated) && isAccelerationChanged()){
executeShakeAction();
}else if((shakeInitiated) && (!isAccelerationChanged())){
shakeInitiated = false;
}
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
//setting the accuracy
}
Dont forget to add this code in your MainActivity.java:
MainActivity.java
mShaker = new ShakeListener(this);
mShaker.setOnShakeListener(new ShakeListener.OnShakeListener () {
public void onShake() {
Toast.makeText(MainActivity.this, "Shake " , Toast.LENGTH_LONG).show();
}
});
#Override
protected void onResume() {
super.onResume();
mShaker.resume();
}
#Override
protected void onPause() {
super.onPause();
mShaker.pause();
}
Or I give you a link about this stuff.

Categories