Android sensor topic (2) - Orientation sensor

Introduction to this section:

In the previous section, we learned some basic concepts of sensors and learned the routines of using sensors. The sensor we bring to you in this section is the usage of the direction sensor. Okay, let’s start this section~


1. The concept of three-dimensional coordinate system:

In the Android platform, the sensor frame usually uses a standard three-dimensional coordinate system to represent a value. Taking the direction sensor to be discussed in this section as an example, determining a direction also requires a three-dimensional coordinate. After all, our device cannot always be held horizontally. The direction value returned to us by Android is a flat array with a length of 3. , including values ​​in three directions! There is such a picture in the official API document: sensors_overview

If you can’t understand the picture, then write a text explanation:

  • The direction of the X-axis : from left to right along the horizontal direction of the screen. If the phone is not square, the shorter side needs to be placed horizontally and the longer side needs to be placed vertically.
  • The direction of the Y-axis : starting from the lower left corner of the screen and pointing in the vertical direction of the screen to the top of the screen
  • The direction of the Z axis : when placed horizontally, points to the direction of the sky

2. Three values ​​of the direction sensor

As mentioned in the previous section, the sensor callback method: the parameter SensorEvent event in onSensorChanged, the value type of event is Float[], and there are only three elements at most, while the direction sensor has exactly three elements, all representing degrees! The corresponding meanings are as follows:

values[0]: Azimuth angle, the angle at which the phone rotates around the Z axis. 0 represents North, 90 represents East, 180 represents South, and 270 represents West. If the value of values[0] happens to be these four values, and the phone is placed horizontally, then the current front of the phone is in these four directions. You can use this to write a compass!

values[1 ]: Tilt angle, the degree to which the phone tilts up. This value changes when the phone tilts around the x-axis. The value range is between [-180,180]. If the phone is placed on the table and the table is completely horizontal, values ​​1 should be 0. Of course, few tables are absolutely horizontal. Start from the top of the phone and lift it until the phone is rotated 180 degrees along the x-axis (at this time the screen is placed horizontally on the table). During this rotation process, the value of values[ 1 ] will change from 0 to -180 , that is, when the phone is lifted, the value of values ​​1 will gradually become smaller until it is equal to -180; and when the phone is lifted from the bottom , until the phone rotates 180 degrees along the x-axis, at which time the value of values[ 1 ] will change from 0 to 180 . We can use this feature of value[ 1 ] combined with value[ 2 ] to implement a flat ruler!

value[2 ]: rolling angle, rolling angle along the Y-axis, the value range is: [-90,90], assuming that the mobile phone screen is placed horizontally on the desktop, then if the desktop is flat, values ​​2 The value should be 0. Gradually lift the phone from the left side, and the value of values[ 2 ] will gradually decrease until it is placed perpendicularly to the phone. At this time, the value of values[ 2 ] is -90, and from the right side it is 0-90; add it vertically If you continue to scroll right or left at the position, the value of values[ 2 ] will continue to change between -90 and 90!

If you don’t understand it very well, it’s okay. We can write a demo to verify it~


3. A simple Demo helps us understand the changes of these three values:

Operation rendering :

Implementation code :

Layout code: activity_main.xml :

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="5dp">

    <TextView
        android:id="@+id/tv_value1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="azimuth"
        android:textSize="18sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tv_value2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="tilt angle"
        android:textSize="18sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tv_value3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="scroll angle"
        android:textSize="18sp"
        android:textStyle="bold" />

</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity implements SensorEventListener {

    private TextView tv_value1;
    private TextView tv_value2;
    private TextView tv_value3;
    private SensorManager sManager;
    private Sensor mSensorOrientation;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        mSensorOrientation = sManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
        sManager.registerListener(this, mSensorOrientation, SensorManager.SENSOR_DELAY_UI);
        bindViews();
    }

    private void bindViews() {
        tv_value1 = (TextView) findViewById(R.id.tv_value1);
        tv_value2 = (TextView) findViewById(R.id.tv_value2);
        tv_value3 = (TextView) findViewById(R.id.tv_value3);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        tv_value1.setText("方位角:" + (float) (Math.round(event.values[0] * 100)) / 100);
        tv_value2.setText("Tilt angle: " + (float) (Math.round(event.values[1] * 100)) / 100);
        tv_value3.setText("Scroll angle: " + (float) (Math.round(event.values[2] * 100)) / 100);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }
}

