Sensors API — интерфејс платформе Android за приступ хардверским сензорима уређаја. API пружа јединствен начин за добијање података са акцелерометра, жироскопа, магнетометра, сензора осветљења и других сензора. Према подацима Google, 2026, преко 95% савремених Android уређаја опремљено је најмање три типа сензора, што отвара широке могућности за развој контекстуалних апликација.
Главно
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) појавила се подршка за Batch Processing — груписање догађаја сензора ради смањења потрошње енергије. 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, апликације морају декларисати коришћење сензора у манифесту.
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. Вредности укључују гравитацију (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 (Hardware Abstraction Layer) — нисконивоским драјвером сензора који ради на нивоу 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("Sensor", "Жироскоп је доступан")
}
Слушалац се региструје преко 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 (азимут) — угао у односу на магнетни север у rad-има.
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) издваја гравитациону компоненту из очитавања акцелерометра помоћу low-pass филтера. 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 је до 10x по потрошњи енергије.
Од 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. Први начин је пожељнији за проверу у фази иницијализације.
Сирови подаци са сензора садрже шум. За изглађивање користите low-pass филтер: newValue = alpha * rawValue + (1 — alpha) * previousValue. Коефицијент alpha = 0.1–0.3 даје добар баланс између одзивности и глаткоће. За жироскоп се такође примењује high-pass филтер за уклањање нултог дрифта.
Да, али са ограничењима. Од Android 8.0, учесталост догађаја сензора се смањује за позадинске апликације. Од Android 12, потребна је дозвола BODY_SENSORS_BACKGROUND за приступ сензорима у позадини. За позадински рад препоручује се коришћење Foreground Service-а са обавештењем.
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође