android - 是否可以测量手机垂直移动的距离

标签 android

我只是想知道是否有可能/我应该从哪里开始测量 Android 设备的向上和向下运动。我需要它尽可能准确。

我完全不知道去哪里找我已经看到有某些方法 here ,并查看 these old questions他们提到这非常困难,但我想知道从那时起在较新版本的 android 中是否有任何改进。

下图是我希望手机移动方向的额外示例。

enter image description here

最佳答案

在解决问题之前,我会把解决方案分成小 Assets ,然后把谜题放在解决方案上

  1. 我们需要听电话传感器
  2. 我们需要检查手机是否处于垂直位置
  3. 我们需要做一个时间计数器垂直注册手机并计数
  4. 我们需要在屏幕上显示时间

对于第一步,我将在我们的类中实现 SensorEventListener,这将允许我们使用 onSensorChanged 方法。

@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;
        }
    }
}

对于第二步,我构建了一个名为 isPhoneVertical 的方法来检查我们的手机是否垂直,它主要检查 y 轴。您可以通过更改 maxVertical 来更改陡度。 越低越陡峭,0 表示手机应该几乎 100% 垂直。对于我的测试,它设置为 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;
}

对于第 3 步,我使用了一些方法来检查开始时间和停止时间并更新以秒为单位跟踪时间的全局变量。

private long getStartTime() {
    return System.currentTimeMillis() / 1000;
}

private long getDiffTime() {
    return getStartTime() - mStartTime;
}

对于第 4 步,我制作了一个常规的 runOnUiThread 来更新屏幕上的时间。

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()) + "");
        }
    });
}

这就是说这个解决方案是为了说明如何实现这个目标,我相信它可以通过不同的方式来实现。但我想展示解决方案背后的逻辑。

这是应用程序的屏幕截图,它计算手机每次垂直放置的时间以及它一直垂直放置的总时间。

enter image description here

包括一些解释的解决方案:

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>

我也会留下一些阅读链接。

如果您认为我可以添加更多信息来帮助您进一步解决您的问题,请告诉我。还不清楚您是否在寻找步行检测/计数器,如果您对此感兴趣,请查看以下答案/链接。

和 GitHub 源代码

关于android - 是否可以测量手机垂直移动的距离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39884057/

相关文章:

android - Android 上的 Appium 无法定位在屏幕滚动部分不可见的元素

android - 如何将我的 Activity 设置为android中的主要 Activity ?

android - 如何让 font-size 0 在 Android 中工作?

android - 无法添加 Android 支持库版本 7

Android Logcat 垃圾邮件很多

java - 使用 ZXing 编码和解码 byte[]

android - getChildAt(0) 会返回 null 吗?

android - 尝试使用 where 子句时内容解析器 .query 出现问题

java - android 标签布局错误

android - 如何正确过滤包替换广播