I wrote an Android Application to measure acceleration in y-direction. The sensor values are being processed by a thread to keep my UI responsive.
This is my thread:
public class SensorThread extends Thread implements SensorEventListener {
private Context context;
private SensorManager sensorManager;
private Sensor accelerometer;
private long lastUpdate;
private long startTime;
private final float RC = 150.0f;
float accel_y_smoothed = 1000000f;
float raw_y = 0f;
private Handler handler;
public SensorThread(Context context, Handler handler) {
this.context = context;
this.handler = handler;
sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_FASTEST);
startTime = System.currentTimeMillis();
lastUpdate = System.currentTimeMillis();
}
public void run() {
}
#Override
public void onSensorChanged(SensorEvent event) {
// Gather Sensor data
raw_y = event.values[1];
if (System.currentTimeMillis() - lastUpdate > 10) {
// Filter Sensor data
float timeInterval = System.currentTimeMillis() - lastUpdate;
//plot_raw.addValue(accel_y, startTime - System.currentTimeMillis());
float alpha = timeInterval / (RC + timeInterval);
if (accel_y_smoothed == 1000000f) {
accel_y_smoothed = raw_y;
} else {
accel_y_smoothed = alpha * raw_y + (1 - alpha) * accel_y_smoothed;
}
//plot.addValue(accel_y_smoothed, startTime - System.currentTimeMillis());
lastUpdate = System.currentTimeMillis();
Message message = handler.obtainMessage(0);
Bundle bundle = new Bundle();
bundle.putFloat("smoothed_y", accel_y_smoothed);
bundle.putFloat("raw_y", raw_y);
bundle.putLong("timestamp", startTime - System.currentTimeMillis());
message.setData(bundle);
handler.sendMessage(message);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void stopThread() {
sensorManager.unregisterListener(this);
}
public void resumeThread() {
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_FASTEST);
}
public void calibrate() {
long startCalibrationTime = System.currentTimeMillis() + 500;
ArrayList<Float> calibration_values = new ArrayList<Float>();
long lastUpdateCalibration = 0;
while (System.currentTimeMillis() - startCalibrationTime + 500 < 1000) {
if (lastUpdateCalibration != lastUpdate) {
calibration_values.add(raw_y);
}
}
float mean = 0.0f;
for (int i = 0; i < calibration_values.size(); i++) {
mean += calibration_values.get(i);
}
mean = mean / calibration_values.size();
Message message = handler.obtainMessage(1);
Bundle bundle = new Bundle();
bundle.putFloat("y_offset", mean);
message.setData(bundle);
handler.sendMessage(message);
}
}
Now I implemented a calibrate() function to measure the mean offset when the phone is lying still on a table for example. The problem is, when I call this function from my main thread, it blocks the UI.
sensorThread.calibrate(); is called from my main thread on my instance of sensorThread which was created when the main activity started.
How do I properly call this function to not block my UI?
As zapl correctly stated:
A method is executed in the thread it was called from, not in which class it's source is.
So I used a message to let my Thread now I require a new calibration. This works fine for me.
Related
My code :
#Override
public void onSensorChanged(SensorEvent event) {
float f1 = event.values[0];
float f2 = event.values[1];
float f3 = event.values[2];
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Toast.makeText(context,"10 second",Toast.LENGTH_SHORT).show();
new Handler().postDelayed(this, 10000);
}
}, 10000);
this.LastX = event.values[0];
this.LastY = event.values[1];
this.LastZ = event.values[2];
float f4 = Math.abs(this.LastX - f1);
float f5 = Math.abs(this.LastY - f2);
float f6 = Math.abs(this.LastZ - f3);
if(f4<0.003 && f5<0.003 && f6<0.003){
MainActivity.LockState = true;
// Toast.makeText(context,"Düz zemin",Toast.LENGTH_LONG).show();
}
}
I'm trying to compare sensor data every 10 second but postDelayed function does only work first time.After this the toast message is spamming.
You can simply get timestamp from SensorEvent and check if there is 10 seconds difference between the last and current timestamps.
For example:
private SensorEventListener sensorEventListener = new SensorEventListener() {
private long lastTimestamp;
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
long currentTimestamp = sensorEvent.timestamp;
if (currentTimestamp - lastTimestamp >= TimeUnit.SECONDS.toNanos(10)) {
lastTimestamp = currentTimestamp;
Toast.makeText(mContext, "10 seconds", Toast.LENGTH_SHORT).show();
//Here you can compare sensor data
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
I have this swapAnimation method which basically swaps two views. I call this method inside a loop and pass different views on the swapAnimation method each time. But the problem is the animation happens only once. I want it to repeat n number of times.
void swapAnimation(View v1,View v2){
if(isAnimating)return;
isAnimating = true;
float x1,y1,x2,y2;
x1 =getRelativeX(v1);
x2 = getRelativeX(v2);
y1 = getRelativeY(v1);
y2 = getRelativeY(v2);
float x_displacement = (x2-x1);
float y_displacement = (y2-y1);
v1.animate().xBy(x_displacement).yBy(y_displacement);
v2.animate().xBy(-x_displacement).yBy(-y_displacement);
v1.animate().setDuration(500);
v2.animate().setDuration(500);
long duration = v1.animate().getDuration();
new CountDownTimer(duration+10,duration+10){
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
isAnimating = false;
}
}.start();
}
public static void arrange(LinearLayout container, Context context){
MainActivity activity = (MainActivity) context;
for(int i=0;i<container.getChildCount();i++){
BarView v1 = (BarView) container.getChildAt(i);
for(int j=i;j<container.getChildCount();j++){
BarView v2 = (BarView) container.getChildAt(j);
if(v1.getWeight() > v2.getWeight()){
Log.d(TAG, "bubbleSort: "+v1.getWeight()+">"+v2.getWeight());
activity.swapAnimation(v1,v2);
}
}
}
}
Try this
animation.setRepeatCount(Animation.INFINITE);
In android studio in the MainActivity in the onCreate i did:
timerValueRecord = (TextView) findViewById(R.id.timerValueRecord);
In strings.xml i added:
<string name="timerValRecord">Recording Time: 00:00:00</string>
In activity_main.xml i added:
<TextView
android:id="#+id/timerValueRecord"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textSize="20sp"
android:textColor="#000000"
android:layout_marginTop="315dp"
android:text="#string/timerValRecord" />
In the activity_main designer it looks like:
In the MainActivity i have a touch event:
#Override
public boolean onTouchEvent(MotionEvent event)
{
float eventX = event.getX();
float eventY = event.getY();
float lastdownx = 0;
float lastdowny = 0;
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
lastdownx = eventX;
lastdowny = eventY;
Thread t = new Thread(new Runnable()
{
#Override
public void run()
{
byte[] response = null;
if (connectedtoipsuccess == true)
{
if (is_start == true)
{
response = Get(iptouse + "start");
is_start = false;
} else
{
textforthespeacch = "Recording stopped and preparing the file to be shared on youtube";
MainActivity.this.initTTS();
response = Get(iptouse + "stop");
is_start = true;
startuploadstatusthread = true;
servercheckCounter = 0;
}
if (response != null)
{
try
{
a = new String(response, "UTF-8");
MainActivity.this.runOnUiThread(new Runnable()
{
#Override
public void run()
{
if (a.equals("Recording started"))
{
status1.setText("Recording");
}
if (a.equals("Recording stopped and preparing the file to be shared on youtube"))
{
status1.setText("Recording Stopped");
}
}
});
textforthespeacch = a;
MainActivity.this.initTTS();
} catch (UnsupportedEncodingException e)
{
e.printStackTrace();
}
Logger.getLogger("MainActivity(inside thread)").info(a);
}
}
}
});
t.start();
return true;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
default:
return false;
}
return true;
}
What i want to do is when in the touch event it's true after this line:
if (is_start == true)
Start the timer and display on the timerValueRecord the time running including milliseconds seconds and minutes until the user touch again and then it's getting to the stop part and then to stop the timer.
The problem is how to build the timer at all and how to stop and start it.
You can try this below Code:
public class ShowTimer {
private long startTime = 0L;
private Handler customHandler = new Handler();
long timeInMilliseconds = 0L;
long timeSwapBuff = 0L;
long updatedTime = 0L;
public void StartTimer() {
startTime = SystemClock.uptimeMillis();
customHandler.postDelayed(updateTimerThread, 0);
}
public void StopTimer() {
timeSwapBuff += timeInMilliseconds;
customHandler.removeCallbacks(updateTimerThread);
}
private Runnable updateTimerThread = new Runnable() {
public void run() {
timeInMilliseconds = SystemClock.uptimeMillis() - startTime;
updatedTime = timeSwapBuff + timeInMilliseconds;
int secs = (int) (timeInMilliseconds / 1000);
int mins = secs / 60;
secs = secs % 60;
int hours = mins / 60;
mins = mins % 60;
//int milliseconds = (int) (updatedTime % 1000);
//+ ":" + String.format("%03d", milliseconds)
String timer = "" + String.format("%02d", hours) + ":" + String.format("%02d", mins) + ":" + String.format("%02d", secs);
//set yout textview to the String timer here
customHandler.postDelayed(this, 1000);
}
};
You can use StartTimer() and StopTimer() function where you want to start or stop the timer:
try this way
public class AndroidTimerTaskExample extends Activity {
Timer timer;
TimerTask timerTask;
//we are going to use a handler to be able to run in our TimerTask
final Handler handler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
protected void onResume() {
super.onResume();
//onResume we start our timer so it can start when the app comes from the background
startTimer();
}
public void startTimer() {
//set a new Timer
timer = new Timer();
//initialize the TimerTask's job
initializeTimerTask();
//schedule the timer, after the first 5000ms the TimerTask will run every 10000ms
timer.schedule(timerTask, 5000, 10000); //
}
public void stoptimertask(View v) {
//stop the timer, if it's not already null
if (timer != null) {
timer.cancel();
timer = null;
}
}
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
//use a handler to run a toast that shows the current timestamp
handler.post(new Runnable() {
public void run() {
//get the current timeStamp
Calendar calendar = Calendar.getInstance();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd:MMMM:yyyy HH:mm:ss a");
final String strDate = simpleDateFormat.format(calendar.getTime());
//show the toast
int duration = Toast.LENGTH_SHORT;
Toast toast = Toast.makeText(getApplicationContext(), strDate, duration);
toast.show();
}
});
}
};
}
}
I'm making an app that tracks exercise movements based on orientation and accelerometer readings(the exercise movements are very slow). What I have is a strategy pattern kind of a situation where I have an abstract class for exercise movement and the concrete exercise movements implement the actual thing. Problem is, I am spawning threads to track different exercises in the onSensorChanged() method in my activity. since this is going to be called a lot of times, I don't know if my code will spawn as many threads. Do they get garbage collected?
Code:
public class WorkoutBuddy extends Activity implements SensorEventListener {
TextView t1, t2, t3, t4, t5, t6, t7;
SensorManager sensorManager;;
private Sensor sensorAccelerometer;
private Sensor sensorMagneticField;
private float[] valuesAccelerometer;
private float[] valuesMagneticField;
private float[] valuesOrientation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.exercise_buddy);
sensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
sensorAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorMagneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
valuesAccelerometer = new float[3];
valuesMagneticField = new float[3];
valuesOrientation = new float[3];
matrixR = new float[9];
matrixI = new float[9];
matrixValues = new float[3];
//mediaPlayer = MediaPlayer.create(this, R.raw.first_position_confirmation);
}
#Override
protected void onPause() {
sensorManager.unregisterListener(this,sensorAccelerometer);
sensorManager.unregisterListener(this,sensorMagneticField);
super.onPause();
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
float[] orientation;
private float[] matrixR;
private float[] matrixI;
private float[] matrixValues;
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
valuesAccelerometer = lowPass(event.values.clone(), valuesAccelerometer);
} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
valuesMagneticField = lowPass(event.values.clone(), valuesMagneticField);
}
if (valuesAccelerometer != null && valuesMagneticField != null) {
SensorManager.getRotationMatrix(matrixR, matrixI, valuesAccelerometer, valuesMagneticField);
if(true){
SensorManager.getOrientation(matrixR, matrixValues);
double azimuth = Math.toDegrees(matrixValues[0]);
double pitch = Math.toDegrees(matrixValues[1]);
double roll = Math.toDegrees(matrixValues[2]);
valuesOrientation[0]=(float) pitch;
valuesOrientation[1]=(float) roll;
valuesOrientation[0]=(float) azimuth;
Thread forExc1 = new Thread(new LeftShoulder(valuesAccelerometer, valuesOrientation, this));
Thread forExc2 = new Thread(new RightShoulder(valuesAccelerometer, valuesOrientation, this));
forExc1.run();
forExc2.run();
}
}
}
#Override
protected void onResume() {
sensorManager.registerListener(this,sensorAccelerometer,SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this,sensorMagneticField,SensorManager.SENSOR_DELAY_NORMAL);
super.onResume();
}
//Low pass filter used to smooth the sensor readings
protected float[] lowPass( float[] input, float[] output ) {
float ALPHA = 0.25f;
if ( output == null ) return input;
for ( int i=0; i<input.length; i++ ) {
output[i] = output[i] + ALPHA * (input[i] - output[i]);
}
return output;
}
}
package com.example.msapp2;
public abstract class ExerciseMovement implements Runnable{
protected float[] acc, ori;
protected boolean played = false;
}
package com.example.msapp2;
import android.content.Context;
import android.media.MediaPlayer;
public class LeftShoulder extends ExerciseMovement {
MediaPlayer mediaPlayer;
public LeftShoulder(float[] accelerometer, float[] orientation, Context context){
mediaPlayer = MediaPlayer.create(context, R.raw.first_position_confirmation);
acc = accelerometer;
//this.ori = orientation;
}
public void run(){
if(acc[0]> -10 && acc[0] < -8.5 && !played){
mediaPlayer.start();
played = true;
}
}
}
If you just override OnSensorChanged and output a Log.d , you'll see it's called hundreds, if not thousands, of times per second.
I suggest you the opposite approach: Create just one thread to process in background the different received events, then feed such thread from onSensorChanged.
Implement kind of an event queue in the thread. Assume thousands of events will arrive, constantly.
SOmething like:
private class ShoulderMovementProcessorThread extends Thread {
.....
// this will be called from the UI thread, just add event to the (synchronized) queue.
public void publish (int[] valuesAccelerometer, int[] valuesWhatever) {
add_event_to_queue();
}
// this is the typical event loop where you read one from the queue, process it, then wait for the next
public void run() {
-> get event
-> process event
-> wait for next event
}
}
ShoulderMovementProcessorThread mShoulderProcessor=new ShoulderMovementProcessorThread(...);
#Override
public void onSensorChanged(SensorEvent event) {
decodeEvent (event); // fills up azimuth, roll, etc.
mShoulderProcessor.publish(valuesAccelerometer, valuesWhatever);
}
// decode an event
private void decodeEvent (SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
valuesAccelerometer = lowPass(event.values.clone(), valuesAccelerometer);
} else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
valuesMagneticField = lowPass(event.values.clone(), valuesMagneticField);
}
if (valuesAccelerometer != null && valuesMagneticField != null) {
SensorManager.getRotationMatrix(matrixR, matrixI, valuesAccelerometer, valuesMagneticField);
if(true){
SensorManager.getOrientation(matrixR, matrixValues);
double azimuth = Math.toDegrees(matrixValues[0]);
double pitch = Math.toDegrees(matrixValues[1]);
double roll = Math.toDegrees(matrixValues[2]);
valuesOrientation[0]=(float) pitch;
valuesOrientation[1]=(float) roll;
valuesOrientation[0]=(float) azimuth;
}
}
}
I implemented something similar recently:
public class DBWorkerThread implements Runnable
{
private SensorEnum sensorType;
private LinkedBlockingQueue<float[]> sensorData;
private DBService dbService;
public DBWorkerThread(SensorEnum type, DBService dbService)
{
this.sensorType = type;
this.dbService = dbService;
this.sensorData = new LinkedBlockingQueue<float[]>();
}
/**
* Add data to queue
* #param values
*/
public void addDataToProcess(float[] values)
{
if (sensorData.size() < sensorData.remainingCapacity())
{
try
{
this.sensorData.put(values);
}
catch (Exception ex)
{
LogService.log("Error adding queue: " + ex.getMessage());
}
LogService.log("Added to queue. Size: " + sensorData.size());
}
}
/**
* Processes queue of data
*/
#Override
public void run()
{
// Moves the current Thread into the background
android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
while (sensorData.size() > 0)
{
try
{
float[] values = sensorData.take();
storeData(values);
}
catch (Exception ex)
{
LogService.log("Error in queue: " + ex.getMessage());
}
}
}
/**
* Store data to database
* #param values
*/
private void storeData(float[] values)
{
// store data
}
}
Hopes this helps
I want to use the accelerometer sensor to keep track when a user makes sudden moves.
This service should be started via activity and keep running indefinitely even if application is terminated (exits).
Currently everything works fine while app is alive, once the app closed, i can still see the service runs but i don't get any signals from him anymore.
Can someone help keep the service alive with signals?
Please look at the code i have.
MainActivity.java
public class MainActivity extends ActionBarActivity implements CordovaInterface {
private boolean mAlternateTitle = false;
private boolean bound;
private boolean volumeupBound;
private boolean volumedownBound;
String TAG = "MainActivity-ActionBarTest";
private IPlugin activityResultCallback;
private Object activityResultKeepRunning;
private Object keepRunning;
CordovaWebView mainView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//startService(new Intent(getBaseContext(), FirstService.class));
startService(new Intent(getApplicationContext(), MainAccelerometer.class));
mainView = (CordovaWebView) findViewById(R.id.mainView);
mainView.loadUrl("file:///android_asset/www/index.html");
}
MainAccelerometer.java
public class MainAccelerometer extends Service implements AccelerometerListener{
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
public IBinder onBind(Intent arg0)
{
return null;
}
public void onCreate() {
super.onCreate();
//Check device supported Accelerometer senssor or not
if (AccelerometerManager.isSupported(getApplicationContext())) {
//Start Accelerometer Listening
AccelerometerManager.startListening(this);
}
}
public void onAccelerationChanged(float x, float y, float z) {
// TODO Auto-generated method stub
}
public void onShake(float force) {
// Called when Motion Detected
//Toast.makeText(getBaseContext(), "Motion detected", Toast.LENGTH_SHORT).show();
Log.d("Test", "shake");
}
#Override
public void onDestroy() {
super.onDestroy();
Log.i("Sensor", "Service distroy");
//Check device supported Accelerometer senssor or not
if (AccelerometerManager.isListening()) {
//Start Accelerometer Listening
AccelerometerManager.stopListening();
//Toast.makeText(getBaseContext(), "onDestroy Accelerometer Stoped", Toast.LENGTH_LONG).show();
}
}
}
AccelerometerManager.java
public class AccelerometerManager {
private static Context aContext=null;
/** Accuracy configuration */
private static float threshold = 20.0f;
private static int interval = 2000;
private static Sensor sensor;
private static SensorManager sensorManager;
// you could use an OrientationListener array instead
// if you plans to use more than one listener
private static AccelerometerListener listener;
/** indicates whether or not Accelerometer Sensor is supported */
private static Boolean supported;
/** indicates whether or not Accelerometer Sensor is running */
private static boolean running = false;
/**
* Returns true if the manager is listening to orientation changes
*/
public static boolean isListening() {
return running;
}
/**
* Unregisters listeners
*/
public static void stopListening() {
running = false;
try {
if (sensorManager != null && sensorEventListener != null) {
sensorManager.unregisterListener(sensorEventListener);
}
} catch (Exception e) {}
}
/**
* Returns true if at least one Accelerometer sensor is available
*/
public static boolean isSupported(Context context) {
aContext = context;
if (supported == null) {
if (aContext != null) {
sensorManager = (SensorManager) aContext.
getSystemService(Context.SENSOR_SERVICE);
// Get all sensors in device
List<Sensor> sensors = sensorManager.getSensorList(
Sensor.TYPE_ACCELEROMETER);
supported = new Boolean(sensors.size() > 0);
} else {
supported = Boolean.FALSE;
}
}
return supported;
}
/**
* Configure the listener for shaking
* #param threshold
* minimum acceleration variation for considering shaking
* #param interval
* minimum interval between to shake events
*/
public static void configure(int threshold, int interval) {
AccelerometerManager.threshold = threshold;
AccelerometerManager.interval = interval;
}
/**
* Registers a listener and start listening
* #param accelerometerListener
* callback for accelerometer events
*/
public static void startListening( AccelerometerListener accelerometerListener )
{
sensorManager = (SensorManager) aContext.
getSystemService(Context.SENSOR_SERVICE);
// Take all sensors in device
List<Sensor> sensors = sensorManager.getSensorList(
Sensor.TYPE_ACCELEROMETER);
if (sensors.size() > 0) {
sensor = sensors.get(0);
// Register Accelerometer Listener
running = sensorManager.registerListener(
sensorEventListener, sensor,
SensorManager.SENSOR_DELAY_GAME);
listener = accelerometerListener;
}
}
/**
* Configures threshold and interval
* And registers a listener and start listening
* #param accelerometerListener
* callback for accelerometer events
* #param threshold
* minimum acceleration variation for considering shaking
* #param interval
* minimum interval between to shake events
*/
public static void startListening(
AccelerometerListener accelerometerListener,
int threshold, int interval) {
configure(threshold, interval);
startListening(accelerometerListener);
}
/**
* The listener that listen to events from the accelerometer listener
*/
private static SensorEventListener sensorEventListener =
new SensorEventListener() {
private long now = 0;
private long timeDiff = 0;
private long lastUpdate = 0;
private long lastShake = 0;
private float x = 0;
private float y = 0;
private float z = 0;
private float lastX = 0;
private float lastY = 0;
private float lastZ = 0;
private float force = 0;
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
public void onSensorChanged(SensorEvent event) {
// use the event timestamp as reference
// so the manager precision won't depends
// on the AccelerometerListener implementation
// processing time
now = event.timestamp;
x = event.values[0];
y = event.values[1];
z = event.values[2];
// if not interesting in shake events
// just remove the whole if then else block
if (lastUpdate == 0) {
lastUpdate = now;
lastShake = now;
lastX = x;
lastY = y;
lastZ = z;
Toast.makeText(aContext,"No Motion detected", Toast.LENGTH_SHORT).show();
} else {
timeDiff = now - lastUpdate;
if (timeDiff > 0) {
/*force = Math.abs(x + y + z - lastX - lastY - lastZ)
/ timeDiff;*/
//force = Math.abs(x + y + z - lastX - lastY - lastZ);
force = Math.abs(x - lastX);
if (Float.compare(force, threshold) >0 ) {
//Toast.makeText(Accelerometer.getContext(), (now-lastShake)+" >= "+interval, 1000).show();
if (now - lastShake >= interval) {
// trigger shake event
listener.onShake(force);
}
else
{
//Toast.makeText(aContext,"No Motion detected", Toast.LENGTH_SHORT).show();
}
lastShake = now;
}
lastX = x;
lastY = y;
lastZ = z;
lastUpdate = now;
}
else
{
//Toast.makeText(aContext,"No Motion detected", Toast.LENGTH_SHORT).show();
}
}
// trigger change event
listener.onAccelerationChanged(x, y, z);
}
};
}
AccelerometerListener.java
public interface AccelerometerListener {
public void onAccelerationChanged(float x, float y, float z);
public void onShake(float force);
}