Translate

2017년 5월 2일 화요일

Android Studio screenOrientation 고정 상태에서 360˚ 회전 감지하기



Laptop
운영체제Windows 10 Home 64bit
개발프로그램Android Studio 2.3.1
(buildToolsVersion "25.0.2")
프로젝트명OrientationTest

Mobile
모델DOOGEE X5
운영체제Android 5.1 Lollipop


screenOrientation 을 고정한 상태에서 회전을 감지해야 할 필요가 있을 수 있다.
이 때  OrientationEventListener라는 핸들러를 이용하여 방향센서의 값을 가져올 수 있다.
OrientationEventListener는 이름 그대로 기기의 기울기가 변할 때 감지하는 역할을 한다. 말은 이렇지만 그냥 항상 작동한다고 보면 된다.

간단한 예제를 만들어 보자.

먼저 AndroidManifest.xml 을 수정하여 activity를 portrait(세로방향)로 고정해준다.
android:screenOrientation="portrait" 한 줄만 추가해주면 된다.


<activity android:name=".MainActivity"
          android:screenOrientation="portrait">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>


그리고 xml 레이아웃은 간단하게 RelativeLayout과 LinearLayout을 통해
화면 중앙에 orientation 측정값과 위쪽 방향 화살표 ↑ 를 TextView로 띄워준다.

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:orientation="vertical">

        <TextView
            android:id="@+id/text_orientation"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="40dp"
            android:text="Orientation: 0"/>

        <TextView
            android:id="@+id/text_arrow"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textAlignment="center"
            android:textSize="40dp"
            android:text="↑"/>

    </LinearLayout>

</RelativeLayout>



  
 
이제 main 함수를 작성해준다.
이벤트 발생 시(센서 변화) 실행될 내용은 onOrientationChanged 안에 입력하면 된다.
또한 canDetectOrientation 메소드를 통해 핸들러가 정상적으로 작동하는지 여부를 판단할 수 있다.

MainActivity.java
package com.orientationtest;

import android.hardware.SensorManager;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.OrientationEventListener;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    private TextView mTextOrient;
    private TextView mTextArrow;
    private OrientationEventListener orientEventListener;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTextOrient = (TextView) findViewById(R.id.text_orientation);
        mTextArrow = (TextView) findViewById(R.id.text_arrow);
        
        //보통 속도(SENSOR_DELAY_NORMAL)로 측정
        orientEventListener = new OrientationEventListener(this,
                SensorManager.SENSOR_DELAY_NORMAL) {

            @Override
            public void onOrientationChanged(int arg0) {
                
                //arg0: 기울기 값
                
                mTextOrient.setText("Orientation: "
                        + String.valueOf(arg0));

                // 0˚ (portrait)
                if(arg0 >= 315 || arg0 < 45) {
                    mTextArrow.setRotation(0);
                }

                // 90˚
                else if(arg0 >= 45 && arg0 < 135) {
                    mTextArrow.setRotation(270);
                }

                // 180˚
                else if(arg0 >= 135 && arg0 < 225) {
                    mTextArrow.setRotation(180);
                }

                // 270˚ (landscape)
                else if(arg0 >= 225 && arg0 < 315)
                {
                    mTextArrow.setRotation(90);
                }
            }
        };

        //핸들러 활성화
        orientEventListener.enable();

        //인식 오류 시, Toast 메시지 출력
        if (!orientEventListener.canDetectOrientation()) {
            Toast.makeText(this, "Can't DetectOrientation",
                    Toast.LENGTH_LONG).show();
            finish();
        }
    }
}


if문을 통해 45˚씩 여유 범위를 두어 각 방향에 따라 화살표가 회전하여 항상 위를 가리키도록 하였다.

이 부분에서는 onConfigurationChanged 핸들러나 Display.getRotation 함수가 상수형 결과값을 받아오기 때문에 더 편리하지만, 현재 상태를 받아오기 때문에 고정 상태에서는 사용할 수 없다.


결과동영상



참고 사이트 : http://mainia.tistory.com/2208


+ 위 링크에는 나와있지만 테스트 결과 SensorManager는 이 프로그램에서는 필요 없는 듯 하다.

+ 평면을 기준으로 한 기울기 값을 측정하기 때문에 기기를 수평으로 눕혀 놓으면 제대로 측정하지 못한다.