I\'m just wondering if it is possible / where would I get started in measuring the upwards and downwards movement of an Android device. I\'d need it to be as accurate as possibl
Before going to solution, I would split the solution in small assets and put the puzzle for solution
For step one, I would implement SensorEventListener
to our class, this will allow us to use onSensorChanged
method.
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
listenToSensors(event);
}
}
private void listenToSensors(SensorEvent event) {
if (isPhoneVertical(event)) {
timeCounter();
if (mStatus) {
mStartTime = getStartTime();
mStatus = false;
}
} else {
if (!mStatus) {
mTotalTime = getDiffTime() + mTotalTime;
mStatus = true;
}
}
}
For step two, I have built a method called isPhoneVertical
to check if our phone is in vertical way or not, it is primarily checking the y axis. You can change the steep degree by changing maxVertical
.
Less value her less steep, 0 means the phone should almost be 100% vertical. For my test it is set to 3.
private boolean isPhoneVertical(SensorEvent event) {
float[] values = event.values;
double y = values[1];
// do not change this value
double yAxisInitValue = 10.0;
double verMargin = yAxisInitValue - maxVertical;
return y >= verMargin;
}
For step 3 I have made few method to check start time and stop time and update a global variable that keep track of time in seconds.
private long getStartTime() {
return System.currentTimeMillis() / 1000;
}
private long getDiffTime() {
return getStartTime() - mStartTime;
}
For step 4 I have made a regular runOnUiThread
to update the time on screen.
private void timeCounter() {
runOnUiThread(new Runnable() {
@Override
public void run() {
mView1.setText("Phone has been vertical for: " + getDiffTime() + " seconds");
mView2.setText("The total time: " + (mTotalTime + getDiffTime()) + "");
}
});
}
That said this solution is to illustrate how this goal can be reached, I am sure it can be done different ways. But I wanted to show the logic behind the solution.
And here is a screen shot of the app that counts the time for each time the phone is vertical and total time it has been vertical.
The solution including some explanations:
MainActivity.java
public class MainActivity extends Activity implements SensorEventListener {
private SensorManager mSensorManager;
private Sensor mAccelerometer;
private TextView mView1, mView2;
private long mStartTime;
private long mTotalTime;
private boolean mStatus = true;
// less value her less steep, 0 means the phone should almost be 100% vertical
// try it out
private double maxVertical = 3.0;
@Override
public void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mView1 = (TextView) findViewById(R.id.textView1);
mView2 = (TextView) findViewById(R.id.textView2);
mSensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
}
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
listenToSensors(event);
}
}
private void listenToSensors(SensorEvent event) {
if (isPhoneVertical(event)) {
timeCounter();
if (mStatus) {
mStartTime = getStartTime();
mStatus = false;
}
} else {
if (!mStatus) {
mTotalTime = getDiffTime() + mTotalTime;
mStatus = true;
}
}
}
// This method return true only for specific phone orientation
// y axis for vertical orientation
private boolean isPhoneVertical(SensorEvent event) {
float[] values = event.values;
double y = values[1];
// do not change this value
double yAxisInitValue = 10.0;
double verMargin = yAxisInitValue - maxVertical;
return y >= verMargin;
}
private long getStartTime() {
return System.currentTimeMillis() / 1000;
}
private long getDiffTime() {
return getStartTime() - mStartTime;
}
// update steps in user interface
private void timeCounter() {
runOnUiThread(new Runnable() {
@Override
public void run() {
mView1.setText("Phone has been vertical for: " + getDiffTime() + " seconds");
mView2.setText("The total time: " + (mTotalTime + getDiffTime()) + "");
}
});
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
protected void onResume() {
super.onResume();
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
SensorManager.SENSOR_DELAY_NORMAL);
}
@Override
protected void onPause() {
super.onPause();
// if you want to collect data while mobile screen off, just disable the
// following line, the app will still collecting sensor data
mSensorManager.unregisterListener(this);
}
}
Activity_main.xml
I will leave some link for reading as well.
If you think I might add more information that can help you further with your question please let me know. It is also unclear if you was looking for walking detection/counter, if that is some thing you are interesting in, look at following answers/links.
and GitHub source codes