The code is very simple~ If you want to truly experience the changes of these three values, just run the program and turn your phone around to see~


4. A simple version of the text compass example

Let's write a simple text version of the compass to experience the experience. When the text shows true south, it means that the direction directly in front of the phone is south!

Operation rendering :

Code implementation :

Custom View: CompassView.java

/**
 * Created by Jay on 2015/11/14 0014.
 */
public class CompassView extends View implements Runnable{

    private Paint mTextPaint;
    private int sWidth,sHeight;
    private float dec = 0.0f;
    private String msg = "True North 0°";

    public CompassView(Context context) {
        this(context, null);
    }

    public CompassView(Context context, AttributeSet attrs) {
        super(context, attrs);
        sWidth = ScreenUtil.getScreenW(context);
        sHeight = ScreenUtil.getScreenH(context);
        init();
        new Thread(this).start();
    }



    public CompassView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    private void init() {

        mTextPaint = new Paint();
        mTextPaint.setColor(Color.GRAY);
        mTextPaint.setTextSize(64);
        mTextPaint.setStyle(Paint.Style.FILL);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawText(msg, sWidth / 4 , sWidth / 2, mTextPaint);
    }

    //Update compass angle
    public void setDegree(float degree)
    {
        //Set sensitivity
        if(Math.abs(dec - degree) >= 2 )
        {
            dec = degree;
            int range = 22;
            String degreeStr = String.valueOf(dec);

            // Point to true north
            if(dec > 360 - range && dec < 360 + range)
            {
                msg = "True North" + degreeStr + "°";
            }

            // Point due east
            if(dec > 90 - range && dec < 90 + range)
            {
                msg = "Zhengdong" + degreeStr + "°";
            }

            // Point due south
            if(dec > 180 - range && dec < 180 + range)
            {
                msg = "Zhengnan" + degreeStr + "°";
            }

            // Point due west
            if(dec > 270 - range && dec < 270 + range)
            {
                msg = "due west" + degreeStr + "°";
            }

            // Point to the northeast
            if(dec > 45 - range && dec < 45 + range)
            {
                msg = "Northeast" + degreeStr + "°";
            }

            //point southeast
            if(dec > 135 - range && dec < 135 + range)
            {
                msg = "Southeast" + degreeStr + "°";
            }

            //point southwest
            if(dec > 225 - range && dec < 225 + range)
            {
                msg = "Southwest" + degreeStr + "°";
            }

            //point northwest
            if(dec > 315 - range && dec < 315 + range)
            {
                msg = "Northwest" + degreeStr + "°";
            }
        }
    }


    @Override
    public void run() {
        while(!Thread.currentThread().isInterrupted())
        {
            try
            {
                Thread.sleep(100);
            }
            catch(InterruptedException e)
            {
                Thread.currentThread().interrupt();
            }
            postInvalidate();
        }
    }
}

MainActivity.java

public class MainActivity extends AppCompatActivity implements SensorEventListener {

    private CompassView cView;
    private SensorManager sManager;
    private Sensor mSensorOrientation;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        cView = new CompassView(MainActivity.this);
        sManager = (SensorManager) getSystemService(SENSOR_SERVICE);
        mSensorOrientation = sManager.getDefaultSensor(Sensor.TYPE_ORIENTATION);
        sManager.registerListener(this, mSensorOrientation, SensorManager.SENSOR_DELAY_UI);
        setContentView(cView);
    }


    @Override
    public void onSensorChanged(SensorEvent event) {
        cView.setDegree(event.values[0]);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        sManager.unregisterListener(this);
    }
}

This is the prototype of a very simple compass. If you are interested, you can draw your own compass and pointer, and then implement a good-looking compass.

Guess you like

Origin blog.csdn.net/leyang0910/article/details/132438455