Większość urządzeń z Androidem ma wbudowane czujniki, które mierzą ruch, orientację i różne warunki środowiskowe. Czujniki te są w stanie dostarczać nieprzetworzone dane o wysokiej precyzji i dokładności. Przydają się przy monitorowaniu trójwymiarowego ruchu urządzenia lub lub monitorować zmiany w środowisku otoczenia w pobliżu urządzenia. Na przykład gra może śledzić odczyty z czujnika grawitacji urządzenia, aby wywnioskować z nich złożone gesty i ruchy użytkownika, takie jak przechylanie, potrząsanie, obracanie czy kołysanie. Podobnie aplikacja pogodowa może używać czujnika temperatury i wilgotności w urządzeniu do obliczania i zgłaszania punktu rosy lub podróży aplikacja może używać czujnika pola geomagnetycznego i akcelerometru do wskazania kompasu ducha.
Zapoznaj się z tymi powiązanymi materiałami:
Platforma Android obsługuje trzy ogólne kategorie czujników:
- Czujniki ruchu
Czujniki te mierzą siły przyspieszenia i siły obrotowe wzdłuż 3 osi. Ta kategoria obejmuje akcelerometry, czujniki grawitacyjne, żyroskopy i czujniki wektorów obrotowych.
- Czujniki środowiskowe
Czujniki mierzą różne parametry środowiskowe, takie jak temperatura otoczenia oraz ciśnienie, oświetlenie i wilgotność. Do tej kategorii należą: barometry, fotometry termometrów.
- Czujniki położenia
Te czujniki mierzą fizyczną pozycję urządzenia. Ta kategoria obejmuje czujniki orientacji i magnetometry.
Za pomocą interfejsu API frameworka czujników Androida możesz uzyskać dostęp do czujników dostępnych na urządzeniu i pozyskiwać z nich dane w postaci nieprzetworzonej. Struktura czujnika udostępnia kilka klas i interfejsów, które ułatwiają wykonanie wykonywać wiele zadań związanych z czujnikami. Za pomocą konstrukcji czujnika można na przykład:
- Określ, które czujniki są dostępne na urządzeniu.
- określać możliwości poszczególnych czujników, takie jak maksymalny zasięg, producent, wymagania dotyczące zasilania i rozdzielczość;
- Pobieraj nieprzetworzone dane z czujników i określaj minimalną częstotliwość ich pobierania.
- Rejestrowanie i wyrejestrowywanie detektorów zdarzeń czujnika, które monitorują zmiany czujników.
W tej części opisujemy czujniki dostępne na platformie Android. Zawiera on też wprowadzenie do frameworku czujników.
Wprowadzenie do czujników
Platforma czujników w Androidzie zapewnia dostęp do wielu typów czujników. Niektóre z tych czujników są sprzętowe, a niektóre programowe. Sprzętowe czujniki to komponenty fizyczne wbudowane w telefon lub tablet. Pobierają one dane bezpośrednio z określonych właściwości środowiska, takich jak przyspieszenie, natężenie pola geomagnetycznego czy zmiana kątowa. Oparte na oprogramowaniu Czujniki nie są urządzeniami fizycznymi, chociaż imitują czujniki sprzętowe. Czujniki programowe czerpią dane z jednego lub kilku czujników sprzętowych i czasami są nazywane czujniki lub czujniki syntetyczne. Czujnik przyspieszenia liniowego i czujnik grawitacji to przykłady czujnikach opartych na oprogramowaniu. W tabeli 1 podsumowano czujniki obsługiwane przez platformę Android.
Niewiele urządzeń z Androidem ma czujniki każdego typu. Na przykład większość telefonów i tabletów ma akcelerometr i magnetometr, ale mniej urządzeń ma barometry lub termometry. Oprócz tego urządzenie może mieć więcej niż 1 czujnik danego typu. Na przykład urządzenie może mieć 2 czujniki grawitacyjne, z których każdy ma inny zakres.
Tabela 1. Typy czujników obsługiwane przez platformę Android.
Czujnik | Typ | Opis | Częste zastosowania |
---|---|---|---|
TYPE_ACCELEROMETER |
Sprzęt | Mierzy przyspieszenie w m/s2, które jest stosowane na urządzeniu na wszystkich 3 osiach fizycznych (x, y i z), w tym siła grawitacji. | wykrywanie ruchu (potrząsanie, przechylanie itp.); |
TYPE_AMBIENT_TEMPERATURE |
Sprzęt | Mierzy temperaturę otoczenia w stopniach Celsjusza (°C). Zobacz uwagę poniżej. | monitorowanie temperatury powietrza; |
TYPE_GRAVITY |
Oprogramowanie lub sprzęt | Mierzy siłę grawitacji w m/s2, która działa na urządzenie na wszystkich trzech fizycznych osiach (x, y, z). | wykrywanie ruchu (potrząsanie, przechylanie itp.); |
TYPE_GYROSCOPE |
Sprzęt | Mierzy szybkość obrotu urządzenia w rad/s wokół każdego z trzech z nich osie fizyczne (x, y i z). | wykrywanie rotacji (obracanie, skręcanie itp.); |
TYPE_LIGHT |
Sprzęt | Pomiar poziomu światła otoczenia (oświetlenia) w lx. | Sterowanie jasnością ekranu |
TYPE_LINEAR_ACCELERATION |
Oprogramowanie lub sprzęt | Mierzy przyspieszenie w m/s2, które jest stosowane do urządzenia na wszystkich 3 osiach fizycznych (x, y i z), z wyłączeniem siły grawitacji. | Monitorowanie przyspieszenia na jednej osi. |
TYPE_MAGNETIC_FIELD |
Sprzęt | Mierzy pole geomagnetyczne otoczenia dla wszystkich 3 osi fizycznych (x, y, z) w μT. | Tworzenie kompasu. |
TYPE_ORIENTATION |
Oprogramowanie | Mierzy stopnie obrotu urządzenia wokół wszystkich 3 osi fizycznych (x, y, z).
Od poziomu 3 interfejsu API można uzyskać macierz pochylenia i obrotu dla
urządzenia za pomocą czujnika grawitacji i czujnika pola geomagnetycznego w połączeniu z
getRotationMatrix()
. |
Określanie pozycji urządzenia. |
TYPE_PRESSURE |
Sprzęt | Mierzy ciśnienie powietrza w otoczeniu w hPa lub mbar. | Monitorowanie zmian ciśnienia. |
TYPE_PROXIMITY |
Sprzęt | Mierzy odległość obiektu w cm w odniesieniu do ekranu widoku urządzenia. Ten czujnik jest zwykle używany do określania, czy telefon jest przyłożony do ucha. | Pozycja telefonu podczas rozmowy. |
TYPE_RELATIVE_HUMIDITY |
Sprzęt | Mierzy względną wilgotność otoczenia w procentach (%). | Monitoruję punkt rosy oraz wilgotność bezwzględną i względną. |
TYPE_ROTATION_VECTOR |
Oprogramowanie lub sprzęt | Pomiar orientacji urządzenia przez podanie 3 elementów wektora obrotu urządzenia. | wykrywanie ruchu i obrotu; |
TYPE_TEMPERATURE |
Sprzęt | Mierzy temperaturę urządzenia w stopniach Celsjusza (°C). Ten czujnik
na różnych urządzeniach i na różnych urządzeniach
ten czujnik został zastąpiony czujnikiem TYPE_AMBIENT_TEMPERATURE w:
Poziom API 14 |
Monitoruję temperatury. |
Sensor Framework
Możesz uzyskać dostęp do tych czujników i pobierać nieprzetworzone dane z czujników, korzystając z platformy czujników w Androidzie.
Ramka czujnika jest częścią pakietu android.hardware
i zawiera te klasy i interfejsy:
SensorManager
- Za pomocą tej klasy możesz utworzyć instancję usługi czujnika. Te zajęcia: różne metody dostępu do czujników i ich wyświetlania, rejestrowania i wyrejestrowania zdarzeń czujnika słuchaczy i uzyskiwanie informacji o orientacji. Ta klasa udostępnia też kilka stałych wartości czujników, które służą do raportowania dokładności czujnika, ustawiania szybkości pozyskiwania danych i kalibrowania czujników.
Sensor
- Za pomocą tej klasy możesz utworzyć instancję konkretnego czujnika. Ta klasa udostępnia różne metody, które umożliwiają określenie możliwości czujnika.
SensorEvent
- System używa tej klasy do tworzenia obiektu zdarzenia czujnika, który zawiera informacje o zdarzeniu czujnika. Obiekt zdarzenia czujnika zawiera te informacje: nieprzetworzone dane czujnika, typ czujnika, który wygenerował zdarzenie, dokładność danych i znak czasu zdarzenia.
SensorEventListener
- Za pomocą tego interfejsu możesz utworzyć 2 metody wywołania zwrotnego, które otrzymują powiadomienia (czujnik zdarzeń), gdy zmienią się wartości czujnika lub ich dokładność.
W typowej aplikacji te interfejsy API związane z czujnikami wykonują 2 podstawowe zadania:
- Identyfikowanie czujników i ich możliwości
Identyfikowanie czujników i ich możliwości w czasie działania jest przydatne, jeśli aplikacja ma funkcje, które opierają się na określonych typach lub możliwościach czujników. Możesz na przykład: identyfikować wszystkie czujniki w urządzeniu i wyłączać funkcje aplikacji korzystających z brakujących czujników. Możesz również zidentyfikować wszystkie czujniki, danego typu, dzięki czemu możesz wybrać implementację czujnika, która daje optymalną wydajność dla Twojej aplikacji.
- Monitorowanie zdarzeń związanych z czujnikiem
Monitorowanie zdarzeń z czujników to sposób na pozyskiwanie nieprzetworzonych danych z czujnika. Zdarzenie czujnika występuje za każdym razem, gdy czujnik wykryje zmianę w parametrach, które mierzy. Zdarzenie czujnika zawiera 4 rodzaje informacji: nazwę czujnika, który wywołał zdarzenie, sygnaturę czasową zdarzenia, dokładność zdarzenia oraz nieprzetworzone dane czujnika, które wywołały zdarzenie.
Dostępność czujników
Dostępność czujników może się różnić w zależności od urządzenia, a także od wersji Androida. Dzieje się tak, ponieważ czujniki Androida zostały wprowadzone w ciągu kilku wersji platformy. Na przykład wiele czujników zostało wprowadzonych w Androidzie 1.5 (poziom interfejsu API 3), ale niektóre z nich nie zostały zaimplementowane i nie były dostępne do użycia aż do Androida 2.3 (poziom interfejsu API 9). Podobnie, wprowadziliśmy w Androidzie 2.3 (poziom API 9) i 4.0 (poziom API 14) kilka czujników. Dwa czujniki zostały wycofane i zastąpione nowszymi, lepszymi czujnikami.
W tabeli 2 podsumowano dostępność każdego czujnika z poszczególnych platform. Tylko cztery platformy są wymienione na liście, ponieważ to właśnie na nich występują zmiany w czujnikach. Czujniki, które są oznaczone jako wycofane są nadal dostępne na kolejnych platformach (pod warunkiem, znajduje się w urządzeniu, co jest zgodne z zasadami dotyczącymi zgodności z przejściem dla Androida.
Tabela 2. Dostępność czujników w zależności od platformy
Czujnik | Android 4.0 (poziom 14 interfejsu API) |
Android 2.3 (poziom API 9) |
Android 2.2 (poziom API 8) |
Android 1.5 (poziom 3 interfejsu API) |
---|---|---|---|---|
TYPE_ACCELEROMETER |
Tak | Tak | Tak | Tak |
TYPE_AMBIENT_TEMPERATURE |
Tak | nie dotyczy | nie dotyczy | nie dotyczy |
TYPE_GRAVITY |
Tak | Tak | nie dotyczy | nie dotyczy |
TYPE_GYROSCOPE |
Tak | Tak | n/a1 | n/a1 |
TYPE_LIGHT |
Tak | Tak | Tak | Tak |
TYPE_LINEAR_ACCELERATION |
Tak | Tak | nie dotyczy | nie dotyczy |
TYPE_MAGNETIC_FIELD |
Tak | Tak | Tak | Tak |
TYPE_ORIENTATION |
Tak2 | Tak2 | Tak2 | Tak |
TYPE_PRESSURE |
Tak | Tak | n/a1 | n/a1 |
TYPE_PROXIMITY |
Tak | Tak | Tak | Tak |
TYPE_RELATIVE_HUMIDITY |
Tak | nie dotyczy | nie dotyczy | nie dotyczy |
TYPE_ROTATION_VECTOR |
Tak | Tak | nie dotyczy | nie dotyczy |
TYPE_TEMPERATURE |
Tak2 | Tak | Tak | Tak |
1 Ten typ czujnika został dodany w Androidzie 1.5 (poziom API 3), ale nie można było z niej korzystać aż do wersji 2.3 (poziom interfejsu API 9).
2 Ten czujnik jest dostępny, ale wycofane.
Rozpoznawanie czujników i ich funkcji
Platforma czujników Androida udostępnia kilka metod, które ułatwiają określenie w czasie wykonywania, które czujniki są dostępne na urządzeniu. Udostępnia on również metody, które pozwalają określić możliwości każdego z czujników, takie jak jego maksymalny zasięg, rozdzielczość i moc .
Aby zidentyfikować czujniki na urządzeniu, musisz najpierw uzyskać odwołanie do usługi czujnika. W tym celu należy utworzyć instancję klasy SensorManager
przez
wywoływanie metody getSystemService()
i fałszowanie wyników
w argumencie SENSOR_SERVICE
. Na przykład:
private lateinit var sensorManager: SensorManager ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
private SensorManager sensorManager; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
Następnie możesz wyświetlić listę wszystkich czujników urządzenia, wywołując metodę
getSensorList()
ze stałą TYPE_ALL
. Na przykład:
val deviceSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_ALL)
List<Sensor> deviceSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
Jeśli chcesz wyświetlić listę wszystkich czujników danego typu, zamiast TYPE_ALL
możesz użyć innej stałej, np. TYPE_GYROSCOPE
, TYPE_LINEAR_ACCELERATION
lub TYPE_GRAVITY
.
Możesz też sprawdzić, czy na urządzeniu jest określony typ czujnika, używając metody getDefaultSensor()
i przekazując stałą typu dla konkretnego czujnika. Jeśli urządzenie ma więcej niż 1 czujnik danego typu, jeden z
muszą być ustawione jako czujniki domyślne. Jeśli domyślny czujnik nie istnieje dla danego
typ czujnika, wywołanie metody zwraca wartość null, co oznacza, że urządzenie nie ma tego typu
. Na przykład ten kod sprawdza, czy na urządzeniu znajduje się magnetometr:
private lateinit var sensorManager: SensorManager ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null) { // Success! There's a magnetometer. } else { // Failure! No magnetometer. }
private SensorManager sensorManager; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); if (sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) != null){ // Success! There's a magnetometer. } else { // Failure! No magnetometer. }
Uwaga: Android nie wymaga od producentów urządzeń z Androidem instalowania określonych typów czujników, więc urządzenia mogą mieć szeroki zakres konfiguracji czujników.
Oprócz wyświetlania listy czujników zainstalowanych na urządzeniu możesz użyć publicznych metod
Sensor
klasa do określania możliwości i atrybutów poszczególnych osób
i czujników. Jest to przydatne, jeśli chcesz, aby aplikacja działała inaczej w zależności od tego, które czujniki lub
funkcje czujnika są dostępne w urządzeniu. Aby uzyskać rozdzielczość i maksymalny zakres pomiarowy czujnika, możesz na przykład użyć metod getResolution()
i getMaximumRange()
. Możesz też użyć usługi
Metoda getPower()
, która pozwala uzyskać wymagania dotyczące zasilania czujnika.
2 z publicznych metod są szczególnie przydatne, jeśli chcesz zoptymalizować aplikację pod kątem czujników innego producenta lub różnych wersji czujnika. Jeśli na przykład Twoja aplikacja
monitorowania gestów użytkownika, takich jak przechylanie i potrząśnięcie, można utworzyć jeden zestaw filtrów
reguł i optymalizacji nowszych urządzeń, które mają czujnik grawitacji konkretnego dostawcy, oraz inne.
z zestawem reguł filtrowania danych i optymalizacji dla urządzeń, które nie mają czujnika grawitacji i
tylko za pomocą akcelerometru. Poniższy przykładowy kod pokazuje, jak możesz wykorzystać metody getVendor()
i getVersion()
.
to osiągnąć. W tym przykładzie szukamy czujnika grawitacyjnego, którego dostawcą jest Google LLC i który ma numer wersji 3. Jeśli dany czujnik nie jest obecny na urządzeniu, próbujemy użyć akcelerometru.
private lateinit var sensorManager: SensorManager private var mSensor: Sensor? = null ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null) { val gravSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_GRAVITY) // Use the version 3 gravity sensor. mSensor = gravSensors.firstOrNull { it.vendor.contains("Google LLC") && it.version == 3 } } if (mSensor == null) { // Use the accelerometer. mSensor = if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) { sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) } else { // Sorry, there are no accelerometers on your device. // You can't play this game. null } }
private SensorManager sensorManager; private Sensor mSensor; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mSensor = null; if (sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY) != null){ List<Sensor> gravSensors = sensorManager.getSensorList(Sensor.TYPE_GRAVITY); for(int i=0; i<gravSensors.size(); i++) { if ((gravSensors.get(i).getVendor().contains("Google LLC")) && (gravSensors.get(i).getVersion() == 3)){ // Use the version 3 gravity sensor. mSensor = gravSensors.get(i); } } } if (mSensor == null){ // Use the accelerometer. if (sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null){ mSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); } else{ // Sorry, there are no accelerometers on your device. // You can't play this game. } }
Inną przydatną metodą jest getMinDelay()
, która zwraca minimalny przedział czasu (w mikrosekundach), którego może użyć czujnik do rejestrowania danych. Dowolny czujnik
, która zwraca wartość inną niż zero dla funkcji getMinDelay()
metoda to strumieniowanie
. Czujniki strumieniowe zbierają dane w regularnych odstępach czasu. Zostały one wprowadzone w Androidzie 2.3 (poziom interfejsu API 9). Jeśli czujnik zwróci 0 przy wywołaniu metody getMinDelay()
, oznacza to, że
czujnik nie jest czujnikiem strumieniowania, ponieważ przekazuje dane tylko w przypadku zmiany
wykrywanych przez nie parametrów.
Metoda getMinDelay()
jest przydatna, ponieważ pozwala określić maksymalną szybkość, z jaką czujnik może pobierać dane. Jeśli niektóre funkcje w aplikacji wymagają wysokich współczynników pozyskiwania danych lub czujnika strumieniowego, możesz użyć tej metody, aby określić, czy czujnik spełnia te wymagania, a następnie odpowiednio włączyć lub wyłączyć odpowiednie funkcje w aplikacji.
Uwaga: maksymalna szybkość pozyskiwania danych przez czujnik nie musi być szybkością, z jaką framework czujnika dostarcza dane do aplikacji. Platforma czujnika przekazuje dane na podstawie zdarzeń z czujnika, a kilka czynników wpływa na aplikacja odbiera zdarzenia z czujnika. Więcej informacji znajdziesz w artykule Monitorowanie zdarzeń czujnika.
Monitorowanie zdarzeń z czujnika
Aby monitorować nieprzetworzone dane z czujnika, musisz zaimplementować 2 metody wywołania, które są dostępne w interfejsie SensorEventListener
: onAccuracyChanged()
i onSensorChanged()
. System Android wywołuje
te metody, gdy:
- Zmienia się dokładność czujnika.
W takim przypadku system wywołuje metodę
onAccuracyChanged()
, podając odnosi się do obiektuSensor
, który uległ zmianie, nowej dokładności czujnika. Dokładność jest reprezentowana przez jedną z 4 konstant stanu:SENSOR_STATUS_ACCURACY_LOW
,SENSOR_STATUS_ACCURACY_MEDIUM
,SENSOR_STATUS_ACCURACY_HIGH
lubSENSOR_STATUS_UNRELIABLE
. - Czujnik zgłasza nową wartość.
W tym przypadku system wywołuje metodę
onSensorChanged()
, przekazując obiektSensorEvent
. ObiektSensorEvent
zawiera informacje o nowych danych z czujnika, w tym ich dokładność, czujnik, który wygenerował dane, sygnatura czasowa momentu wygenerowania danych oraz nowy zarejestrowane przez czujnik.
Poniższy kod pokazuje, jak używać metody onSensorChanged()
do monitorowania danych z
czujnika światła. Ten przykład wyświetla nieprzetworzone dane z czujnika w TextView
czyli
zdefiniowaną w pliku main.xml jako sensor_data
.
class SensorActivity : Activity(), SensorEventListener { private lateinit var sensorManager: SensorManager private var mLight: Sensor? = null public override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main) sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT) } override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) { // Do something here if sensor accuracy changes. } override fun onSensorChanged(event: SensorEvent) { // The light sensor returns a single value. // Many sensors return 3 values, one for each axis. val lux = event.values[0] // Do something with this sensor value. } override fun onResume() { super.onResume() mLight?.also { light -> sensorManager.registerListener(this, light, SensorManager.SENSOR_DELAY_NORMAL) } } override fun onPause() { super.onPause() sensorManager.unregisterListener(this) } }
public class SensorActivity extends Activity implements SensorEventListener { private SensorManager sensorManager; private Sensor mLight; @Override public final void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); mLight = sensorManager.getDefaultSensor(Sensor.TYPE_LIGHT); } @Override public final void onAccuracyChanged(Sensor sensor, int accuracy) { // Do something here if sensor accuracy changes. } @Override public final void onSensorChanged(SensorEvent event) { // The light sensor returns a single value. // Many sensors return 3 values, one for each axis. float lux = event.values[0]; // Do something with this sensor value. } @Override protected void onResume() { super.onResume(); sensorManager.registerListener(this, mLight, SensorManager.SENSOR_DELAY_NORMAL); } @Override protected void onPause() { super.onPause(); sensorManager.unregisterListener(this); } }
W tym przykładzie domyślne opóźnienie danych (SENSOR_DELAY_NORMAL
) jest określane przy wywoływaniu metody registerListener()
. Dane
opóźnienie (lub częstotliwość próbkowania) określa odstęp czasu, po którym zdarzenia z czujnika są wysyłane do aplikacji.
za pomocą metody wywołania zwrotnego onSensorChanged()
. Domyślne opóźnienie danych jest odpowiednie do monitorowania typowych zmian orientacji ekranu i wynosi 200 tys. mikrosekund. Możesz też określić inne
opóźnienia danych, takie jak SENSOR_DELAY_GAME
(20 000 mikrosekund
opóźnienie), SENSOR_DELAY_UI
(opóźnienie 60 000 mikrosekund) lub SENSOR_DELAY_FASTEST
(opóźnienie 0 mikrosekund). Począwszy od Androida 3.0 (interfejs API na poziomie 11) możesz też określić opóźnienie jako wartość bezwzględną (w mikrosekundach).
Określone przez Ciebie opóźnienie jest tylko sugerowanym opóźnieniem. System Android i inne aplikacje co może zmienić to opóźnienie. Sprawdzoną metodą jest określenie jak największego opóźnienia, ponieważ system zwykle stosuje mniejsze opóźnienie niż podane (czyli należy wybrać najniższą częstotliwość próbkowania, która nadal spełnia wymagania aplikacji). Większe opóźnienie nakłada obciąża procesor i zużywa mniej energii.
Nie ma żadnej publicznej metody określania szybkości, z jaką framework czujnika wysyła do aplikacji zdarzenia czujnika. Możesz jednak używać sygnatur czasowych powiązanych z poszczególnymi zdarzeniami czujnika, aby obliczyć częstotliwość próbkowania na podstawie kilku zdarzeń. Nie musisz zmieniać parametru częstotliwości próbkowania (opóźnienia). Jeśli z jakiegoś powodu musisz zmienić opóźnienie, wyrejestrować i ponownie zarejestrować detektor czujnika.
Warto też pamiętać, że w tym przykładzie użyto atrybutów onResume()
i
onPause()
metoda wywołania zwrotnego do rejestrowania i wyrejestrowania zdarzenia czujnika
słuchacz. Sprawdzoną metodą jest wyłączenie czujników, których nie potrzebujesz, zwłaszcza gdy
aktywność jest wstrzymana. Jeśli tego nie zrobisz, bateria może wyczerpać się już w ciągu kilku godzin, ponieważ niektóre czujniki
mają znaczne wymagania w zakresie zasilania i mogą szybko zużywać baterię. System nie wyłączy automatycznie czujników po wyłączeniu ekranu.
Obsługa różnych konfiguracji czujników
Android nie określa standardowej konfiguracji czujnika dla urządzeń, co oznacza, że producenci urządzeń mogą stosować w swoich urządzeniach dowolną konfigurację Urządzenia z systemem Android. Urządzenia mogą więc obejmować różne funkcje, w wielu różnych konfiguracjach. Jeśli Twoja aplikacja korzysta z określonego typu czujnika, musisz upewnić się, że w urządzeniu jest czujnik, który umożliwia prawidłowe działanie aplikacji.
Masz 2 sposoby sprawdzania, czy dany czujnik znajduje się w urządzeniu:
- Wykrywanie czujników w czasie działania aplikacji i właściwe włączanie lub wyłączanie funkcji aplikacji.
- Używaj filtrów Google Play, aby kierować reklamy na urządzenia z określonymi konfiguracjami czujników.
Każda z tych opcji została omówiona w kolejnych sekcjach.
Wykrywanie czujników w czasie działania
Jeśli Twoja aplikacja korzysta z określonego typu czujnika, ale nie zależy od niego, możesz użyć parametru platforma czujnika do wykrywania czujnika w czasie działania, a następnie wyłączania lub włączania funkcji aplikacji w razie potrzeby. Na przykład aplikacja do nawigacji może korzystać z czujnika temperatury, czujnik ciśnienia, czujnika GPS i czujnik pola geomagnetycznego do wyświetlania temperatury, barometryczne takie jak ciśnienie, położenie i położenie kompasu. Jeśli urządzenie nie ma czujnika ciśnienia, możesz użyć frameworku czujnika, aby wykryć brak czujnika ciśnienia w czasie działania, a następnie wyłączyć część interfejsu aplikacji, która wyświetla ciśnienie. Na przykład te kontrole kodu czy urządzenie jest wyposażone w czujnik ciśnienia:
private lateinit var sensorManager: SensorManager ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null) { // Success! There's a pressure sensor. } else { // Failure! No pressure sensor. }
private SensorManager sensorManager; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); if (sensorManager.getDefaultSensor(Sensor.TYPE_PRESSURE) != null){ // Success! There's a pressure sensor. } else { // Failure! No pressure sensor. }
Używanie filtrów Google Play do kierowania na konkretne konfiguracje czujników
Jeśli publikujesz aplikację w Google Play, możesz użyć elementu <uses-feature>
w pliku manifestu, aby odfiltrować aplikację z urządzeń, które nie mają odpowiedniej konfiguracji czujników dla Twojej aplikacji.
Element <uses-feature>
ma kilka deskryptorów sprzętowych, które umożliwiają filtrowanie
w zależności od obecności określonych czujników. Czujniki, które możesz wyświetlić, to:
akcelerometr, barometr, kompas (pole geomagnetyczne), żyroskop, światło i bliskość.
poniżej znajdziesz przykładowy wpis w pliku manifestu, który filtruje aplikacje bez akcelerometru:
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
Jeśli dodasz ten element i opis do pliku manifestu aplikacji, użytkownicy zobaczą Twoją aplikację w Google Play tylko wtedy, gdy ich urządzenie będzie wyposażone w akcelerometr.
Deskryptor należy ustawić na android:required="true"
tylko wtedy, gdy aplikacja
zależy całkowicie od konkretnego czujnika. Jeśli aplikacja używa czujnika do niektórych funkcji, ale działa też bez niego, należy uwzględnić czujnik w elemencie <uses-feature>
, ale ustawić opis na android:required="false"
. Dzięki temu urządzenia będą mogły instalować Twoją aplikację, nawet jeśli nie mają tego konkretnego czujnika. Jest to też sprawdzona metoda zarządzania projektem, która pomaga śledzić funkcje używane przez aplikację.
Pamiętaj, że jeśli Twoja aplikacja korzysta z konkretnego czujnika, ale działa bez niego,
należy wykryć czujnik w czasie działania i wyłączyć lub włączyć funkcje aplikacji,
odpowiednie.
System współrzędnych czujnika
Ogólnie rzecz biorąc, do wyrażania wartości danych framework czujnika używa standardowego układu współrzędnych 3-osiowych. W przypadku większości czujników układ współrzędnych jest zdefiniowany względem ekranu urządzenia, gdy urządzenie jest trzymane w domyślnej orientacji (patrz rys. 1). Gdy urządzenie jest trzymane w domyślnej orientacji, Oś X jest pozioma i wskazuje po prawej stronie, oś Y jest pionowa i jest skierowana w górę, a oś Z wskazuje na zewnętrzną część płaszczyzny ekranu. W tym systemie współrzędne za ekranem mają ujemne wartości Z. Ten układ współrzędnych jest używany przez te czujniki:

Rysunek 1. System współrzędnych (w odniesieniu do urządzenia), którego używa czujnik API.
- Przyspieszenie rozwoju czujnik
- Czujnik przyspieszenia
- Żyroskop
- Czujnik przyspieszenia liniowego
- Pole geomagnetyczne czujnik
Najważniejszym punktem do zrozumienia w tym układzie współrzędnych jest to, że osie nie są zamieniane, gdy zmienia się orientacja ekranu urządzenia. Oznacza to, że układ współrzędnych czujnika nigdy się nie zmienia, gdy urządzenie się porusza. Działania te są takie same jak w systemie współrzędnych OpenGL.
Kolejną kwestią, którą należy wziąć pod uwagę, jest to, że aplikacja nie może zakładać, że naturalny (domyślny) kierunek urządzenia to orientacja pionowa. Naturalna orientacja wielu tabletów to orientacja pozioma. oraz układ współrzędnych czujnika zawsze opiera się na naturalnej orientacji urządzenia.
Jeśli Twoja aplikacja dopasowuje dane czujnika do wyświetlacza, musisz użyć metody getRotation()
, aby określić obrót ekranu, a potem metody remapCoordinateSystem()
, aby zmapować współrzędne czujnika na współrzędne ekranu. Jest to konieczne, nawet jeśli w pliku manifestu określono, że
w orientacji pionowej.
Uwaga: niektóre czujniki i metody używają układu współrzędnych, który jest względny względem układu odniesienia świata (w opozycji do układu odniesienia urządzenia). Te
czujniki i metody zwracają dane, które reprezentują ruch lub położenie urządzenia względem
Ziemię. Więcej informacji znajdziesz w metodach getOrientation()
i getRotationMatrix()
, czujniku orientacji oraz czujniku wektorowym obrotu.
Ograniczenie szybkości czujnika
Aby chronić potencjalnie poufne informacje o użytkownikach, jeśli Twoja aplikacja jest kierowana na Androida 12 (poziom API 31) lub nowszego, system ogranicza częstotliwość odświeżania danych z niektórych czujników ruchu i położenia. Te dane obejmują wartości zarejestrowane przez akcelerometr, żyroskop i czujnik pola geomagnetycznego urządzenia.
Limit częstotliwości odświeżania zależy od sposobu uzyskiwania dostępu do danych z czujników:
- Jeśli wywołujesz metodę
registerListener()
do monitorowania zdarzeń z czujnika, częstotliwość próbkowania będzie wynosić ograniczona do 200 Hz. Dotyczy to wszystkich przeciążonych wariantów interfejsu MetodaregisterListener()
. - Jeśli używasz tagu
SensorDirectChannel
zajęcia, częstotliwość próbkowania czujnika jest ograniczona doRATE_NORMAL
, czyli zwykle ok. 50 Hz.
Jeśli aplikacja ma szybciej gromadzić dane z czujnika ruchu, musisz:
zadeklaruj
HIGH_SAMPLING_RATE_SENSORS
jak widać poniżej. Jeśli jednak aplikacja próbuje zbierać dane z czujnika ruchu z większą częstotliwością bez deklarowania tego uprawnienia, wystąpi błąd SecurityException
.
AndroidManifest.xml
<manifest ...> <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"/> <application ...> ... </application> </manifest>
Sprawdzone metody uzyskiwania dostępu do czujników i ich używania
Podczas projektowania implementacji czujnika postępuj zgodnie ze wskazówkami podanymi w tej sekcji. Te wytyczne to zalecane sprawdzone metody dla wszystkich, którzy korzystają z ramowego projektu czujników do uzyskiwania dostępu do czujników i pozyskiwania danych z nich.
Zbieraj dane z czujników tylko na pierwszym planie
Na urządzeniach z Androidem 9 (poziom interfejsu API 28) lub nowszym aplikacje działające w tle podlegają tym ograniczeniom:
- Czujniki, które używają ciągłego trybu raportowania, takie jak akcelerometry i żyroskopy, nie otrzymują zdarzeń.
- Czujniki, które używają w zmianie lub one-shot tryby raportowania nie odbierają zdarzeń.
Z powodu tych ograniczeń najlepiej wykrywać zdarzenia czujnika, gdy aplikacja jest na pierwszym planie lub gdy jest częścią usługi na pierwszym planie.
Wyrejestruj detektory czujników
Po zakończeniu korzystania z czujnika lub wstrzymaniu jego działania pamiętaj o odrejestrowaniu jego listenera. Jeśli rejestrator czujnika jest zarejestrowany, a jego aktywność jest wstrzymana, czujnik nadal będzie gromadzić dane i wykorzystywać zasoby baterii, chyba że zarejestrujesz go ponownie. Poniższy kod pokazuje, jak użyć metody onPause()
, aby zarejestrować odbiornik:
private lateinit var sensorManager: SensorManager ... override fun onPause() { super.onPause() sensorManager.unregisterListener(this) }
private SensorManager sensorManager; ... @Override protected void onPause() { super.onPause(); sensorManager.unregisterListener(this); }
Więcej informacji: unregisterListener(SensorEventListener)
.
Testowanie za pomocą emulatora Androida
Emulator Androida zawiera zestaw elementów sterujących czujnikami wirtualnymi, które pozwalają na do testowania czujników, takich jak akcelerometr, temperatura otoczenia, magnetometr, bliskości, światła i innych obiektów.
Emulator używa połączenia z urządzeniem z Androidem, na którym działa SdkControllerSensor . Pamiętaj, że ta aplikacja jest dostępna tylko na urządzeniach z Androidem 4.0 (interfejs API poziomu 14) lub wyższym. (jeśli urządzenie ma Androida 4.0, musi mieć zainstalowaną wersję 2). Aplikacja SdkControllerSensor monitoruje zmiany w czujników urządzenia i przesyła je do emulatora. Ten emulator jest przekształcona na podstawie nowych wartości otrzymywanych z czujników na Twoim urządzeniu.
Kod źródłowy aplikacji SdkControllerSensor możesz wyświetlić w tym miejscu:
$your-android-sdk-directory /tools/apps/SdkController
Aby przenieść dane między urządzeniem a emulatorem, wykonaj te czynności: kroki:
- Sprawdź, czy USB jest włączone debugowanie na urządzeniu.
- Podłącz urządzenie do maszyny wirtualnej za pomocą kabla USB.
- Na urządzeniu uruchom aplikację SdkControllerSensor.
- W aplikacji wybierz czujniki, które chcesz emulować.
Uruchom to polecenie
adb
:- Uruchom emulator. Możesz teraz zastosować przekształcenia do funkcji za pomocą emulatora.
$ adb forward tcp:1968 tcp:1968
Uwaga: jeśli ruchy na fizycznym urządzeniu nie powodują zmiany w emulatorze, spróbuj ponownie uruchomić polecenie adb
z kroku 5.
Więcej informacji znajdziesz w przewodniku po emulatorze Androida.
Nie blokuj metody onSensorChanged()
Dane czujnika mogą się zmieniać z dużą częstotliwością, co oznacza, że system może dość często wywoływać metodę onSensorChanged(SensorEvent)
. Zgodnie ze sprawdzoną metodą
powinien robić jak najwięcej w ramach metody onSensorChanged(SensorEvent)
, aby jej nie blokować. Jeśli
filtrowanie lub redukcji danych z czujnika wymaga wykonania jakichkolwiek czynności,
które działają poza metodą onSensorChanged(SensorEvent)
.
Unikaj używania wycofanych metod lub typów czujników
Wycofano kilka metod i stałych.
W szczególności wycofany został typ czujnika TYPE_ORIENTATION
. Aby uzyskać dane orientacji, użyj metody getOrientation()
. Podobnie
Typ czujnika TYPE_TEMPERATURE
został wycofany. Na urządzeniach z Androidem 4.0 należy użyć typu czujnika TYPE_AMBIENT_TEMPERATURE
.
Sprawdź czujniki, zanim ich użyjesz
Przed podjęciem próby pozyskania danych z urządzenia zawsze sprawdź, czy znajduje się w nim czujnik. Nie zakładaj, że czujnik istnieje, tylko dlatego, że jest często używany. Producenci urządzeń nie muszą umieszczać w nich żadnych konkretnych czujników.
Uważnie wybieraj opóźnienia czujników
Gdy rejestrujesz czujnik za pomocą metody registerListener()
, wybierz częstotliwość przesyłania, która Ci odpowiada
do danej aplikacji lub przypadku użycia. Czujniki dostarczają dane w bardzo dużych ilościach. Umożliwianie systemowi wysyłania
dodatkowe dane, których nie potrzebujesz, zużywają zasoby systemu i zużywają baterię.