Sensors API — رابط پلتفرم Android برای دسترسی به سنسورهای سختافزاری دستگاه است. API روشی یکپارچه برای دریافت داده از شتابسنج، ژیروسکوپ، مغناطیسسنج، سنسور نور و سایر حسگرها فراهم میکند. طبق دادههای Google, 2026، بیش از ۹۵٪ دستگاههای مدرن Android حداقل به سه نوع سنسور مجهز هستند که فرصتهای گستردهای برای توسعه برنامههای وابسته به زمینه باز میکند.
نکات اصلی
Sensors API — رابط برنامهنویسی Android Framework است که به توسعهدهندگان دسترسی به سنسورهای سختافزاری دستگاه همراه را میدهد. API از نسخه ۱.۰ بخشی از Android SDK است و از طریق بسته android.hardware در دسترس است. این رابط تفاوتهای بین پیادهسازی سنسورهای تولیدکنندگان مختلف — Qualcomm، MediaTek، Samsung Exynos — را انتزاع میکند و یک مدل یکپارچه برای کار با حسگرها فراهم میکند.
API امکان انجام سه عملیات کلیدی را میدهد: دریافت لیست سنسورهای موجود، ثبت شنوندگان برای دریافت داده و مدیریت فرکانس بهروزرسانی خوانشها. SensorManager نقطه دسترسی مرکزی به تمام عملیات است. سیستم از طریق callback onSensorChanged با ارسال شیء SensorEvent حاوی آرایهای از مقادیر float، برنامه را مطلع میکند.
در طول عمر Android، API چندین مرحله توسعه را طی کرده است. در نسخه ۲.۳ (Gingerbread) پشتیبانی از Batch Processing — گروهبندی رویدادهای سنسور برای کاهش مصرف انرژی — اضافه شد. Android ۴.۰ (Ice Cream Sandwich) سنسورهای مجازی Gravity و Linear Acceleration را اضافه کرد. از Android ۸.۰، سیستم دسترسی پسزمینه به سنسورها را برای افزایش حریم خصوصی محدود کرد.
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 ۱۲، برنامهها باید استفاده از سنسورها را در مانیفست اعلام کنند.
Android تمام سنسورها را به سه دسته طبقهبندی میکند: Motion (حرکت)، Position (موقعیت) و Environment (محیط). سنسورهای Motion شامل شتابسنج، ژیروسکوپ و گامشمار هستند. سنسورهای Position شامل مغناطیسسنج و Orientation هستند. 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 اندازهگیری میکند. مقادیر شامل گرانش (۹.۸ 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 (Hardware Abstraction Layer) — درایور سطح پایین سنسور که در سطح هسته Linux کار میکند — ارتباط برقرار میکند.
درایور HAL دادههای خام را از تراشه سختافزاری دریافت میکند، نویزها را فیلتر کرده و آنها را به بالای پشته — از طریق SensorService (پروسۀ سیستمی) به برنامه — منتقل میکند. دادهها به صورت شیء SensorEvent حاوی آرایهای از مقادیر float به نام values و برچسب زمانی بر حسب نانوثانیه منتقل میشوند. فرکانس رویدادها به حالت تحویل انتخاب شده بستگی دارد.
هنگام ثبت شنونده، توسعهدهنده تأخیر مورد نظر بین رویدادها را از طریق ثابتهای SENSOR_DELAY_NORMAL (۲۰۰ ms)، SENSOR_DELAY_UI (۶۰ ms)، SENSOR_DELAY_GAME (۲۰ ms) و SENSOR_DELAY_FASTEST (۰ ms — حداکثر فرکانس) مشخص میکند. فرکانس واقعی ممکن است متفاوت باشد — سیستم مصرف انرژی را بهینه میکند.
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
sensorManager.registerListener(
this,
sensor,
SensorManager.SENSOR_DELAY_GAME
)
از Android ۲.۳، سنسورها از حالت دستهای پشتیبانی میکنند — رویدادها در بافر FIFO جمع شده و در یک بسته تحویل داده میشوند. این به پردازنده اجازه میدهد مدت بیشتری در حالت خواب بماند و مصرف انرژی را تا ۶۰٪ کاهش دهد. اندازه بافر به تراشه سنسور بستگی دارد و در فیلد Sensor.fifoMaxEventCount مشخص میشود.
SensorManager — سرویس سیستمی قابل دسترسی از طریق getSystemService(Context.SENSOR_SERVICE). روشهایی برای دریافت لیست سنسورها، دریافت سنسور پیشفرض خاص و ثبت/لغو شنوندگان فراهم میکند. SensorManager — singleton، یک نمونه برای کل برنامه.
قبل از استفاده از سنسور باید وجود آن را بررسی کنید. متد 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("Sensor", "ژیروسکوپ در دسترس است")
}
شنونده از طریق registerListener(listener, sensor, delay) ثبت میشود. مهم: لغو شنونده در متد onPause() از طریق unregisterListener(listener) ضروری است. اگر این کار انجام نشود، برنامه حتی در پسزمینه به دریافت رویدادهای سنسور ادامه داده و باتری را تخلیه میکند. Android ۸+ در 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")
}
}
سنسور نور امکان تطبیق رابط با شرایط محیطی را فراهم میکند. در نور کم (کمتر از ۱۰ lx) میتوان به حالت تاریک سوئیچ کرد. در نور شدید خورشید (بیشتر از ۱۰۰۰۰ lx) — کنتراست را افزایش داد. برای فیلتر کردن نویز از میانگین متحرک ۵ مقدار آخر استفاده میشود.
Android چندین سنسور مجازی ارائه میدهد که معادل سختافزاری مستقیم ندارند. سنسور مجازی مقادیر خود را بر اساس ترکیبی از سنسورهای فیزیکی محاسبه میکند. این کار بار توسعهدهنده را کاهش میدهد — سیستم خود الگوریتمهای ادغام داده را پیادهسازی میکند.
سنسور Gravity (TYPE_GRAVITY) مؤلفه گرانشی را از خوانشهای شتابسنج با استفاده از فیلتر پایینگذر (low-pass) استخراج میکند. Linear Acceleration (TYPE_LINEAR_ACCELERATION) — برعکس، گرانش را حذف کرده و فقط شتاب خطی دستگاه را باقی میگذارد. مجموع Gravity و Linear Acceleration خوانشهای خام شتابسنج را میدهد.
Rotation Vector — پیچیدهترین سنسور مجازی. دادههای ژیروسکوپ (تغییرات با فرکانس بالا)، شتابسنج (بردار گرانش) و مغناطیسسنج (جهت نسبت به شمال) را ترکیب میکند. نتیجه — یک کواترنیون که جهت مطلق دستگاه در فضا را توصیف میکند. در برنامههای AR و هدستهای VR استفاده میشود.
Game Rotation Vector — نسخه سادهشده Rotation Vector بدون استفاده از مغناطیسسنج. این دقت کمتری در تعیین آزیموت، اما فرکانس بهروزرسانی و پایداری بالاتری میدهد. برای بازیها توصیه میشود که تأخیر کم مهم است نه جهت مطلق نسبت به شمال.
سنسورها — یکی از انرژیبرترین اجزای دستگاه هستند. شتابسنج و ژیروسکوپ در حداکثر فرکانس پرسوجو میتوانند باتری را در ۳–۴ ساعت کار مداوم تخلیه کنند. بهینهسازی کار با سنسورها یک وظیفه حیاتی برای هر برنامهای است که از Sensors API استفاده میکند.
بدون نیاز از SENSOR_DELAY_FASTEST استفاده نکنید. برای انیمیشنهای UI، SENSOR_DELAY_UI (۶۰ ms) کافی است. برای تعیین جهت صفحه — SENSOR_DELAY_NORMAL (۲۰۰ ms). هرچه فرکانس بالاتر باشد، پردازنده زمان بیشتری را در حالت فعال سپری میکند. تفاوت بین NORMAL و FASTEST تا ۱۰ برابر در مصرف انرژی است.
از Android ۸.۰ (API ۲۶)، برنامههای پسزمینه رویدادهای سنسور را با فرکانس کاهشیافته دریافت میکنند. در Android ۱۲+ دسترسی پسزمینه به سنسورهای Motion و Position نیاز به مجوز BODY_SENSORS_BACKGROUND دارد. هنگام رفتن برنامه به حالت پسزمینه، ثبت شنونده را لغو کنید — این کار عمر باتری دستگاه را افزایش میدهد.
از پردازش دستهای از طریق متد registerListener(listener, sensor, delay, maxReportLatencyUs) استفاده کنید. پارامتر maxReportLatencyUs حداکثر تأخیر تحویل رویدادها را بر حسب میکروثانیه تعیین میکند. با مقدار ۱۰۰۰۰۰۰ (۱ ثانیه)، رویدادها در بافر FIFO سنسور جمع شده و یک بار در ثانیه تحویل داده میشوند — پردازنده کمتر از خواب بیدار میشود.
سوالات متداول
حداقل مجموعه — شتابسنج و مغناطیسسنج. این دو سنسور در بیش از ۹۵٪ دستگاهها وجود دارند. ژیروسکوپ، سنسور نور و سنسور مجاورت — در ۷۰–۸۰٪ مدلهای مدرن. سایر سنسورها (فشار، دما، رطوبت، گامشمار) کمتر رایج هستند و به رده قیمتی دستگاه بستگی دارند.
TYPE_ACCELEROMETER شتاب کامل شامل گرانش را برمیگرداند (۹.۸ m/s²). TYPE_LINEAR_ACCELERATION شتاب بدون گرانش — فقط شتاب ناشی از حرکت دستگاه را برمیگرداند. اگر دستگاه ساکن باشد، شتابسنج ۹.۸ m/s² در محور Z نشان میدهد، در حالی که Linear Acceleration در همه محورها ۰ نشان میدهد.
از getPackageManager().hasSystemFeature() با ثابتهای مربوطه استفاده کنید: FEATURE_SENSOR_ACCELEROMETER، FEATURE_SENSOR_GYROSCOPE، FEATURE_SENSOR_PROXIMITY و غیره. روش جایگزین — فراخوانی getDefaultSensor(type) و بررسی null بودن نتیجه. روش اول برای بررسی در مرحله مقداردهی اولیه ترجیح داده میشود.
دادههای خام سنسورها حاوی نویز هستند. برای صاف کردن از فیلتر پایینگذر (low-pass) استفاده کنید: newValue = alpha * rawValue + (1 — alpha) * previousValue. ضریب alpha = ۰.۱–۰.۳ تعادل خوبی بین پاسخدهی و نرمی میدهد. برای ژیروسکوپ نیز فیلتر بالاگذر (high-pass) برای حذف رانش صفر استفاده میشود.
بله، اما با محدودیتهایی. از Android ۸.۰، فرکانس رویدادهای سنسور برای برنامههای پسزمینه کاهش مییابد. از Android ۱۲، مجوز BODY_SENSORS_BACKGROUND برای دسترسی به سنسورها در پسزمینه الزامی است. برای کار در پسزمینه، استفاده از Foreground Service با اعلان توصیه میشود.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید