Sensors API คืออินเทอร์เฟสของแพลตฟอร์ม Android สำหรับเข้าถึงเซนเซอร์ฮาร์ดแวร์ของอุปกรณ์ API มีวิธีการแบบครบวงจรในการรับข้อมูลจากมาตรความเร่ง ไจโรสโคป มาตรแม่เหล็ก เซนเซอร์แสง และเซนเซอร์อื่นๆ ตามข้อมูลของ Google, 2026 อุปกรณ์ Android สมัยใหม่มากกว่า 95% ติดตั้งเซนเซอร์อย่างน้อยสามประเภท ซึ่งเปิดโอกาสมากมายสำหรับการพัฒนาแอปพลิเคชันที่รับรู้บริบท
ประเด็นสำคัญ
Sensors API คืออินเทอร์เฟสซอฟต์แวร์ของ Android Framework ที่ให้นักพัฒนาสามารถเข้าถึงเซนเซอร์ฮาร์ดแวร์ของอุปกรณ์มือถือ API เป็นส่วนหนึ่งของ Android SDK ตั้งแต่เวอร์ชัน 1.0 และพร้อมใช้งานผ่านแพ็คเกจ android.hardware อินเทอร์เฟสนี้จะขจัดความแตกต่างระหว่างการใช้งานเซนเซอร์จากผู้ผลิตต่างๆ — Qualcomm, MediaTek, Samsung Exynos — และให้โมเดลการทำงานกับเซนเซอร์แบบครบวงจร
API อนุญาตให้ดำเนินการหลักสามอย่าง: รับรายการเซนเซอร์ที่มีอยู่ ลงทะเบียนผู้ฟังเพื่อรับข้อมูล และจัดการอัตราการอัปเดต SensorManager ทำหน้าที่เป็นจุดเข้าถึงกลางสำหรับการดำเนินการทั้งหมด ระบบแจ้งเตือนแอปพลิเคชันผ่าน callback onSensorChanged โดยส่งออบเจ็กต์ SensorEvent พร้อมอาร์เรย์ของค่า float
ตลอดการดำรงอยู่ของ Android API ได้ผ่านหลายขั้นตอนของการพัฒนา เวอร์ชัน 2.3 (Gingerbread) ได้แนะนำการสนับสนุนการประมวลผลแบบแบตช์ — การจัดกลุ่มเหตุการณ์เซนเซอร์เพื่อลดการใช้พลังงาน Android 4.0 (Ice Cream Sandwich) เพิ่มเซนเซอร์เสมือน Gravity และ Linear Acceleration ตั้งแต่ Android 8.0 เป็นต้นมา ระบบได้จำกัดการเข้าถึงเซนเซอร์ในพื้นหลังเพื่อเพิ่มความเป็นส่วนตัว
val sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
val sensorList: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_ALL)
sensorList.forEach { sensor ->
Log.d("เซนเซอร์", "${sensor.name} — ${sensor.type}")
}
ไม่ใช่อุปกรณ์ทั้งหมดที่มีชุดเซนเซอร์เหมือนกัน แอปพลิเคชันต้องตรวจสอบความพร้อมใช้งานของเซนเซอร์เฉพาะก่อนลงทะเบียนผู้ฟัง โปรแกรมจำลอง Android รองรับเฉพาะเซนเซอร์ชุดจำกัด — มาตรความเร่งและมาตรแม่เหล็ก การทดสอบเซนเซอร์อื่นต้องใช้อุปกรณ์จริง ตั้งแต่ Android 12 เป็นต้นไป แอปพลิเคชันต้องประกาศการใช้เซนเซอร์ใน manifest
Android จัดประเภทเซนเซอร์ทั้งหมดเป็นสามหมวดหมู่: Motion, Position และ Environment เซนเซอร์ Motion รวมถึงมาตรความเร่ง ไจโรสโคป และเครื่องนับก้าว เซนเซอร์ Position รวมถึงมาตรแม่เหล็กและการวางแนว เซนเซอร์ Environment รวมถึงแสง ความดัน อุณหภูมิ และความชื้น
| หมวดหมู่ | เซนเซอร์ | ประเภท (ค่าคงที่) | กายภาพ/เสมือน |
|---|---|---|---|
| Motion | มาตรความเร่ง | TYPE_ACCELEROMETER | กายภาพ |
| Motion | ไจโรสโคป | TYPE_GYROSCOPE | กายภาพ |
| Motion | เครื่องนับก้าว | TYPE_STEP_COUNTER | กายภาพ |
| Motion | Gravity | TYPE_GRAVITY | เสมือน |
| Position | มาตรแม่เหล็ก | TYPE_MAGNETIC_FIELD | กายภาพ |
| Position | Rotation Vector | TYPE_ROTATION_VECTOR | เสมือน |
| Environment | แสง | TYPE_LIGHT | กายภาพ |
| Environment | ความดัน | TYPE_PRESSURE | กายภาพ |
มาตรความเร่ง วัดความเร่งเป็น m/s² ตามสามแกน — X, Y และ Z ค่าต่างๆ รวมถึงแรงโน้มถ่วง (9.8 m/s² ตามแกน Z ในขณะหยุดนิ่ง) ไจโรสโคปวัดความเร็วเชิงมุมเป็น rad/s — ความเร็วในการหมุนของอุปกรณ์รอบแต่ละแกน การรวมกันของเซนเซอร์ทั้งสองนี้ใช้ในการนำทาง เกม และแอปพลิเคชัน AR
class SensorActivity : Activity(), SensorEventListener {
override fun onSensorChanged(event: SensorEvent) {
if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) {
val x = event.values[0]
val y = event.values[1]
val z = event.values[2]
textView.text = "X: $x, Y: $y, Z: $z"
}
}
override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
}
มาตรแม่เหล็ก (TYPE_MAGNETIC_FIELD) วัดสนามแม่เหล็กเป็นไมโครเทสลา (µT) ตามสามแกน ใช้เป็นเข็มทิศดิจิทัล — เมื่อรวมกับมาตรความเร่งจะกำหนดทิศทางของอุปกรณ์ Rotation Vector เป็นเซนเซอร์เสมือนที่หลอมรวมข้อมูลจากไจโรสโคป มาตรความเร่ง และมาตรแม่เหล็กเพื่อการกำหนดทิศทางที่แม่นยำ
เซนเซอร์แสง (TYPE_LIGHT) วัดระดับแสงโดยรอบเป็นลักซ์ (lx) ใช้สำหรับปรับความสว่างหน้าจออัตโนมัติ เซนเซอร์ความดัน (TYPE_PRESSURE) วัดความดันบรรยากาศเป็นเฮกโตปาสกาล (hPa) — ใช้ในแอปพลิเคชันนำทางเพื่อกำหนดความสูงเหนือระดับน้ำทะเล
Sensors API สร้างขึ้นบนสถาปัตยกรรมไคลเอนต์-เซิร์ฟเวอร์ แอปพลิเคชันทำหน้าที่เป็นไคลเอนต์ และ SensorManager ทำหน้าที่เป็นบริการระบบ Android เมื่อแอปพลิเคชันลงทะเบียนผู้ฟังผ่าน registerListener SensorManager จะสื่อสารกับ HAL (ชั้นนามธรรมฮาร์ดแวร์) — ตัวขับเซนเซอร์ระดับต่ำที่ทำงานที่ระดับเคอร์เนล Linux
ตัวขับ HAL รับข้อมูลดิบจากชิปฮาร์ดแวร์ กรองสัญญาณรบกวน และส่งต่อขึ้นไปตามสแต็ก — ผ่าน SensorService (กระบวนการของระบบ) ไปยังแอปพลิเคชัน ข้อมูลจะถูกส่งเป็นออบเจ็กต์ SensorEvent ที่ประกอบด้วยอาร์เรย์ของค่า float values และประทับเวลาเป็นนาโนวินาที อัตราเหตุการณ์ขึ้นอยู่กับโหมดการส่งที่เลือก
เมื่อลงทะเบียนผู้ฟัง นักพัฒนาจะระบุความล่าช้าที่ต้องการระหว่างเหตุการณ์โดยใช้ค่าคงที่ SENSOR_DELAY_NORMAL (200 ms), SENSOR_DELAY_UI (60 ms), SENSOR_DELAY_GAME (20 ms) และ SENSOR_DELAY_FASTEST (0 ms — อัตราสูงสุด) อัตราจริงอาจแตกต่างกัน — ระบบจะเพิ่มประสิทธิภาพการใช้พลังงาน
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
sensorManager.registerListener(
this,
sensor,
SensorManager.SENSOR_DELAY_GAME
)
ตั้งแต่ Android 2.3 เป็นต้นไป เซนเซอร์รองรับโหมดแบตช์ — เหตุการณ์จะสะสมในบัฟเฟอร์ FIFO และส่งเป็นชุดเดียว ช่วยให้โปรเซสเซอร์อยู่ในโหมดสลับได้นานขึ้น ลดการใช้พลังงานได้ถึง 60% ขนาดบัฟเฟอร์ขึ้นอยู่กับชิปเซนเซอร์และระบุในฟิลด์ Sensor.fifoMaxEventCount
SensorManager เป็นบริการของระบบที่พร้อมใช้งานผ่าน getSystemService(Context.SENSOR_SERVICE) โดยมีวิธีการสำหรับรับรายการเซนเซอร์ รับเซนเซอร์เริ่มต้นเฉพาะ และลงทะเบียน/ยกเลิกผู้ฟัง SensorManager เป็นซิงเกิลตัน — หนึ่งอินสแตนซ์สำหรับทั้งแอปพลิเคชัน
ก่อนใช้เซนเซอร์ คุณต้องตรวจสอบความพร้อมใช้งานของเซนเซอร์ วิธีการ getDefaultSensor(type) จะคืนค่า null หากเซนเซอร์ไม่มีอยู่ในอุปกรณ์ การรับ null โดยไม่ตรวจสอบจะทำให้เกิด NullPointerException เมื่อลงทะเบียนผู้ฟัง วิธีการ getSensorList(type) จะคืนค่ารายการของเซนเซอร์ทั้งหมด
fun checkSensorAvailability(type: Int): Boolean {
val sensorManager =
getSystemService(Context.SENSOR_SERVICE) as SensorManager
return sensorManager.getDefaultSensor(type) != null
}
// การใช้งาน:
if (checkSensorAvailability(Sensor.TYPE_GYROSCOPE)) {
Log.d("เซนเซอร์", "ไจโรสโคปพร้อมใช้งาน")
}
ผู้ฟังจะถูกลงทะเบียนผ่าน registerListener(listener, sensor, delay) สำคัญ: คุณต้องยกเลิกผู้ฟังในวิธีการ onPause() ผ่าน unregisterListener(listener) หากไม่ทำเช่นนั้น แอปพลิเคชันจะยังคงรับเหตุการณ์เซนเซอร์ต่อไป ทำให้แบตเตอรี่หมดแม้ในพื้นหลัง Android 8+ จะแสดงคำเตือนใน logcat เกี่ยวกับผู้ฟังที่ไม่ได้ยกเลิก
วิธีการ onAccuracyChanged(sensor, accuracy) จะถูกเรียกเมื่อความแม่นยำของเซนเซอร์เปลี่ยนแปลง ค่า: SENSOR_STATUS_ACCURACY_HIGH, MEDIUM, LOW และ UNRELIABLE เมื่อได้รับ UNRELIABLE ข้อมูลเซนเซอร์ควรถูกละเว้นจนกว่าความแม่นยำจะกลับคืนมา ตัวอย่างเช่น มาตรแม่เหล็กต้องการการสอบเทียบ — การเขย่าอุปกรณ์เป็นรูปเลขแปด
มาดูตัวอย่างการใช้งาน Sensors API ในแอปพลิเคชัน Android ด้วย Kotlin ตัวอย่างแรก — การกำหนดทิศทางหน้าจอโดยใช้มาตรความเร่ง ตัวอย่างที่สอง — การอ่านข้อมูลมาตรแม่เหล็กพร้อมการสอบเทียบ ตัวอย่างที่สาม — ตัวตรวจจับก้าวโดยใช้เครื่องนับก้าว
ใช้การรวมกันของมาตรความเร่งและมาตรแม่เหล็กเพื่อกำหนดทิศทาง วิธีการ SensorManager.getRotationMatrix() คำนวณเมทริกซ์การหมุน และ getOrientation() แยกมุม pitch, roll และ azimuth Azimuth (ทิศทาง) — มุมเทียบกับทิศเหนือแม่เหล็กเป็นเรเดียน
val gravity = FloatArray(3)
val geomagnetic = FloatArray(3)
val rotationMatrix = FloatArray(9)
val orientation = FloatArray(3)
SensorManager.getRotationMatrix(
rotationMatrix, null, gravity, geomagnetic
)
SensorManager.getOrientation(rotationMatrix, orientation)
// orientation[0] — azimuth, [1] — pitch, [2] — roll
val azimuthDeg = Math.toDegrees(orientation[0].toDouble())
เครื่องนับก้าว (TYPE_STEP_COUNTER) คืนค่าจำนวนก้าวทั้งหมดที่ผู้ใช้เดินตั้งแต่การรีบูตอุปกรณ์ครั้งล่าสุด เซนเซอร์ทำงานที่ระดับฮาร์ดแวร์ — ทำงานแม้เมื่อแอปพลิเคชันไม่ได้ทำงาน ในการรับก้าวต่อเซสชัน คุณต้องบันทึกค่าเริ่มต้นและคำนวณความแตกต่าง
var initialSteps = 0
var isInitialized = false
override fun onSensorChanged(event: SensorEvent) {
if (event.sensor.type == Sensor.TYPE_STEP_COUNTER) {
if (!isInitialized) {
initialSteps = event.values[0].toInt()
isInitialized = true
}
val currentSteps = event.values[0].toInt()
val sessionSteps = currentSteps - initialSteps
Log.d("ก้าว", "ก้าวต่อเซสชัน: $sessionSteps")
}
}
เซนเซอร์แสง ช่วยให้ปรับอินเทอร์เฟสให้เข้ากับสภาพแวดล้อม ในที่แสงน้อย (น้อยกว่า 10 lx) คุณสามารถสลับไปยังโหมดมืด ในแสงแดดจ้า (มากกว่า 10000 lx) คุณสามารถเพิ่มคอนทราสต์ การกรองสัญญาณรบกวนใช้ค่าเฉลี่ยเคลื่อนที่ของ 5 ค่าล่าสุด
Android มีเซนเซอร์เสมือนหลายตัวที่ไม่มีเทียบเท่าฮาร์ดแวร์โดยตรง เซนเซอร์เสมือน คำนวณค่าการอ่านโดยอาศัยการรวมกันของเซนเซอร์ทางกายภาพ ช่วยลดภาระของนักพัฒนา — ระบบเองจะใช้อัลกอริทึมการหลอมรวมข้อมูล
เซนเซอร์ Gravity (TYPE_GRAVITY) แยกองค์ประกอบแรงโน้มถ่วงจากการอ่านค่ามาตรความเร่งโดยใช้ตัวกรองความถี่ต่ำผ่าน Linear Acceleration (TYPE_LINEAR_ACCELERATION) ในทางกลับกัน จะลบแรงโน้มถ่วงและเหลือเพียงความเร่งเชิงเส้นของอุปกรณ์ ผลรวมของ Gravity และ Linear Acceleration ให้ค่าการอ่านมาตรความเร่งดิบ
Rotation Vector — เซนเซอร์เสมือนที่ซับซ้อนที่สุด รวมข้อมูลจากไจโรสโคป (การเปลี่ยนแปลงความถี่สูง) มาตรความเร่ง (เวกเตอร์แรงโน้มถ่วง) และมาตรแม่เหล็ก (ทิศทางเทียบกับทิศเหนือ) ผลลัพธ์คือควอเทอร์เนียนที่อธิบายทิศทางสัมบูรณ์ของอุปกรณ์ในอวกาศ ใช้ในแอปพลิเคชัน AR และชุดหูฟัง VR
Game Rotation Vector — เวอร์ชันที่เรียบง่ายของ Rotation Vector โดยไม่ใช้มาตรแม่เหล็ก ให้ความแม่นยำของทิศทางต่ำกว่า แต่อัตราการอัปเดตและความเสถียรสูงกว่า แนะนำสำหรับเกมที่ต้องการความหน่วงต่ำมากกว่าทิศทางสัมบูรณ์เทียบกับทิศเหนือ
เซนเซอร์ เป็นหนึ่งในส่วนประกอบที่ใช้พลังงานมากที่สุดของอุปกรณ์ มาตรความเร่งและไจโรสโคปที่อัตราการสอบถามสูงสุดสามารถทำให้แบตเตอรี่หมดใน 3–4 ชั่วโมงของการทำงานต่อเนื่อง การเพิ่มประสิทธิภาพการใช้เซนเซอร์เป็นงานที่สำคัญสำหรับแอปพลิเคชันใดๆ ที่ใช้ Sensors API
อย่าใช้ SENSOR_DELAY_FASTEST โดยไม่จำเป็น สำหรับแอนิเมชัน UI SENSOR_DELAY_UI (60 ms) ก็เพียงพอ สำหรับการตรวจจับทิศทางหน้าจอ — SENSOR_DELAY_NORMAL (200 ms) ยิ่งอัตราสูงเท่าไร โปรเซสเซอร์ก็ใช้เวลาในสถานะทำงานมากขึ้นเท่านั้น ความแตกต่างระหว่าง NORMAL และ FASTEST ในการใช้พลังงานสูงถึง 10 เท่า
ตั้งแต่ Android 8.0 (API 26) เป็นต้นไป แอปพลิเคชันในพื้นหลังจะได้รับเหตุการณ์เซนเซอร์ด้วยอัตราที่ลดลง ใน Android 12+ การเข้าถึงเซนเซอร์ Motion และ Position ในพื้นหลังต้องได้รับสิทธิ์ BODY_SENSORS_BACKGROUND ยกเลิกผู้ฟังเมื่อแอปพลิเคชันเข้าสู่พื้นหลัง — ซึ่งจะยืดอายุแบตเตอรี่ของอุปกรณ์
ใช้การประมวลผลแบบแบตช์ผ่านวิธีการ registerListener(listener, sensor, delay, maxReportLatencyUs) พารามิเตอร์ maxReportLatencyUs กำหนดความหน่วงสูงสุดในการส่งเหตุการณ์เป็นไมโครวินาที ด้วยค่า 1000000 (1 วินาที) เหตุการณ์จะสะสมในบัฟเฟอร์ FIFO ของเซนเซอร์และส่งครั้งต่อวินาที — โปรเซสเซอร์จะตื่นน้อยลง
คำถามที่พบบ่อย
ชุดขั้นต่ำคือ มาตรความเร่ง และมาตรแม่เหล็ก เซนเซอร์ทั้งสองนี้มีอยู่ในมากกว่า 95% ของอุปกรณ์ ไจโรสโคป เซนเซอร์แสง และเซนเซอร์ระยะใกล้ — ใน 70–80% ของรุ่นสมัยใหม่ เซนเซอร์อื่นๆ (ความดัน อุณหภูมิ ความชื้น เครื่องนับก้าว) พบได้น้อยกว่าและขึ้นอยู่กับระดับราคาของอุปกรณ์
TYPE_ACCELEROMETER คืนค่าความเร่งรวมรวมถึงแรงโน้มถ่วง (9.8 m/s²) TYPE_LINEAR_ACCELERATION คืนค่าความเร่งที่ไม่รวมแรงโน้มถ่วง — เฉพาะความเร่งจากการเคลื่อนที่ของอุปกรณ์ หากอุปกรณ์อยู่นิ่ง มาตรความเร่งจะแสดง 9.8 m/s² ตามแกน Z ในขณะที่ Linear Acceleration จะแสดง 0 บนทุกแกน
ใช้ getPackageManager().hasSystemFeature() พร้อมค่าคงที่ที่เหมาะสม: FEATURE_SENSOR_ACCELEROMETER, FEATURE_SENSOR_GYROSCOPE, FEATURE_SENSOR_PROXIMITY และอื่นๆ วิธีอื่นคือเรียก getDefaultSensor(type) และตรวจสอบผลลัพธ์เป็น null วิธีแรกเหมาะกว่าสำหรับการตรวจสอบระหว่างการเริ่มต้น
ข้อมูลดิบจากเซนเซอร์มีสัญญาณรบกวน สำหรับการปรับให้เรียบ ให้ใช้ ตัวกรองความถี่ต่ำผ่าน: newValue = alpha * rawValue + (1 — alpha) * previousValue สัมประสิทธิ์ alpha 0.1–0.3 ให้สมดุลที่ดีระหว่างการตอบสนองและความเรียบ สำหรับไจโรสโคป จะใช้ตัวกรองความถี่สูงผ่านเพื่อกำจัดการเลื่อนของศูนย์
ได้ แต่มีข้อจำกัด ตั้งแต่ Android 8.0 เป็นต้นไป อัตราเหตุการณ์เซนเซอร์จะลดลงสำหรับแอปพลิเคชันในพื้นหลัง ตั้งแต่ Android 12 เป็นต้นไป ต้องได้รับสิทธิ์ BODY_SENSORS_BACKGROUND สำหรับการเข้าถึงเซนเซอร์ในพื้นหลัง สำหรับการทำงานในพื้นหลัง แนะนำให้ใช้ Foreground Service พร้อมการแจ้งเตือน
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม