03 March 2013

Sensor API in Android - การใช้งาน Proximity Sensor

Updated on

        คราวนี้เป็นบทความเกี่ยวกับ Proximity Sensor ที่เอาไว้วัดระยะทางสั้นๆที่ใช้หลักการทางแสง โดยพบได้บนอุปกรณ์แอนดรอยด์ที่สามารถโทรศัพท์ได้


        Sensor ตัวนี้จะมีไว้เพื่อปิดหน้าจอในเวลาที่ผู้ใช้โทรศัพท์ เพราะว่าผู้ใช้ต้องเอาหน้าแนบกับจอ ดังนั้นถ้าไม่ปิดหน้าจอก็จะทำให้เผลอไปกดโดนปุ่มวางสายได้นั่นเอง

        โดย Proximity Sensor จะมีแหล่งกำเนิดแสงอินฟราเรดและตัวรับแสงอินฟราเรดอยู่คู่กัน เมื่อผู้ใช้เอาหน้าแนบกับโทรศัพท์ แสงดอินฟราเรดที่ยิงออกมาก็จะสะท้อนกลับไปยังตัวรับ ทำให้รู้ได้ว่ามีวัตถุใดๆอยู่ข้างหน้า

        บนอุปกรณ์แอนดรอยด์แต่ละเครื่องที่มี Proximity Sensor จะมีระยะการตรวจจับที่ไม่เท่ากัน บางเครื่องก็ 3cm บ้างก็ 5cm หรือ 10cm ต่างกันไป ดังนั้นอย่าแปลกใจถ้าลองกับหลายๆเครื่องแล้วระยะที่ Sensor ทำงานนั้นไม่เหมือนกัน

        และที่สำคัญ Proximity Sensor กับ Light Sensor นั้นเป็นคนละตัวกันนะ เผื่อว่ามีผู้ที่หลงเข้ามาอ่านคนใดเข้าใจผิด โดยที่ Light Sensor จะมีไว้สำหรับวัดแสงเพื่อปรับความสว่างหน้าจอ (แต่ถ้าเป็น Light Saber จะเป็นอาวุธประจำกายของเจได)


        วิธีสังเกตง่ายๆคือ Proximity Sensor จะมีอยู่ 2 รูติดกัน ส่วน Light Sensor จะมีอยู่รูเดียว บ้างก็อยู่แยกกันและบ้างก็อยู่ติดกัน ขึ้นอยู่กับแต่ละเครื่อง


        ค่าที่อ่านได้จาก Proximity จะมีค่าอยู่แค่สองค่าคือ 0 และ X โดย X คือระยะที่ตรวจจับของแต่ละเครื่องในหน่วย cm เพราะจากที่บอกในตอนแรกคือ Proximity Sensor ของแต่ละเครื่องมีระยะตรวจจับที่ไม่เท่ากัน

        จากวีดีโอตัวอย่างจะเห็นว่า Samsung Galaxy Nexus วัดระยะได้เป็น 5cm และจากการลองกับ Samsung Galaxy Gio พบว่ามีระยะแค่ 1cm เท่านั้น

        ดังนั้นการนำไปใช้งานให้วัดแค่ว่าค่าเป็น 0 หรือไม่ ถ้าค่าเป็น 0 ก็คือมีวัตถุบังอยู่ และถ้ามีค่ามากกว่า 0 ก็คือไม่มีวัตถุบังอยู่นั่นเอง

        สำหรับการทำงานของคำสั่งหลักๆจะไม่อธิบาย ให้อ่านจากบทความ [Android Code] การใช้งาน Accelerometer แทน เพราะว่าเหมือนๆกัน (ขี้เกียจพิมพ์อธิบายซ้ำๆหลายรอบ)


        ส่วนการใช้งานก็จะเปลี่ยนคำสั่งจากของเดิมในตอนที่กำหนดค่า Sensor ที่ต้องการเรียกใช้งาน

SensorManager sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);


        และสำหรับค่าที่อ่านได้จาก Proximity มีแค่ค่าเดียวเท่านั้น ไม่เหมือนกับ Accelerometer ที่ส่งค่ามาสามตัวคือ XYZ

public void onAccuracyChanged(Sensor sensor, int acc) { }
 
public void onSensorChanged(SensorEvent event) {
    float proximity = event.values[0];
}

        ส่วนคำสั่งอื่นๆ ทั้งหมดก็จะเหมือนกับ Accelerometer


        ทีนี้ก็มาดูตัวอย่างในบทความนี้ต่อเลยดีกว่าละกัน

Main.java
package app.akexorcist.sensor_proximity;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.widget.TextView;

public class Main extends Activity {
    TextView textProximity;
    SensorManager sensorManager;
    Sensor sensor;
 
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
 
        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
        
        textProximity = (TextView) findViewById(R.id.textProximity);
    }
 
    public void onResume() {
        super.onResume();
        sensorManager.registerListener(proxiListener, sensor,SensorManager.SENSOR_DELAY_NORMAL);
    }
 
    public void onStop() {
        super.onStop();
        sensorManager.unregisterListener(proxiListener);
    }

    public SensorEventListener proxiListener = new SensorEventListener() {
        public void onAccuracyChanged(Sensor sensor, int acc) { }
 
        public void onSensorChanged(SensorEvent event) {
            float proximity = event.values[0];
            textProximity.setText("Proximity : " + (int)proximity);
        }
    };
}


main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center" >
    
    <TextView
        android:id="@+id/textProximity"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="30sp" 
        android:text="" />

</LinearLayout>


AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="app.akexorcist.sensor_proximity"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="8" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="app.akexorcist.sensor_proximity.Main"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

</manifest>


        สำหรับ Proximity Sensor มักจะใช้กับแอพฯที่ค่อนข้างเฉพาะทางพอสมควร เช่น แอพฯที่เอาไว้ปิดหน้าจอโดยไม่ต้องกดปุ่ม Power โดยจะให้ผู้ใช้เอามือปิดที่ Proximity Sensor แล้วสั่งให้ปิดหน้าจอแทนนั่นเอง และสำหรับไฟล์ตัวอย่างในบทความนี้สามารถดาวน์โหลดได้ที่ 

                Sensor-Proximity [Google Drive]

                Sensor-Proximity [GitHub]

                Sensor-Proximity [Sleeping For Less]