是否可以测量手机垂直移动的距离 [英] Is it possible to measure the how far the phone travels vertically
问题描述
我只是想知道是否有可能/从哪里开始测量Android设备的向上和向下运动.我需要尽可能准确.
我完全不知道在哪里看,我已经看到了某些方法
在寻求解决方案之前,我将解决方案分为小资产,并提出解决方案的难题
- 我们需要听电话感应器
- 我们需要检查手机是否处于垂直位置
- 我们需要建立一个可以垂直注册手机并向上计数的计时器
- 我们需要在屏幕上显示时间
对于第一步,我将对我们的类实现 SensorEventListener
,这将使我们能够使用 onSensorChanged
方法.
@Override公共无效onSensorChanged(SensorEvent事件){如果(event.sensor.getType()== Sensor.TYPE_ACCELEROMETER){listenToSensors(event);}}私人无效的listenToSensors(SensorEvent事件){如果(isPhoneVertical(event)){timeCounter();如果(mStatus){mStartTime = getStartTime();mStatus = false;}} 别的 {如果(!mStatus){mTotalTime = getDiffTime()+ mTotalTime;mStatus = true;}}}
对于第二步,我建立了一个名为 isPhoneVertical
的方法来检查我们的手机是否处于垂直状态,主要是检查y轴.您可以通过更改 maxVertical
来更改陡峭度.值越小,她的陡度就越小,0表示手机应几乎是100%垂直的.对于我的测试,它设置为3.
私有布尔isPhoneVertical(SensorEvent事件){float [] values = event.values;双重y =值[1];//请勿更改此值yAxisInitValue的两倍= 10.0;double verMargin = yAxisInitValue-maxVertical;返回y> = verMargin;}
对于第3步,我几乎没有方法检查开始时间和结束时间以及更新以秒为单位跟踪时间的全局变量.
private long getStartTime(){返回System.currentTimeMillis()/1000;}私人长getDiffTime(){返回getStartTime()-mStartTime;}
对于第4步,我制作了一个常规的 runOnUiThread
来更新屏幕上的时间.
private void timeCounter(){runOnUiThread(new Runnable(){@Override公共无效run(){mView1.setText(电话已垂直放置:" + getDiffTime()+秒");mView2.setText(总时间:" +(mTotalTime + getDiffTime())+");}});}
那是说这个解决方案是为了说明如何实现这个目标,我相信可以用不同的方式来实现.但是我想展示解决方案背后的逻辑.
这是该应用程序的屏幕截图,其中统计了手机每次垂直移动的时间和垂直移动的总时间.
解决方案包括一些解释:
MainActivity.java
公共类MainActivity扩展Activity实现SensorEventListener {私有SensorManager mSensorManager;专用传感器加速度计;私人TextView mView1,mView2;私人长mStartTime;私人长mTotalTime;私有布尔值mStatus = true;//值越小,她的陡度就越小,0表示电话应该几乎是100%垂直//试试看私人double maxVertical = 3.0;@Override公共无效onCreate(捆绑保存的InstanceState){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);加速度计= mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);}@Override公共无效onSensorChanged(SensorEvent事件){如果(event.sensor.getType()== Sensor.TYPE_ACCELEROMETER){listenToSensors(event);}}私人无效的listenToSensors(SensorEvent事件){如果(isPhoneVertical(event)){timeCounter();如果(mStatus){mStartTime = getStartTime();mStatus = false;}} 别的 {如果(!mStatus){mTotalTime = getDiffTime()+ mTotalTime;mStatus = true;}}}//此方法仅针对特定的手机方向返回true//垂直方向的y轴私人布尔isPhoneVertical(SensorEvent事件){float [] values = event.values;双重y =值[1];//请勿更改此值yAxisInitValue的两倍= 10.0;double verMargin = yAxisInitValue-maxVertical;返回y> = verMargin;}私人长getStartTime(){返回System.currentTimeMillis()/1000;}私人长getDiffTime(){返回getStartTime()-mStartTime;}//更新用户界面中的步骤私人void timeCounter(){runOnUiThread(new Runnable(){@Override公共无效run(){mView1.setText(电话已垂直放置:" + getDiffTime()+秒");mView2.setText(总时间:" +(mTotalTime + getDiffTime())+");}});}@Overridepublic void onAccuracyChanged(Sensor sensor,int precision){}@Override受保护的void onResume(){super.onResume();mSensorManager.registerListener(this,mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),SensorManager.SENSOR_DELAY_NORMAL);}@Override受保护的void onPause(){super.onPause();//如果您要在手机屏幕关闭时收集数据,只需禁用//在以下一行中,该应用仍将收集传感器数据mSensorManager.unregisterListener(this);}}
Activity_main.xml
<?xml version ="1.0" encoding ="utf-8"?>< RelativeLayout xmlns:android ="http://schemas.android.com/apk/res/android"xmlns:tools ="http://schemas.android.com/tools"android:id ="@ + id/activity_main"android:layout_width ="match_parent"android:layout_height ="match_parent"android:paddingBottom ="@ dimen/activity_vertical_margin"android:paddingLeft ="@ dimen/activity_horizontal_margin"android:paddingRight ="@ dimen/activity_horizontal_margin"android:paddingTop ="@ dimen/activity_vertical_margin"工具:context ="com.example.maytham.verticaltravels.MainActivity">< TextViewandroid:id ="@ + id/textView1"android:layout_width ="match_parent"android:layout_height ="wrap_content"android:layout_alignParentLeft ="true"android:layout_alignParentStart ="true"android:layout_alignParentTop ="true"android:textSize ="20sp"android:text ="TextView1"/>< TextViewandroid:id ="@ + id/textView2"android:layout_width ="match_parent"android:layout_height ="wrap_content"android:layout_alignParentLeft ="true"android:layout_alignParentStart ="true"android:layout_below ="@ + id/textView1"android:layout_marginTop ="57dp"android:textSize ="20sp"android:text ="TextView2"/></RelativeLayout>
我也会留下一些阅读链接.
- https://developer.android.com/reference/android/hardware/SensorManager.html
- http://www.livescience.com/40103-accelerometer-vs-gyroscope.html
- https://physics.stackexchange.com/questions/41653/how-do-i-get-the-total-acceleration-from-3-axes
- https://code.tutsplus.com/tutorials/如何识别用户活动-with-activity-recognition--cms-25851
- http://www.vogella.com/tutorials/AndroidSensor/article.html
- 如何获取与人类方位匹配的Android手机方位?/a>
如果您认为我可能会添加更多可以帮助您进一步解决问题的信息,请告诉我.还不清楚您是否正在寻找步行检测/计数器,如果这是您感兴趣的事情,请查看以下答案/链接.
和GitHub源代码
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 possible.
I'm quite lost of where to look I've seen there are certain methods here, and looking at these old questions they mention it's quite difficult but I wanted to know if there had been any improvements since then in newer versions of android.
The image below is an extra example of the the direction I would like the phone to move in.
Before going to solution, I would split the solution in small assets and put the puzzle for solution
- We need to listen to phone sensors
- We need to check phone is in vertical position or not
- We need to make a time counter that register the phone vertically and count up
- We need to display the time on screen
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
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.maytham.verticaltravels.MainActivity">
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:textSize="20sp"
android:text="TextView1" />
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@+id/textView1"
android:layout_marginTop="57dp"
android:textSize="20sp"
android:text="TextView2" />
</RelativeLayout>
I will leave some link for reading as well.
- https://developer.android.com/reference/android/hardware/SensorManager.html
- http://www.livescience.com/40103-accelerometer-vs-gyroscope.html
- https://physics.stackexchange.com/questions/41653/how-do-i-get-the-total-acceleration-from-3-axes
- https://code.tutsplus.com/tutorials/how-to-recognize-user-activity-with-activity-recognition--cms-25851
- http://www.vogella.com/tutorials/AndroidSensor/article.html
- How to get Android phone orientation matching human orientation?
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.
- Activity Recognition Api
- How to detect walking with Android accelerometer
- how to calculate exact foot step count using accelerometer in android?
- Detect Movement Accurately using Accelerometer in Android
and GitHub source codes
这篇关于是否可以测量手机垂直移动的距离的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!