화면 회전을 센서로 체크하기.

|

샘플용 앱을 개발하다가 다음과 같은 요구사항이 발생했다.


1. 화면은 자동으로 회전되지 않는다.

   [특정 기능을 통해 Portrait/landscape 모드를 지원한다.]


2. 물리적으로 화면이 돌아갔을때, 이벤트가 발생되어야 한다.


<그림 예시>






여러가지 방안을 찾아봤지만...


화면을 고정시켜야한 상태에서 이벤트를 받아야하기 때문에 센서를 이용하는 방법외에는 찾지 못했다.

[있을지도 모르는데 일단 찾지는 못 함...]




사용할 센서


Sensor.TYPE_ROTATION_VECTOR ( 또는 Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR 등)


 * 센서 사용시에 SensorManager의 getDefaultSensor를 통해서 디바이스가 해당 센서를 제공하는지 체크가 필요하다.

   [ 조건문으로  SensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) != null 를 확인해서 null 인 경우 다른 ROTATION_VECTOR 센서를 사용하자.]




알고리즘 순서


1. 해당 센서의 리스너를 이용해서 roll 과 pitch를 계산한다.


2. 계산된 roll과 pitch 값을 이용하여 이벤트를 발생시킨다.


<roll , pitch>





<코드>


    private static final int RADIAN_TO_DEGREE = -57;

//아래 checkOrientation 에서 나오는 값이 라디안 입니다.

//라디안으로 값을 계산하기엔 다소 불편함이 있어 일반적인 도로 단위를 바꿈.

//정확한 값은 57.xxxxxxx 지만 매우 정확한 값을 요구하지 않기 때문에 대략 적인 값을 사용함.


    .....


    @Override

    public void onAccuracyChanged(Sensor sensor, int accuracy) {

        // TODO Auto-generated method stub

    }


    @Override

    public void onSensorChanged(SensorEvent event) {

        if (event.sensor == mRotationSensor) {

            if (event.values.length > 4) {

                float[] truncatedRotationVector = new float[4];

                System.arraycopy(event.values, 0, truncatedRotationVector, 0, 4);

                checkOrientation(truncatedRotationVector);

            } else {

                checkOrientation(event.values);

            }

        }

    }


    private void checkOrientation(float[] vectors) {

        float[] rotationMatrix = new float[9];

        SensorManager.getRotationMatrixFromVector(rotationMatrix, vectors);

        int axisX = SensorManager.AXIS_X;

        int axisZ = SensorManager.AXIS_Z;

        float[] adjustedRotationMatrix = new float[9];

        SensorManager.remapCoordinateSystem(rotationMatrix, axisX, axisZ, adjustedRotationMatrix);

        float[] orientation = new float[3];

        SensorManager.getOrientation(adjustedRotationMatrix, orientation);

        float azimuch = orientation[0] * RADIAN_TO_DEGREE;

        float pitch = orientation[1] * RADIAN_TO_DEGREE;

        float roll = orientation[2] * RADIAN_TO_DEGREE;

        ((TextView)findViewById(R.id.azimuth)).setText("Azimuch: "+azimuch);

        ((TextView)findViewById(R.id.pitch)).setText("Pitch: "+pitch);

        ((TextView)findViewById(R.id.roll)).setText("Roll: "+roll);

        if(Math.abs(pitch) < 55) {    //눕혀있는 경우에는 화면 상태가 어렵다고 판단되어 특정 각도 내에서만 작동하도록 함.

            ((TextView) findViewById(R.id.orientation)).setText(calculateOrientation((int) roll, (int) pitch));

        }

    }


    private String calculateOrientation(int roll, int pitch) {

        if((-120 < roll && roll < -60) || (60 < roll && roll <120)){

            return "LANDSCAPE " + roll + "/" + pitch;

        }else if(( -30 < roll && roll < 30) || (150 < roll && roll < 180) || (-180 < roll && roll < -150)){

            return "PORTRAIT " + roll + "/" + pitch;

        }else{

            return "UNKNOWN " + roll + "/" + pitch;

        }

    }



<결과>






화면 회전 소스.zip






'Android > etc' 카테고리의 다른 글

암호화 적용 MessageDigest  (0) 2018.09.14
Kakao REST API 로컬 연동  (1) 2018.09.14
Android VLC Compile  (0) 2018.02.06
화면 코드로 회전 시키기  (0) 2018.01.23
MediaPlayer를 위한 Service 사용  (0) 2017.12.26
And