I tried to pass shake speed through a listener activity to main activity, but the code just won't work. It says "the application has unfortunately stopped"
listener code:
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
/**
* Listener that detects shake gesture.
*/
public class AccReader implements SensorEventListener {
Activity foo;
SensorManager manager;
Sensor accelerometer;
private static final int MIN_FORCE = 10;
private static final int MIN_DIRECTION_CHANGE = 3;
private static final int MAX_PAUSE_BETHWEEN_DIRECTION_CHANGE = 200;
private static final int MAX_TOTAL_DURATION_OF_SHAKE = 400;
private long mFirstDirectionChangeTime = 0;
private long mLastDirectionChangeTime;
/** How many movements are considered so far. */
private int mDirectionChangeCount = 0;
/** The last x position. */
private float lastX = 0;
/** The last y position. */
private float lastY = 0;
/** The last z position. */
private float lastZ = 0;
/** OnShakeListener that is called when shake is detected. */
private OnShakeListener mShakeListener;
private float totalMovement;
public AccReader(Activity foo) {
this.foo = foo;
manager = (SensorManager) this.foo.getSystemService(Context.SENSOR_SERVICE);
accelerometer = manager.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
manager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_GAME);
}
/**
* Interface for shake gesture.
*/
public interface OnShakeListener {
/**
* Called when shake gesture is detected.
*/
void onShake();
}
public void setOnShakeListener(OnShakeListener listener) {
mShakeListener = listener;
}
public float getTotalMovement() {
return this.totalMovement;
}
#Override
public void onSensorChanged(SensorEvent se) {
// get sensor data
float x = se.values[SensorManager.DATA_X];
float y = se.values[SensorManager.DATA_Y];
float z = se.values[SensorManager.DATA_Z];
// calculate movement
totalMovement = Math.abs(x + y + z - lastX - lastY - lastZ);
if (totalMovement > MIN_FORCE) {
// get time
long now = System.currentTimeMillis();
// store first movement time
if (mFirstDirectionChangeTime == 0) {
mFirstDirectionChangeTime = now;
mLastDirectionChangeTime = now;
}
// check if the last movement was not long ago
long lastChangeWasAgo = now - mLastDirectionChangeTime;
if (lastChangeWasAgo < MAX_PAUSE_BETHWEEN_DIRECTION_CHANGE) {
// store movement data
mLastDirectionChangeTime = now;
mDirectionChangeCount++;
// store last sensor data
lastX = x;
lastY = y;
lastZ = z;
// check how many movements are so far
if (mDirectionChangeCount >= MIN_DIRECTION_CHANGE) {
// checkk total duration
long totalDuration = now - mFirstDirectionChangeTime;
if (totalDuration < MAX_TOTAL_DURATION_OF_SHAKE) {
mShakeListener.onShake();
resetShakeParameters();
}
}
} else {
resetShakeParameters();
}
}
}
/**
* Resets the shake parameters to their default values.
*/
private void resetShakeParameters() {
mFirstDirectionChangeTime = 0;
mDirectionChangeCount = 0;
mLastDirectionChangeTime = 0;
lastX = 0;
lastY = 0;
lastZ = 0;
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
}
main activity code:
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.EditText;
public abstract class MainActivity extends AppCompatActivity implements SensorEventListener {
private SensorManager mSensorManager;
private AccReader mSensorListener;
private Sensor mAccelerometer;
AccReader acc;
private EditText output;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(new AccReader(this), mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
output = (EditText) findViewById(R.id.editText1);
acc = new AccReader(this);
mSensorListener.setOnShakeListener(new AccReader.OnShakeListener() {
#Override
public void onShake() {
refresh();
}
});
}
public void refresh() {
output.setText("X:" + acc.getTotalMovement());
}
#Override
protected void onResume() {
super.onResume();
mSensorManager.registerListener(mSensorListener,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);
}
#Override
protected void onPause() {
mSensorManager.unregisterListener(mSensorListener);
super.onPause();
}
The code has compiled correctly, but the resulting APK is unable to run.
Can anyone put light on what I may have done wrong?
P.S. I'm completely new to android development
EDIT:
Logcat:
09 - 03 23: 51: 26.680 1936 - 1936 / lamegames.app I / art﹕Not late - enabling - Xcheck: jni(already on)
09 - 03 23: 51: 27.195 1936 - 1936 / lamegames.app D / AndroidRuntime﹕Shutting down VM---------beginning of crash
09 - 03 23: 51: 27.195 1936 - 1936 / lamegames.app E / AndroidRuntime﹕FATAL EXCEPTION: main
Process: lamegames.slapapp,
PID: 1936
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo {
lamegames.app / lamegames.app.MainActivity
}: java.lang.InstantiationException: class lamegames.app.MainActivity cannot be instantiated
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java: 2236)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java: 2390)
at android.app.ActivityThread.access$800(ActivityThread.java: 151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java: 1303)
at android.os.Handler.dispatchMessage(Handler.java: 102)
at android.os.Looper.loop(Looper.java: 135)
at android.app.ActivityThread.main(ActivityThread.java: 5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java: 372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 698)
Caused by: java.lang.InstantiationException: class lamegames.app.MainActivity cannot be instantiated
at java.lang.Class.newInstance(Class.java: 1587)
at``android.app.Instrumentation.newActivity(Instrumentation.java: 1066)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java: 2226)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java: 2390)
at android.app.ActivityThread.access$800(ActivityThread.java: 151)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java: 1303)
at android.os.Handler.dispatchMessage(Handler.java: 102)
at android.os.Looper.loop(Looper.java: 135)
at android.app.ActivityThread.main(ActivityThread.java: 5257)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java: 372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 903)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java: 698)
09 - 03 23: 52: 10.917 1936 - 1943 / lamegames.app W / art﹕Suspending all threads took: 19.739ms
09 - 03 23: 52: 24.263 1936 - 1936 / lamegames.app I / Process﹕Sending signal.PID: 1936 SIG: 9
MainActivity does not need to be abstract nor does it need to implement SensorEventListener. I'm also not sure why you were using two AccReader objects.
Here is the fixed MainActivity code:
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.EditText;
public class MainActivity extends AppCompatActivity {
private SensorManager mSensorManager;
private Sensor mAccelerometer;
AccReader acc;
private EditText output;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(new AccReader(this), mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
output = (EditText) findViewById(R.id.editText1);
acc = new AccReader(this);
acc.setOnShakeListener(new AccReader.OnShakeListener() {
#Override
public void onShake() {
refresh();
}
});
}
public void refresh() {
output.setText("X:" + acc.getTotalMovement());
}
#Override
protected void onResume() {
super.onResume();
mSensorManager.registerListener(acc,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_UI);
}
#Override
protected void onPause() {
mSensorManager.unregisterListener(acc);
super.onPause();
}
}
The last thing was a null check for mShakeListener in AccReader, because the shake event seemed to trigger multiple times, and confused the listener.
This code should go in your onSensorChanged method when you call onShake
if(mShakeListener != null)
mShakeListener.onShake();
Related
I have to log my Sensor data from my Android Phone to a csv. file so I can use it further , the problem is I tried something with some code(FileWriter to csv) that I found and put it into my code and it does not work, can maybe someone tell me what I do wrong, where my error is. The idea is to just record different sensor data with different EventHandlers like in the Code Example and then write the sensor data to a csv. file together and that csv. file should be on the phone.
I have maybe to mention that I have never before programed in Java or did Android , so please try to answer me as simple as possible, thank you :)
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.ProgressBar;
import android.widget.Switch;
import android.widget.TextView;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
TextView txt_currentAccel, txt_prevAccel, txt_acceleration, txt_temp;
ProgressBar prog_shakeMeter;
Switch switch1;
//define Sensor Variables
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private SensorManager mSensorManagerNew;
private Sensor mTemp;
private double accelerationCurrentValue;
private double accelerationPreviousValue;
private int SwitchFlag = 0;
final String TAG = "SensorLog";
FileWriter writer;
private SensorEventListener sensorEventListener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER && SwitchFlag == 1) {
float x = sensorEvent.values[0];
float y = sensorEvent.values[1];
float z = sensorEvent.values[2];
accelerationCurrentValue = Math.sqrt((x * x + y * y + z * z));
double changeInAcceleration = Math.abs(accelerationCurrentValue - accelerationPreviousValue);
accelerationPreviousValue = accelerationCurrentValue;
//update text views
txt_currentAccel.setText("Current =" + accelerationCurrentValue);
txt_prevAccel.setText(("Prev = " + accelerationPreviousValue));
txt_acceleration.setText("Acceleration change =" + changeInAcceleration);
prog_shakeMeter.setProgress((int) changeInAcceleration);
try {
writer.write(String.format("ACC; %f; %f; %f; %f; %f; %f\n", sensorEvent.values[0], sensorEvent.values[1], sensorEvent.values[2], 0.f, 0.f, 0.f));
}catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
private SensorEventListener sensorEventListenerNew = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
float temp = sensorEvent.values[0];
txt_temp.setText("Temp = " + temp);
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt_acceleration = findViewById(R.id.txt_accel);
txt_prevAccel = findViewById(R.id.txt_prevAccel);
txt_currentAccel = findViewById(R.id.txt_currentAccel);
txt_temp = findViewById(R.id.txt_temp);
prog_shakeMeter = findViewById(R.id.prog_shakeMeter);
switch1 = findViewById(R.id.switch1);
// Initialize Sensors
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManagerNew = (SensorManager) getSystemService(SENSOR_SERVICE);
mTemp = mSensorManagerNew.getDefaultSensor(Sensor.TYPE_LIGHT);
switch1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b == true) {
SwitchFlag = 1;
} else {
SwitchFlag = 0;
}
}
});
}
public void flag() {
if (SwitchFlag == 1) {
Log.d(TAG, "Writing to " + getStorageDir());
try {
writer = new FileWriter(new File(getStorageDir(), "sensors_" + System.currentTimeMillis() + ".csv"));
} catch (
IOException e) {
e.printStackTrace();
}
} else {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
protected void onResume() {
super.onResume();
mSensorManager.registerListener(sensorEventListenerNew, mTemp, SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(sensorEventListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(sensorEventListener);
mSensorManager.unregisterListener(sensorEventListenerNew);
}
private String getStorageDir() {
return this.getExternalFilesDir(null).getAbsolutePath();
}
}
I have put somehow together a code that records my sensor data from the phone and i want to save them as csv file in some directory (maybe DCIM) in the internal Storage on the phone, but i cannot find something similar, i am also new to Android Studio and java.
On the bottom you can see ,i found that code example with
"getExternalFilesDir(null).getAbsolutePath()" , how can i change that , that my file is saved on the phone in internal storage and tell him exactly where so i can find it later and use it further ?
package com.example.shakedemo;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.content.Intent;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.CompoundButton;
import android.widget.ProgressBar;
import android.widget.Switch;
import android.widget.TextView;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class MainActivity extends AppCompatActivity {
TextView txt_currentAccel, txt_prevAccel, txt_acceleration, txt_temp;
ProgressBar prog_shakeMeter;
Switch switch1;
//define Sensor Variables
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private SensorManager mSensorManagerNew;
private Sensor mTemp;
private double accelerationCurrentValue;
private double accelerationPreviousValue;
private int SwitchFlag = 0;
final String TAG = "SensorLog";
FileWriter writer;
private SensorEventListener sensorEventListener = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER && SwitchFlag == 1) {
float x = sensorEvent.values[0];
float y = sensorEvent.values[1];
float z = sensorEvent.values[2];
accelerationCurrentValue = Math.sqrt((x * x + y * y + z * z));
double changeInAcceleration = Math.abs(accelerationCurrentValue - accelerationPreviousValue);
accelerationPreviousValue = accelerationCurrentValue;
//update text views
txt_currentAccel.setText("Current =" + accelerationCurrentValue);
txt_prevAccel.setText(("Prev = " + accelerationPreviousValue));
txt_acceleration.setText("Acceleration change =" + changeInAcceleration);
prog_shakeMeter.setProgress((int) changeInAcceleration);
try {
writer.write(String.format("ACC; %f; %f; %f; %f; %f; %f\n", sensorEvent.values[0], sensorEvent.values[1], sensorEvent.values[2], 0.f, 0.f, 0.f));
}catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
private SensorEventListener sensorEventListenerNew = new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
float temp = sensorEvent.values[0];
txt_temp.setText("Temp = " + temp);
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txt_acceleration = findViewById(R.id.txt_accel);
txt_prevAccel = findViewById(R.id.txt_prevAccel);
txt_currentAccel = findViewById(R.id.txt_currentAccel);
txt_temp = findViewById(R.id.txt_temp);
prog_shakeMeter = findViewById(R.id.prog_shakeMeter);
switch1 = findViewById(R.id.switch1);
// Initialize Sensors
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManagerNew = (SensorManager) getSystemService(SENSOR_SERVICE);
mTemp = mSensorManagerNew.getDefaultSensor(Sensor.TYPE_LIGHT);
switch1.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if (b == true) {
Log.d(TAG, "Writing to " + getStorageDir());
try {
writer = new FileWriter(new File(getStorageDir(), "sensors_" + System.currentTimeMillis() + ".csv"));
} catch (
IOException e) {
e.printStackTrace();
}
SwitchFlag = 1;
} else {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
SwitchFlag = 0;
}
}
});
}
protected void onResume() {
super.onResume();
mSensorManager.registerListener(sensorEventListenerNew, mTemp, SensorManager.SENSOR_DELAY_NORMAL);
mSensorManager.registerListener(sensorEventListener, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(sensorEventListener);
mSensorManager.unregisterListener(sensorEventListenerNew);
}
private String getStorageDir() {
return this.getExternalFilesDir(null).getAbsolutePath();
}
}
My app is crashing. I am trying to build an accelerometer based app. Though build is successful, it is not running in the Pixel Emulator. Where have I gone wrong?
I have been trying to find the error but am unsuccessful. I am attaching the run error message, the screenshot of the manifest file and the main code.
This is the error message:
The main code follows
package com.example.androidaccelerometerexample;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.text.Html;
import android.view.Menu;
import android.widget.TextView;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.os.Vibrator;
import android.widget.TextView;
class Main extends Activity implements SensorEventListener {
private float lastX, lastY, lastZ;
private SensorManager sensorManager;
private Sensor accelerometer;
private float deltaXMax = 0;
private float deltaYMax = 0;
private float deltaZMax = 0;
private float deltaX = 0;
private float deltaY = 0;
private float deltaZ = 0;
private float vibrateThreshold = 0;
private TextView currentX, currentY, currentZ, maxX, maxY, maxZ;
public Vibrator v;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeViews();
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
// success! we have an accelerometer
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
vibrateThreshold = accelerometer.getMaximumRange() / 2;
} else {
// fai! we dont have an accelerometer!
}
//initialize vibration
v = (Vibrator) this.getSystemService(Context.VIBRATOR_SERVICE);
}
public void initializeViews() {
currentX = (TextView) findViewById(R.id.currentX);
currentY = (TextView) findViewById(R.id.currentY);
currentZ = (TextView) findViewById(R.id.currentZ);
maxX = (TextView) findViewById(R.id.maxX);
maxY = (TextView) findViewById(R.id.maxY);
maxZ = (TextView) findViewById(R.id.maxZ);
}
protected void onResume() {
super.onResume();
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
#Override
public void onSensorChanged(#org.jetbrains.annotations.NotNull SensorEvent event) {
// clean current values
displayCleanValues();
// display the current x,y,z accelerometer values
displayCurrentValues();
// display the max x,y,z accelerometer values
displayMaxValues();
// get the change of the x,y,z values of the accelerometer
deltaX = Math.abs(lastX - event.values[0]);
deltaY = Math.abs(lastY - event.values[1]);
deltaZ = Math.abs(lastZ - event.values[2]);
// if the change is below 2, it is just plain noise
if (deltaX < 2)
deltaX = 0;
if (deltaY < 2)
deltaY = 0;
if ((deltaZ > vibrateThreshold) || (deltaY > vibrateThreshold) || (deltaX > vibrateThreshold)) {
v.vibrate(50);
}
}
public void displayCleanValues() {
currentX.setText("0.0");
currentY.setText("0.0");
currentZ.setText("0.0");
}
// display the current x,y,z accelerometer values
public void displayCurrentValues() {
currentX.setText(Float.toString(deltaX));
currentY.setText(Float.toString(deltaY));
currentZ.setText(Float.toString(deltaZ));
}
// display the max x,y,z accelerometer values
public void displayMaxValues() {
if (deltaX > deltaXMax) {
deltaXMax = deltaX;
maxX.setText(Float.toString(deltaXMax));
}
if (deltaY > deltaYMax) {
deltaYMax = deltaY;
maxY.setText(Float.toString(deltaYMax));
}
if (deltaZ > deltaZMax) {
deltaZMax = deltaZ;
maxZ.setText(Float.toString(deltaZMax));
}
}
}
Your activity class needs to be public and not package-private.
Change class Main to public class Main.
I'm simply trying to learn android using baby-steps. I've followed a tutorial on how to implement a "shake listener" from this tutorial
This is it:
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.FloatMath;
public class ShakeListener implements SensorEventListener {
/*
* 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 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;
// gForce will be close to 1 when there is no movement.
float gForce = FloatMath.sqrt(gX * gX + gY * gY + gZ * gZ);
if (gForce > SHAKE_THRESHOLD_GRAVITY) {
final long 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);
}
}
}
}
I read jokes from a folder and I'd like to display a new one every time I shake the phone. I have no idea how to call the shake listener.
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private ShakeListener mShakeListener;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Intent intent = getIntent();
String message = intent.getStringExtra(MainActivity.EXTRA_MESSAGE);
TextView textView = new TextView(this);
textView.setTextSize(16);
String[] test = processData(readText(message));
textView.setText(test[0]); // later will use random
//________________________________________________
// THIS IS THE PART I HAVE NO IDEA HOW TO IMPLEMENT.
while (true) {
if (shake)
textView.setText(test[RandomNumber]);
}
//________________________________________________
setContentView(textView);
}
I think this is what I should use, but frankly I don't understand what's going on:
// ShakeListener initialization
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager
.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mShakeListener = new ShakeListener();
mShakeListener.setOnShakeListener(new OnShakeListener() {
#Override
public void onShake(int count) {
/*
* The following method, "handleShakeEvent(count):" is a stub //
* method you would use to setup whatever you want done once the
* device has been shook.
*/
handleShakeEvent(count);
}
});
You don't call Listeners. They call you.
Move:
while (true) {
if (shake)
textView.setText(test[RandomNumber]); // this line
}
to:
#Override
public void onShake(int count) {
/*
* HERE
*/
handleShakeEvent(count);
}
Should achieve what you're aiming for.
I'm trying to implement a ShakeListener. So I made a Class called ShakeListener.java :
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
public class ShakeListener implements SensorEventListener {
private SensorManager sensorManager;
private List<Sensor> sensors;
private Sensor sensor;
private long lastUpdate = -1;
private long currentTime = -1;
private float last_x, last_y, last_z;
private float current_x, current_y, current_z, currenForce;
private static final int FORCE_THRESHOLD = 900;
private final int DATA_X = SensorManager.DATA_X;
private final int DATA_Y = SensorManager.DATA_Y;
private final int DATA_Z = SensorManager.DATA_Z;
public ShakeListener(Activity parent) {
SensorManager sensorService = (SensorManager) parent
.getSystemService(Context.SENSOR_SERVICE);
this.sensorManager = sensorManager;
this.sensors = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
if (sensors.size() > 0) {
sensor = sensors.get(0);
}
}
public void start() {
if (sensor != null) {
sensorManager.registerListener(this, sensor,
SensorManager.SENSOR_DELAY_GAME);
}
}
public void stop() {
sensorManager.unregisterListener(this);
}
public void onAccuracyChanged(Sensor s, int valu) {
}
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() != Sensor.TYPE_ACCELEROMETER
|| event.values.length < 3)
return;
currentTime = System.currentTimeMillis();
if ((currentTime - lastUpdate) > 100) {
long diffTime = (currentTime - lastUpdate);
lastUpdate = currentTime;
current_x = event.values[DATA_X];
current_y = event.values[DATA_Y];
current_z = event.values[DATA_Z];
currenForce = Math.abs(current_x + current_y + current_z - last_x
- last_y - last_z)
/ diffTime * 10000;
if (currenForce > FORCE_THRESHOLD) {
Log.d("ShakeListener", "SHAKE DETECTED");
}
last_x = current_x;
last_y = current_y;
last_z = current_z;
}
}
}
Now, I want to envoke it from my main activity (thinking about implementing a While-loop that waits for a shake boolean to change?). So in my main activity, I use :
private ShakeListener myShakeListener;
and then
myShakeListener = new ShakeListener(this);
myShakeListener.start();
But I get an NPE on the line :
this.sensors = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
What am I doing wrong? How should I implement this?
Look at sensorService. It is wrong. Change your code:
SensorManager sensorService = (SensorManager) parent
.getSystemService(Context.SENSOR_SERVICE);
this.sensorManager = sensorManager;
to
SensorManager sensorService = (SensorManager) parent
.getSystemService(Context.SENSOR_SERVICE);
this.sensorManager = sensorService ;
or a better code:
this.sensorManager = (SensorManager) parent.getSystemService(Context.SENSOR_SERVICE);