핸드폰에 내장된 근접 센서는 전화를 받을 때 화면을 귀나 볼로 터치 해서 엉뚱한 작동을 하지 못하게 하기 위해 화면을 잠그거나 할 때 사용합니다. 

물론 스피커 폰을 사용하거나 ARS등의 서비스를 이용하기 위해 몸에서 멀어지면 다시 화면이 켜지게 됩니다.



1. Sensor event data


센서를 작동 시키면 각 센서마다 이벤트가 작동하여 리턴 값을 받아 올 수 있습니다.

이 값이 바로 우리가 필요로 하는 값으로 각 센서 별로 이벤트 개수 및 값이 다르게 전달 됩니다.

근접 센서는 1개의 이벤트 값을 받을 수 있고 그 수치의 단위는 센티미터(cm) 입니다.

 


1.1 근접 센서 이벤트 값



근접 센서가 작동을 하면 값이 변경 될 때마다 이벤트가 발행 하고 그 값을 넘겨주게 되어 있습니다.

그럼 이론 상으로는 그 값을 받아서 어플리케이션을 작성하면 됩니다.

원래 proximity sensor는 이벤트 값으로 물체와의 거리를 넘겨줘야 하지만 안타깝게도 대부분의 핸드폰들은

멀거나 가깝거나 두 가지만 감지할 정도의 간단한 기능을 가진 센서를 내장하고 있습니다.


 Sensor

 Sensor event data

 표현 값

 측정 단위

 TYPE_PROXIMITY

 SensorEvent.values[0]

 물체와의 거리

 cm



1.2 센서의 이벤트 비율(rate)


센서로부터 얼마나 자주 값을 받을 것인가에 대한 설정은 registerListener() 메소드를 이용하여 설정 합니다.


- SENSOR_DELAY_NORMAL : 200,000 microsecond delay

- SENSOR_DELAY_UI : 60,000 microsecond delay

- SENSOR_DELAY_GAME : 20,000 microsecond delay

- SENSOR_DELAY_FASTEST : 0 microsecond delay

 


2. 근접센서 프로그램


2.1 신규 프로젝트 생성

신규로 프로젝트를 생성 하고 프로젝트 명 및 기타 사항은 본인의 기호에 맞게 설정 합니다.

2.2 AndroidManifest.xml


어플리케이션에 대한 정보를 담고 있는 AndroidManifest.xml에 근접 선서 사용 권한을 기입한다.
<uses-permission android:name="android.hardware.sensor.proximity"/>
테스트 해보니 이 설정을 해도 그만 안해도 그만인 것 같다.  근접 센서를 가지고 좀더 상세한 어플리케이션을 만들 때는 필요할지 모르겠네요.


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.will.proximitysensor">
    <uses-permission android:name="android.hardware.sensor.proximity"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>


2.3 Layout 작성


센서 작동에 대한 간단한 테스트만 진행 하기 때문에 센서에서 오는 값을 출력 할 수 있을 정도의 화면만 구성 한다.

tvTitle TextView는 고정해서 Proximity Sensor를 출력 하고 센서로부터 받아온 값은 tvProximity TextView에 출력 한다.

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Proximity Sensor"
        android:layout_marginTop="50dp"
        android:textSize="30dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/tvProximity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/tvTitle"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:textSize="20dp"
        android:text="0"
        />
</android.support.constraint.ConstraintLayout>



2.4 Java Source


Sensor는 다른 어플리케이션을 사용하기 위해 일시 중지 되거나 화면을 종료(turn off)해도 계속 작동하고 있으며 전력을 소모하고 있습니다.

이를 방지하기 위해서는 어플리케이션을 완전 종료하거나 다른 어플리케이션에 의해 일시 중지되는 경우 센서의 작동을 중지 시켜주고

이벤트를 받아 다시 센서관련 어플리케이션이 활성화 되었을 경우 작동이 되도록 하여야 합니다.

그러기 위해서 onPause()에서는 중지하고 onResume()에서는 활성화 하도록 코드를 추가 합니다.

 

- 센서로 부터의 값을 받아 올 수 있도록 classSensorEventListenerimplements 시켜 줍니다.

