I have the following class to read data from accelerometer:
public class Accelerometer implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mAccelerometer;
float deltaX;
float deltaY;
float deltaZ;
Activity activity;
public Accelerometer(Activity act)
{
this.activity = act;
mSensorManager = (SensorManager) this.activity.getSystemService(Context.SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
public float getDeltaX()
{
return this.deltaX;
}
public float getDeltaY()
{
return this.deltaY;
}
public float getDeltaZ()
{
return this.deltaZ;
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
deltaX = event.values[0];
deltaY = event.values[1];
deltaZ = event.values[2];
}
}
and I am accessing this class from my main activity class using the following code:
Accelerometer sbt = new Accelerometer (this);
tvX.setText(Float.toString(sbt.getDeltaX()) + " " +Float.toString(sbt.getDeltaY()) + " "+Float.toString(sbt.getDeltaZ()));
However, it always shows me 0, 0, 0. not sure whats wrong with current code. any help would be highly appreciated.
THe accelerometer (and all sensor data) works on a callback system. It won't call you until the next time it reads the sensor, and it will continue to call your onSensorChanged until you unregister. But if you try to set the text immediately after registering, you won't have been called yet. You need to set the textView in onSensorChanged, when you're updated with new values.
Related
I have created a simple app that uses the accelerometer sensor to calculate the outside force then start a mp3 file. It seems to work well unless I turn screen off (or it automaticlly turns itself off) then it stops completely. How can i fix it. My code here, Thanks.
private MediaPlayer mediaPlayer;
private TextView textView;
private SensorManager sensorManager;
private Sensor accelerometerSensor;
private float maxf;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) this.findViewById(R.id.textView);
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorManager.registerListener(this, accelerometerSensor, SensorManager.SENSOR_DELAY_UI);
}
#Override
public void onSensorChanged(SensorEvent event) {
if(event.sensor.getType() != Sensor.TYPE_ACCELEROMETER){
return;
}
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
float f = Math.round(Math.abs(x*x + y*y + z*z));
if (f>maxf ){ maxf =f;}
StringBuilder sb = new StringBuilder();
sb.append("forrce:").append(f).append("\n");
sb.append("MaxForce:").append(maxf).append("\n");
textView.setText(sb.toString());
if (maxf>150) {
mediaPlayer = MediaPlayer.create(this, R.raw.b);
mediaPlayer.start();
maxf=1;
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
Add on-lock services
[Reference][1]https://developer.android.com/guide/components/services.html
And use accelerometer in that particular activity...Hope it helps :)
I've implemented SensorEventListener in my MainActivity, and it works quite well, i'd even say most of the time very well.
But weirdly, sometimes it completely stops working, I need to shake it in every direction for 5-10 seconds and it's magically back on.
It seems to be after the phone as idle/asleep for a long time.
I did implemented the register/unregister on onResume/onPause.
Here is my code, mostly coming from stackoverflow:
SensorManager sensorManager;
private float accel; // acceleration apart from gravity
private float accelCurrent; // current acceleration including gravity
private float accelLast; // last acceleration including gravity
private static final float SHAKE_THRESHOLD = 12.f;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initSensor();
}
private void initSensor() {
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
registerSensor();
}
private void registerSensor() {
HandlerThread handlerThread = new HandlerThread(HANDLER_THREAD_NAME_SENSOR);
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL, handler);
accel = 0.00f;
accelCurrent = SensorManager.GRAVITY_EARTH;
accelLast = SensorManager.GRAVITY_EARTH;
}
#Override
protected void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
}
#Override
protected void onResume() {
super.onResume();
registerSensor();
}
#Override
public void onSensorChanged(SensorEvent event) {
float x = event.values[0];
float y = event.values[1];
float z = event.values[2];
accelLast = accelCurrent;
accelCurrent = (float) Math.sqrt((double) (x*x + y*y + z*z));
float delta = accelCurrent - accelLast;
accel = accel * 0.9f + delta; // perform low-cut filter
//Log.d(TAG, ">>> ALL shake accel = "+ accel);
if (accel > SHAKE_THRESHOLD) {
Log.d(TAG, "shake accel = "+ accel);
runOnUiThread(new Runnable() {
#Override
public void run() {
// Do stuffs in the UI
}
});
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Nothing do to here
}
It was fixed by changing the sensor delay to SensorManager.SENSOR_DELAY_FASTEST;
The registration now looks like :
// Global
private static final String HANDLER_THREAD_NAME_SENSOR = "sensorThread";
// ...Registration
HandlerThread handlerThread = new HandlerThread(HANDLER_THREAD_NAME_SENSOR);
handlerThread.start();
Handler handler = new Handler(handlerThread.getLooper());
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_FASTEST,
handler);
I am a java newer,
I want to get, for example, 10 different values of my phone's acceleration,
and get an average value from them.
But I can only find answers for continued data, or only one data.
Now I can get one data and display it on my screen.
Can I use for loop to calculate for 10 times?
Thank you.
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
aAngle = event.values[0];
bAngle = event.values[1];
}
private Button.OnClickListener listener = new Button.OnClickListener() {
switch(viewMode){
case VIEW_MODE_1:
title.setText(Double.toString(aAngle) + " " + Double.toString(bAngle));
break;}
I've tried to cast a for loop in the OnSensorChanged method, but it didn't work at all.
I tried to do this, but it seems to have a runtime error.
List<Sensor> sensors = sensorManager.getSensorList(Sensor.TYPE_ACCELEROMETER);
if (sensors.size() > 0 && sensors.size() <= 10) {
sensorManager.registerListener(this,sensors.get(count),SensorManager.SENSOR_DELAY_NORMAL);
count ++;
}
also, I create two list to save the result every time when my angle is changed.
for(int i = 0; i < aAngleList.size(); i++){
double aAngleTotal = 0;
double bAngleTotal = 0;
aAngleTotal += aAngleList.get(i);
bAngleTotal += bAngleList.get(i);
aAngleAverage = aAngleTotal / aAngleList.size();
bAngleAverage = bAngleTotal / bAngleList.size();
}
public void onSensorChanged(SensorEvent event) {
aAngleList.add(aAngle);
bAngleList.add(bAngle);
}
the for loop is in onResume, right under the if (sensors...)
onSensorChanged is fired everytime your sensor gets a new reading. you can place a counter for ten changes. keep track of values in a list,hashmap and aggregate them.
public class SensorActivity extends Activity, implements SensorEventListener {
private final SensorManager mSensorManager;
private final Sensor mAccelerometer;
private int count=0;
private List<String> eventX=new ArrayList<String>();
public SensorActivity() {
mSensorManager = (SensorManager)getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
protected void onResume() {
super.onResume();
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
protected void onPause() {
super.onPause();
mSensorManager.unregisterListener(this);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
eventX.add(event.getValueMethodwhateverItis());
count++;
if (count=10){
//aggregate from list do anything you want.;
}
}
}
SO im trying to make a App that tracks which direction the phone is pointed VIA the compass and once a button is hit on the screen it displays the number of where it is pointed in degrees. So far i understand how the compass is created but can not find which values are the pointed direction in relation to North. Here is what i have so far.
public class compass extends Activity implements OnClickListener, SensorEventListener{
private final SensorManager DirPoint;
float var;
TextView theNumber;
Button DirectionIn;
public compass(){
DirPoint = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
}
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
public void onSensorChanged(SensorEvent event) {}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
theNumber = (textView) findViewById(R.id.output);
DirectionIn =(Button) findViewById(R.Id.Buton);
DirectionIn.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v) {
//gets direction of phone compass
// ((TextView)findViewById(R.id.output)).setText(var);
}
}
}
}
Any help would be welcomed or if im headed in the right direction even would be nice.
You have to implement a "compass". You can do this like this:
Let your activity implement the SensorEventListener and add the necessary fields:
public class CompassActivity extends Activity implements SensorEventListener {
private SensorManager sensorManager;
private Sensor accelerometer;
private Sensor magnetometer;
private float[] lastAccelerometer = new float[3];
private float[] lastMagnetometer = new float[3];
private boolean lastAccelerometerSet = false;
private boolean lastMagnetometerSet = false;
private float[] rotationMatrix = new float[9];
private float[] orientation = new float[3];
private float currentDegree = 0f;
In the onCreate method of the activity get and start the two sensors, the accelerometer and the magnetometer:
// onCreate method stub ...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
magnetometer = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI);
sensorManager.registerListener(this, magnetometer, SensorManager.SENSOR_DELAY_UI);
// more onCreate method stub ....
In the method of the SensorEventListener you can now calculate the heading of the phone and calculate the bearing between the current location and a other location:
#Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor == this.accelerometer) {
System.arraycopy(event.values, 0, this.lastAccelerometer, 0, event.values.length);
this.lastAccelerometerSet = true;
} else if (event.sensor == this.magnetometer) {
System.arraycopy(event.values, 0, this.lastMagnetometer, 0, event.values.length);
this.lastMagnetometerSet = true;
}
if (this.lastAccelerometerSet && this.lastAccelerometerSet) {
SensorManager.getRotationMatrix(this.rotationMatrix,null, this.lastAccelerometer, this.lastMagnetometer);
SensorManager.getOrientation(this.rotationMatrix, this.orientation);
float azimuthInRadiands = this.orientation[0];
// this is now the heading of the phone. If you want
// to rotate a view to north don´t forget that you have
// to rotate by the negative value.
float azimuthInDegrees = (float) Math.toDegrees(azimuthInRadiands);
}
}
But don´t forget that there is much more behind a compass. You have to show the user if the magnetic field sensor is uncalibrated. You have to calculate the difference between the magnetic and the geographic north...
I have created a small compass helper class. The HowTo is in the readme. It will provide you all the information you need to present a compass on the screen:
Compass Assistant on GitHub
It provides you the current heading of the device. Please don´t hesitate to ask me if you have problems.
For Details look here
Use a compination of TYPE_ACCELEROMETER and TYPE_MAGNETIC_FIELD.
Sensor beschleunigung = sensor.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0);
Sensor magnetometer = sensor.getSensorList(Sensor.TYPE_MAGNETIC_FIELD).get(0);
sensor.registerListener(handler, beschleunigung, SensorManager.SENSOR_DELAY_NORMAL, null);
sensor.registerListener(handler, magnetometer, SensorManager.SENSOR_DELAY_NORMAL, null);
and
handler = new SensorEventListener() {
float[] mGravity;
float[] mGeomagnetic;
#Override
public void onSensorChanged( SensorEvent event ) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
mGravity = event.values;
if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD)
mGeomagnetic = event.values;
if (mGravity != null && mGeomagnetic != null) {
float R[] = new float[9];
float I[] = new float[9];
boolean success = SensorManager.getRotationMatrix(R, I, mGravity, mGeomagnetic);
if (success) {
float orientation[] = new float[3];
SensorManager.getOrientation(R, orientation);
azimut = orientation[0]; // orientation contains: azimut, pitch and roll
}
}
NavigationArrow.this.setOffsetFromNorth((float) Math.toDegrees(azimut));
}
#Override
public void onAccuracyChanged( Sensor sensor, int accuracy ) {
}
};
Hope that helps :)
I am facing a challenge in my new application, i want to find the android phone screen facing ceiling or floor.Can i able to make this with the android sensors.If any body tried this please share your valuable ideas and tutorial if available.
In oncreate
sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
List<Sensor> sensorList = sensorManager
.getSensorList(Sensor.TYPE_ACCELEROMETER);
if (sensorList.size() > 0) {
accelerometerPresent = true;
accelerometerSensor = sensorList.get(0);
}
register the SensorEventListener
sensorManager.registerListener(accelerometerListener,
accelerometerSensor, SensorManager.SENSOR_DELAY_NORMAL);
and the SensorEventListener implementation
private SensorEventListener accelerometerListener = new SensorEventListener() {
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
public void onSensorChanged(SensorEvent event) {
float z_value = event.values[2];
if (z_value == 10) {
// up facing
} else if(z_value == -10)
// down facing
}
}
};
In my two device it shows z_values = 10 when it is upfacing and horizontal and in the opposite case it is showing - 10. check your cases.
You can use the SensorEventListener to achieve this. Have a look at my below code for a better understanding. You can also look at this in the developer docs for more about sensors.
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
public class SensorClass implements SensorEventListener {
private float mInR[];
private float mI[];
private float mGravity[];
private float mGeomag[];
private float mOrientVals[];
final float rad2deg = 180/((float) Math.PI);
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// Do something here when accuracy changed
}
#Override
public void onSensorChanged(SensorEvent event) {
float azimuth = 0f;
float pitch = 0f;
float roll = 0f;
// If the sensor data is unreliable return
if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
return;
// Gets the value of the sensor that has been changed
switch (event.sensor.getType()){
case Sensor.TYPE_ACCELEROMETER:
mGravity = event.values.clone();
break;
case Sensor.TYPE_MAGNETIC_FIELD:
mGeomag = event.values.clone();
break;
}
if (mGravity != null && mGeomag != null){
// checks that the rotation matrix is found
if (SensorManager.getRotationMatrix(mInR, mI, mGravity, mGeomag)){
// magnetic north and the horizon respectively
SensorManager.getOrientation(mInR, mOrientVals);
azimuth = mOrientVals[0]*rad2deg;
pitch = mOrientVals[1]*rad2deg;
roll = mOrientVals[2]*rad2deg;
}
}
}
}