- 받아온 값을 보여줄 TextView를 대입 합니다. : tvProximity = (TextView)findViewById(R.id.tvProximity);

- Sensor proximitySensor 센서를 선언하고 sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY); 근접선세의 값을 할당 합니다.

- 근접 센서가 없으면 Toast를 이용해 화면에 잠시 메시지를 보여 줍니다.

- onSensorChanged() 함수에서 이벤트 값을 이용하여 0인 경우 [Near]이라고 표시하고 그 이외에는 [Far]와 거리를 표기 합니다.

  정교한 센서가 아닌 경우 대부분 5.0 또는 9.0만 표시 됩니다.

public class MainActivity extends AppCompatActivity implements SensorEventListener{

    private SensorManager sensorManager;
    TextView tvProximity;

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

        tvProximity = (TextView)findViewById(R.id.tvProximity);
        sensorManager = (SensorManager)getSystemService(Context.SENSOR_SERVICE);
        Sensor proximitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
        if(proximitySensor == null) {
            Toast.makeText(this, "No Proximity Sensor Found", Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        sensorManager.registerListener(this,
                sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY),
                SensorManager.SENSOR_DELAY_NORMAL);
    }

    @Override
    protected void onPause() {
        super.onPause();
        sensorManager.unregisterListener(this);
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if(event.sensor.getType() == Sensor.TYPE_PROXIMITY) {
            if(event.values[0] == 0) {
                tvProximity.setText("Near : " + String.valueOf(event.values[0]));
            } else {
                tvProximity.setText(" Far :" + String.valueOf(event.values[0]));
            }
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        switch (accuracy) {
            case SensorManager.SENSOR_STATUS_UNRELIABLE:
                Toast.makeText(this, "UNRELIABLE", Toast.LENGTH_SHORT).show();
                break;
            case SensorManager.SENSOR_STATUS_ACCURACY_LOW:
                Toast.makeText(this, "LOW", Toast.LENGTH_SHORT).show();
                break;
            case SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM:
                Toast.makeText(this, "MEDIUM", Toast.LENGTH_SHORT).show();
                break;
            case SensorManager.SENSOR_STATUS_ACCURACY_HIGH:
                Toast.makeText(this, "HIGH", Toast.LENGTH_SHORT).show();
                break;
        }
    }
}



3. 결과


3.1 결과 화면


프로젝트를 실행 할하고 AVD Manager에서 생성한 가상 디바이스가 아닌 실제 핸드폰에서 테스트한 결과 아래와 같은 화면이 나옵니다.


proximity sensor android



3.2 Source Code


첨부된 소스파일을 다운받아 적당한 곳에 압축을 풀고 Android Studio를 이용하여 File > Open 메뉴로 프로젝트 열고 실행을 합니다.

테스트를 위해서 Target Device는 개인 핸드폰으로 설정을 합니다.

각자의 개발 툴 버전이 달라 update가 진행 되기도 하고 개발을 진행한 디렉토리 정보등의 환경도 차이가 나서 오류가 발생 하기도 합니다.

만약 실행 중 팝업으로 오류가

Installation failed with message Invalid File: E:\android\app\build\intermediates\split-apk\debug\slices\slice_3.apk

이것 비스무리 하게 발생한다면 Android Studio 상단 Build 메뉴 에서

Build > Clean Project

Build > Rebuild Project

메뉴를 이용하여 기존 Build 정보를 삭제 하고 다시 실행 하면 됩니다.


ProximitySensor.7z


 

3.3 APK File


Android Studio가 없거나 귀찮아 첨부된 APK 파일을 이용하여 핸드폰에서 실행을 하려면 출처를 알 수 없은 앱 설치를 가능하게 하고

실행을 해야 합니다. 

테스트 후에는 다시 출처를 알 수 없는 앱 설치 가능을 차단 해 줍니다.

어디서 설정을 변경 했는지 모르겠다 싶으면 핸드폰에 있는 은행 앱을 하나 실행 하면 출처를 알 수 없는 앱 설치 설정 기능을 차단하라고

메시지가 나오면서 변경할 수 있는 위치로 이동할 수 있도록 되어 있으니 바꿔주면 됩니다.


ProximitySensor.apk


- copy coding -


+ Recent posts