Die meisten Android-Geräte haben integrierte Sensoren, die Bewegung, Ausrichtung und verschiedene Umgebungsbedingungen messen. Diese Sensoren können Rohdaten mit hoher Präzision und Genauigkeit liefern. Sie sind nützlich, wenn Sie die dreidimensionale Gerätebewegung oder -positionierung überwachen oder Änderungen in der Umgebung eines Geräts beobachten möchten. In einem Spiel können beispielsweise Messwerte des Schwerkraftsensors eines Geräts erfasst werden, um komplexe Nutzergesten und -bewegungen wie Neigen, Schütteln, Drehen oder Schwingen zu ermitteln. Ebenso kann eine Wetter-App den Temperatur- und den Feuchtigkeitssensor eines Geräts verwenden, um den Taupunkt zu berechnen und anzugeben. Eine Reise-App kann den Geomagnetfeldsensor und den Beschleunigungsmesser verwenden, um eine Kompasspeilung anzugeben.
Weitere Informationen finden Sie unter den folgenden Links:
Die Android-Plattform unterstützt drei allgemeine Sensorkategorien:
- Bewegungssensoren
Diese Sensoren messen Beschleunigungs- und Rotationskräfte entlang drei Achsen. Diese Kategorie umfasst Beschleunigungsmesser, Schwerkraftsensoren, Gyroskope und Drehvektorsensoren.
- Umgebungssensoren
Diese Sensoren messen verschiedene Umgebungsparameter wie die Temperatur und den Druck der Umgebungsluft, die Beleuchtung und die Luftfeuchtigkeit. Diese Kategorie umfasst Barometer, Fotometer und Thermometer.
- Positionssensoren
Diese Sensoren messen die physische Position eines Geräts. Diese Kategorie umfasst Ausrichtungssensoren und Magnetometer.
Sie können auf die auf dem Gerät verfügbaren Sensoren zugreifen und Sensor-Rohdaten mithilfe des Android-Sensor-Frameworks erfassen. Das Sensor-Framework bietet mehrere Klassen und Schnittstellen, mit denen Sie eine Vielzahl von sensorbezogenen Aufgaben ausführen können. Mit dem Sensor-Framework können Sie beispielsweise Folgendes tun:
- Herausfinden, welche Sensoren auf einem Gerät verfügbar sind
- Sie können die Funktionen eines einzelnen Sensors ermitteln, z. B. seinen maximalen Bereich, den Hersteller, die Leistungsanforderungen und die Auflösung.
- Erfassen Sie Rohsensordaten und definieren Sie die Mindestrate, mit der Sie Sensordaten erfassen.
- Registrieren und unregisteren Sie Sensorereignis-Listener, die Sensoränderungen überwachen.
In diesem Artikel erhalten Sie einen Überblick über die Sensoren, die auf der Android-Plattform verfügbar sind. Außerdem erhalten Sie eine Einführung in das Sensor-Framework.
Einführung in Sensoren
Mit dem Android-Sensor-Framework können Sie auf viele Arten von Sensoren zugreifen. Einige dieser Sensoren sind hardwarebasiert, andere softwarebasiert. Hardwarebasierte Sensoren sind physische Komponenten, die in ein Smartphone oder Tablet eingebaut sind. Die Daten werden durch direkte Messung bestimmter Umwelteigenschaften wie Beschleunigung, Stärke des geomagnetischen Feldes oder Winkeländerung abgeleitet. Softwarebasierte Sensoren sind keine physischen Geräte, obwohl sie hardwarebasierte Sensoren imitieren. Softwarebasierte Sensoren leiten ihre Daten von einem oder mehreren der hardwarebasierten Sensoren ab und werden manchmal als virtuelle Sensoren oder synthetische Sensoren bezeichnet. Der lineare Beschleunigungssensor und der Schwerkraftsensor sind Beispiele für softwarebasierte Sensoren. In Tabelle 1 sind die von der Android-Plattform unterstützten Sensoren zusammengefasst.
Nur wenige Android-Geräte haben alle Arten von Sensoren. So haben beispielsweise die meisten Smartphones und Tablets einen Beschleunigungsmesser und ein Magnetometer, aber weniger Geräte haben Barometer oder Thermometer. Außerdem kann ein Gerät mehrere Sensoren eines bestimmten Typs haben. Ein Gerät kann beispielsweise zwei Gravitationssensoren mit unterschiedlicher Reichweite haben.
Sensor | Eingeben | Beschreibung | Übliche Anwendungsbereiche |
---|---|---|---|
TYPE_ACCELEROMETER |
Hardware | Misst die Beschleunigungskraft in m/s2, die auf ein Gerät auf allen drei physischen Achsen (x, y und z) ausgeübt wird, einschließlich der Schwerkraft. | Bewegungserkennung (Schütteln, Neigen usw.) |
TYPE_AMBIENT_TEMPERATURE |
Hardware | Misst die Raumtemperatur in Grad Celsius (°C). Weitere Informationen finden Sie im Hinweis unten. | Überwachung der Lufttemperaturen |
TYPE_GRAVITY |
Software oder Hardware | Misst die Schwerkraft in m/s2, die auf ein Gerät auf allen drei physischen Achsen (x, y, z) ausgeübt wird. | Bewegungserkennung (Schütteln, Neigen usw.) |
TYPE_GYROSCOPE |
Hardware | Misst die Drehgeschwindigkeit eines Geräts in rad/s um jede der drei physischen Achsen (x, y und z). | Drehung erkennen (Drehen, Wenden usw.) |
TYPE_LIGHT |
Hardware | Gibt die Lichtintensität der Umgebung (Beleuchtung) in x L an. | Bildschirmhelligkeit steuern |
TYPE_LINEAR_ACCELERATION |
Software oder Hardware | Misst die Beschleunigungskraft in m/s2, die auf ein Gerät auf allen drei physischen Achsen (x, y und z) ausgeübt wird, ohne die Schwerkraft. | Beschleunigung entlang einer einzelnen Achse überwachen |
TYPE_MAGNETIC_FIELD |
Hardware | Misst das Umgebungsmagnetfeld für alle drei physischen Achsen (x, y, z) in μT. | Kompass erstellen |
TYPE_ORIENTATION |
Software | Misst die Drehung eines Geräts um alle drei physischen Achsen (x, y, z).
Ab API-Ebene 3 können Sie die Neigungsmatrix und die Drehungsmatrix für ein Gerät mithilfe des Gravitationssensors und des Geomagnetfeldsensors in Verbindung mit der Methode getRotationMatrix() abrufen. |
Geräteposition wird ermittelt. |
TYPE_PRESSURE |
Hardware | Misst den Umgebungsluftdruck in hPa oder mbar. | Überwachung von Luftdruckänderungen |
TYPE_PROXIMITY |
Hardware | Misst die Nähe eines Objekts in Zentimetern relativ zum Display eines Geräts. Dieser Sensor wird in der Regel verwendet, um zu ermitteln, ob ein Mobiltelefon an das Ohr einer Person gehalten wird. | Position des Telefons während eines Anrufs. |
TYPE_RELATIVE_HUMIDITY |
Hardware | Misst die relative Luftfeuchtigkeit in Prozent (%). | Taupunkt, absolute und relative Luftfeuchtigkeit überwachen |
TYPE_ROTATION_VECTOR |
Software oder Hardware | Misst die Ausrichtung eines Geräts, indem die drei Elemente des Drehvektors des Geräts angegeben werden. | Bewegungs- und Dreherkennung |
TYPE_TEMPERATURE |
Hardware | Misst die Temperatur des Geräts in Grad Celsius (°C). Die Implementierung dieses Sensors variiert je nach Gerät. Er wurde in API-Level 14 durch den TYPE_AMBIENT_TEMPERATURE -Sensor ersetzt. |
Temperaturüberwachung |
Sensor Framework
Mithilfe des Android-Sensor-Frameworks können Sie auf diese Sensoren zugreifen und Sensorrohdaten erfassen.
Das Sensor-Framework ist Teil des android.hardware
-Pakets und umfasst die folgenden Klassen und Schnittstellen:
SensorManager
- Mit dieser Klasse können Sie eine Instanz des Sensordienstes erstellen. Diese Klasse bietet verschiedene Methoden zum Zugriff auf und zum Auflisten von Sensoren, zum Registrieren und Entfernen von Sensorereignis-Listenern und zum Abrufen von Orientierungsinformationen. Diese Klasse bietet auch mehrere Sensorkonstanten, mit denen die Sensorgenauigkeit erfasst, die Datenerfassungsraten festgelegt und Sensoren kalibriert werden.
Sensor
- Mit dieser Klasse können Sie eine Instanz eines bestimmten Sensors erstellen. Diese Klasse bietet verschiedene Methoden, mit denen Sie die Funktionen eines Sensors ermitteln können.
SensorEvent
- Das System verwendet diese Klasse, um ein Sensorereignisobjekt zu erstellen, das Informationen zu einem Sensorereignis enthält. Ein Sensorereignisobjekt enthält die folgenden Informationen: die Sensorrohdaten, den Sensortyp, der das Ereignis generiert hat, die Genauigkeit der Daten und den Zeitstempel des Ereignisses.
SensorEventListener
- Mit dieser Schnittstelle können Sie zwei Rückrufmethoden erstellen, die Benachrichtigungen (Sensorereignisse) erhalten, wenn sich die Sensorwerte oder die Sensorgenauigkeit ändern.
In einer typischen Anwendung werden diese sensorbezogenen APIs für zwei grundlegende Aufgaben verwendet:
- Sensoren und Sensorfunktionen identifizieren
Die Identifizierung von Sensoren und Sensorfunktionen während der Laufzeit ist nützlich, wenn Ihre Anwendung Funktionen enthält, die auf bestimmten Sensortypen oder ‐funktionen basieren. So können Sie beispielsweise alle Sensoren auf einem Gerät identifizieren und alle Anwendungsfunktionen deaktivieren, die auf nicht vorhandenen Sensoren basieren. Ebenso können Sie alle Sensoren eines bestimmten Typs identifizieren, damit Sie die Sensorimplementierung auswählen können, die für Ihre Anwendung die optimale Leistung bietet.
- Sensorereignisse beobachten
Durch das Überwachen von Sensorereignissen können Sie Rohsensordaten erfassen. Ein Sensorereignis tritt jedes Mal auf, wenn ein Sensor eine Änderung bei den gemessenen Parametern erkennt. Ein Sensorereignis enthält vier Informationen: den Namen des Sensors, der das Ereignis ausgelöst hat, den Zeitstempel für das Ereignis, die Genauigkeit des Ereignisses und die Rohdaten des Sensors, die das Ereignis ausgelöst haben.
Verfügbarkeit des Sensors
Die Verfügbarkeit des Sensors kann von Gerät zu Gerät und von Android-Version zu Android-Version variieren. Das liegt daran, dass die Android-Sensoren im Laufe mehrerer Plattformversionen eingeführt wurden. Beispielsweise wurden viele Sensoren in Android 1.5 (API-Level 3) eingeführt, einige waren jedoch erst implementiert und konnten erst ab Android 2.3 (API-Level 9) verwendet werden. Außerdem wurden in Android 2.3 (API-Level 9) und Android 4.0 (API-Level 14) mehrere Sensoren eingeführt. Zwei Sensoren wurden eingestellt und durch neuere, bessere Sensoren ersetzt.
In Tabelle 2 ist die Verfügbarkeit der einzelnen Sensoren für jede Plattform zusammengefasst. Es sind nur vier Plattformen aufgeführt, da es sich dabei um die Plattformen handelt, bei denen Sensoränderungen vorgenommen wurden. Sensoren, die als eingestellt aufgeführt sind, sind auf nachfolgenden Plattformen weiterhin verfügbar, sofern der Sensor auf einem Gerät vorhanden ist. Dies entspricht der Richtlinie zur Abwärtskompatibilität von Android.
Sensor | Android 4.0 (API-Level 14) |
Android 2.3 (API-Level 9) |
Android 2.2 (API-Level 8) |
Android 1.5 (API-Level 3) |
---|---|---|---|---|
TYPE_ACCELEROMETER |
Ja | Ja | Ja | Ja |
TYPE_AMBIENT_TEMPERATURE |
Ja | – | – | – |
TYPE_GRAVITY |
Ja | Ja | – | – |
TYPE_GYROSCOPE |
Ja | Ja | Nicht verfügbar1 | –1 |
TYPE_LIGHT |
Ja | Ja | Ja | Ja |
TYPE_LINEAR_ACCELERATION |
Ja | Ja | – | – |
TYPE_MAGNETIC_FIELD |
Ja | Ja | Ja | Ja |
TYPE_ORIENTATION |
Ja2 | Ja2 | Ja2 | Ja |
TYPE_PRESSURE |
Ja | Ja | Nicht verfügbar1 | –1 |
TYPE_PROXIMITY |
Ja | Ja | Ja | Ja |
TYPE_RELATIVE_HUMIDITY |
Ja | – | – | – |
TYPE_ROTATION_VECTOR |
Ja | Ja | – | – |
TYPE_TEMPERATURE |
Ja2 | Ja | Ja | Ja |
1 Dieser Sensortyp wurde in Android 1.5 (API-Level 3) hinzugefügt, konnte aber erst ab Android 2.3 (API-Level 9) verwendet werden.
2 Dieser Sensor ist verfügbar, wird aber nicht mehr unterstützt.
Sensoren und Sensorfunktionen identifizieren
Das Android-Sensor-Framework bietet mehrere Methoden, mit denen Sie ganz einfach ermitteln können, welche Sensoren sich auf einem Gerät befinden. Die API bietet auch Methoden, mit denen Sie die Funktionen jedes Sensors ermitteln können, z. B. maximale Reichweite, Auflösung und Leistungsanforderungen.
Um die Sensoren auf einem Gerät zu identifizieren, müssen Sie zuerst eine Referenz zum Sensordienst abrufen. Dazu erstellen Sie eine Instanz der Klasse SensorManager
, indem Sie die Methode getSystemService()
aufrufen und das Argument SENSOR_SERVICE
übergeben. Beispiel:
Kotlin
private lateinit var sensorManager: SensorManager ... sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
Java
private SensorManager sensorManager; ... sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
Als Nächstes können Sie eine Liste aller Sensoren auf einem Gerät abrufen. Dazu rufen Sie die Methode getSensorList()
auf und verwenden die Konstante TYPE_ALL
. Beispiel:
Kotlin
val deviceSensors: List<Sensor> = sensorManager.getSensorList(Sensor.TYPE_ALL)
Java
List<Sensor> deviceSensors = sensorManager.getSensorList(Sensor.TYPE_ALL);
Wenn Sie alle Sensoren eines bestimmten Typs auflisten möchten, können Sie anstelle von TYPE_ALL
eine andere Konstante verwenden, z. B. TYPE_GYROSCOPE
, TYPE_LINEAR_ACCELERATION
oder TYPE_GRAVITY
.
Sie können auch mithilfe der Methode getDefaultSensor()
und der Typkonstante für einen bestimmten Sensor feststellen, ob ein bestimmter Sensortyp auf einem Gerät vorhanden ist. Wenn ein Gerät mehr als einen Sensor eines bestimmten Typs hat, muss einer der Sensoren als Standardsensor festgelegt werden. Wenn für einen bestimmten Sensortyp kein Standardsensor vorhanden ist, gibt der Methodenaufruf „null“ zurück. Das bedeutet, dass das Gerät keinen Sensor dieses Typs hat. Mit dem folgenden Code wird beispielsweise geprüft, ob sich auf einem Gerät ein Magnetometer befindet:
Kotlin
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. }
Java
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. }
Hinweis:Android-Gerätehersteller sind nicht verpflichtet, bestimmte Sensortypen in ihre Android-Geräte einzubauen. Daher können Geräte eine Vielzahl von Sensorkonfigurationen haben.
Sie können nicht nur die Sensoren auf einem Gerät auflisten, sondern auch mithilfe der öffentlichen Methoden der Klasse Sensor
die Funktionen und Attribute einzelner Sensoren ermitteln. Das ist nützlich, wenn sich Ihre Anwendung je nach Sensoren oder Sensorfunktionen auf einem Gerät unterschiedlich verhalten soll. Sie können beispielsweise die Methoden getResolution()
und getMaximumRange()
verwenden, um die Auflösung und den maximalen Messbereich eines Sensors zu ermitteln. Sie können auch die Methode getPower()
verwenden, um die Leistungsanforderungen eines Sensors zu erhalten.
Zwei der öffentlichen Methoden sind besonders nützlich, wenn Sie Ihre Anwendung für Sensoren verschiedener Hersteller oder verschiedener Versionen eines Sensors optimieren möchten. Wenn Ihre Anwendung beispielsweise Nutzergesten wie Neigen und Schütteln überwachen muss, können Sie einen Satz von Datenfilterregeln und Optimierungen für neuere Geräte mit einem bestimmten Schwerkraftsensor eines bestimmten Anbieters und einen weiteren Satz von Datenfilterregeln und Optimierungen für Geräte erstellen, die keinen Gravitationssensor und nur einen Beschleunigungsmesser haben. Das folgende Codebeispiel zeigt, wie Sie dazu die Methoden getVendor()
und getVersion()
verwenden. In diesem Beispiel suchen wir nach einem Schwerkraftsensor, der Google LLC als Anbieter angibt und die Versionsnummer 3 hat. Wenn dieser Sensor nicht am Gerät vorhanden ist, versuchen wir, ihn zu verwenden.
Kotlin
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 } }
Java
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. } }
Eine weitere nützliche Methode ist die Methode getMinDelay()
. Sie gibt das minimale Zeitintervall (in Mikrosekunden) zurück, das ein Sensor zum Erfassen von Daten verwenden kann. Jeder Sensor, der für die Methode getMinDelay()
einen Wert ungleich null zurückgibt, ist ein Streamingsensor. Streamingsensoren erfassen Daten in regelmäßigen Abständen und wurden in Android 2.3 (API-Level 9) eingeführt. Wenn ein Sensor bei Aufruf der getMinDelay()
-Methode den Wert „0“ zurückgibt, ist er kein Streaming-Sensor, da er nur dann Daten meldet, wenn sich die von ihm gemessenen Parameter ändern.
Die Methode getMinDelay()
ist nützlich, da Sie damit die maximale Rate bestimmen können, mit der ein Sensor Daten erfassen kann. Wenn bestimmte Funktionen in Ihrer Anwendung hohe Datenerfassungsraten oder einen Streamingsensor erfordern, können Sie mit dieser Methode feststellen, ob ein Sensor diese Anforderungen erfüllt, und die entsprechenden Funktionen in Ihrer Anwendung entsprechend aktivieren oder deaktivieren.
Achtung:Die maximale Datenakquisitionsrate eines Sensors entspricht nicht unbedingt der Rate, mit der das Sensor-Framework Sensordaten an Ihre Anwendung liefert. Das Sensor-Framework meldet Daten anhand von Sensorereignissen. Dabei beeinflussen mehrere Faktoren die Geschwindigkeit, mit der Ihre Anwendung Sensorereignisse empfängt. Weitere Informationen finden Sie unter Sensorereignisse überwachen.
Sensorereignisse überwachen
Wenn Sie Rohsensordaten überwachen möchten, müssen Sie zwei Rückrufmethoden implementieren, die über die SensorEventListener
-Schnittstelle verfügbar sind: onAccuracyChanged()
und onSensorChanged()
. Das Android-System ruft diese Methoden immer dann auf, wenn Folgendes eintritt:
- Die Genauigkeit eines Sensors ändert sich.
In diesem Fall ruft das System die
onAccuracyChanged()
-Methode auf und stellt Ihnen einen Verweis auf das geänderteSensor
-Objekt und die neue Genauigkeit des Sensors zur Verfügung. Die Genauigkeit wird durch eine der vier Statuskonstanten dargestellt:SENSOR_STATUS_ACCURACY_LOW
,SENSOR_STATUS_ACCURACY_MEDIUM
,SENSOR_STATUS_ACCURACY_HIGH
oderSENSOR_STATUS_UNRELIABLE
. - Ein Sensor meldet einen neuen Wert.
In diesem Fall ruft das System die Methode
onSensorChanged()
auf und stellt einSensorEvent
-Objekt bereit. EinSensorEvent
-Objekt enthält Informationen zu den neuen Sensordaten, darunter die Genauigkeit der Daten, den Sensor, der die Daten generiert hat, den Zeitstempel, zu dem die Daten generiert wurden, und die neuen Daten, die der Sensor erfasst hat.
Im folgenden Code wird gezeigt, wie Sie mit der Methode onSensorChanged()
Daten vom Lichtsensor überwachen. In diesem Beispiel werden die Rohsensordaten in einem TextView
angezeigt, das in der Datei „main.xml“ als sensor_data
definiert ist.
Kotlin
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) } }
Java
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); } }
In diesem Beispiel wird die Standarddatenverzögerung (SENSOR_DELAY_NORMAL
) angegeben, wenn die Methode registerListener()
aufgerufen wird. Mit der Datenverzögerung (oder Abtastrate) wird das Intervall festgelegt, in dem Sensorereignisse über die onSensorChanged()
-Callback-Methode an Ihre Anwendung gesendet werden. Die Standarddatenverzögerung eignet sich für das Überwachen typischer Änderungen der Bildschirmausrichtung und verwendet eine Verzögerung von 200.000 Mikrosekunden. Sie können auch andere Datenverzögerungen angeben, z. B. SENSOR_DELAY_GAME
(20.000 Mikrosekunden), SENSOR_DELAY_UI
(60.000 Mikrosekunden) oder SENSOR_DELAY_FASTEST
(0 Mikrosekunden). Ab Android 3.0 (API-Level 11) können Sie die Verzögerung auch als absoluten Wert (in Mikrosekunden) angeben.
Die von Ihnen angegebene Verzögerung ist nur eine Empfehlung. Das Android-System und andere Anwendungen können diese Verzögerung ändern. Es wird empfohlen, die maximale Verzögerung anzugeben, da das System in der Regel eine kürzere Verzögerung verwendet als die von Ihnen angegebene. Sie sollten also die niedrigste Abtastrate auswählen, die die Anforderungen Ihrer Anwendung erfüllt. Eine längere Verzögerung belastet den Prozessor weniger und verbraucht daher weniger Strom.
Es gibt keine öffentliche Methode, um die Rate zu ermitteln, mit der das Sensor-Framework Sensorereignisse an Ihre Anwendung sendet. Sie können jedoch die Zeitstempel verwenden, die mit jedem Sensorereignis verknüpft sind, um die Abtastrate über mehrere Ereignisse hinweg zu berechnen. Die Abtastrate (Verzögerung) sollte nach der Festlegung nicht mehr geändert werden müssen. Wenn Sie die Verzögerung ändern müssen, müssen Sie die Registrierung des Sensor-Listeners aufheben und dann noch einmal registrieren.
Beachten Sie außerdem, dass in diesem Beispiel die Callback-Methoden onResume()
und onPause()
zum Registrieren und Entfernen des Sensorereignis-Listeners verwendet werden. Es hat sich bewährt, Sensoren, die Sie nicht benötigen, immer zu deaktivieren, insbesondere wenn Ihre Aktivität pausiert ist. Andernfalls kann der Akku in nur wenigen Stunden leer sein, da einige Sensoren einen hohen Energieverbrauch haben und den Akku schnell entladen können. Das System deaktiviert die Sensoren nicht automatisch, wenn das Display ausgeschaltet wird.
Umgang mit verschiedenen Sensorkonfigurationen
Android gibt keine Standardsensorkonfiguration für Geräte vor. Das bedeutet, dass Gerätehersteller beliebige Sensorkonfigurationen in ihre Android-Geräte einbinden können. Daher können Geräte eine Vielzahl von Sensoren in einer Vielzahl von Konfigurationen enthalten. Wenn Ihre Anwendung einen bestimmten Sensortyp benötigt, müssen Sie dafür sorgen, dass der Sensor auf dem Gerät vorhanden ist, damit Ihre App ausgeführt werden kann.
Sie haben zwei Möglichkeiten, um sicherzustellen, dass ein bestimmter Sensor auf einem Gerät vorhanden ist:
- Erkennt Sensoren während der Laufzeit und aktivieren oder deaktivieren Sie Anwendungsfunktionen nach Bedarf.
- Verwenden Sie Google Play-Filter, um eine Ausrichtung auf Geräte mit bestimmten Sensorkonfigurationen vorzunehmen.
Diese Optionen werden in den folgenden Abschnitten erläutert.
Sensoren zur Laufzeit erkennen
Wenn Ihre Anwendung einen bestimmten Sensortyp verwendet, aber nicht auf diesen angewiesen ist, können Sie das Sensor-Framework verwenden, um den Sensor zur Laufzeit zu erkennen und dann Anwendungsfunktionen nach Bedarf zu deaktivieren oder zu aktivieren. Eine Navigations-App kann beispielsweise den Temperatursensor, den Drucksensor, den GPS-Sensor und den Sensor für das geomagnetische Feld verwenden, um die Temperatur, den barometrischen Druck, den Standort und die Kompasspeilung anzuzeigen. Wenn ein Gerät keinen Drucksensor hat, können Sie das Sensor-Framework verwenden, um das Fehlen des Drucksensors zur Laufzeit zu erkennen und dann den Teil der Benutzeroberfläche Ihrer Anwendung zu deaktivieren, in dem der Druck angezeigt wird. Mit dem folgenden Code wird beispielsweise geprüft, ob sich ein Drucksensor am Gerät befindet:
Kotlin
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. }
Java
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. }
Google Play-Filter für die Ausrichtung auf bestimmte Sensorkonfigurationen verwenden
Wenn du deine App bei Google Play veröffentlichst, kannst du das Element <uses-feature>
in deiner Manifestdatei verwenden, um deine App auf Geräten zu filtern, die nicht über die entsprechende Sensorkonfiguration für deine App verfügen. Das Element <uses-feature>
enthält mehrere Hardwaredeskriptoren, mit denen Sie Anwendungen anhand bestimmter Sensoren filtern können. Zu den Sensoren, die Sie auflisten können, gehören: Beschleunigungsmesser, Barometer, Kompass (geomagnetisches Feld), Gyroskop, Licht und Näherung. Im folgenden Beispiel wird ein Manifesteintrag gezeigt, mit dem Apps ohne Beschleunigungsmesser herausgefiltert werden:
<uses-feature android:name="android.hardware.sensor.accelerometer" android:required="true" />
Wenn Sie dieses Element und diesen Descriptor dem Manifest Ihrer App hinzufügen, sehen Nutzer Ihre App bei Google Play nur, wenn ihr Gerät einen Beschleunigungsmesser hat.
Sie sollten den Deskriptor nur dann auf android:required="true"
festlegen, wenn Ihre Anwendung ausschließlich auf einem bestimmten Sensor basiert. Wenn Ihre Anwendung einen Sensor für einige Funktionen verwendet, aber auch ohne Sensor ausgeführt werden kann, sollten Sie den Sensor im Element <uses-feature>
angeben, aber den Descriptor auf android:required="false"
setzen. So können Ihre App auch auf Geräten installiert werden, die diesen Sensor nicht haben. Dies ist auch eine Best Practice für das Projektmanagement, mit der Sie den Überblick über die Funktionen Ihrer Anwendung behalten können.
Wenn Ihre Anwendung einen bestimmten Sensor verwendet, aber auch ohne ihn ausgeführt wird, sollten Sie den Sensor zur Laufzeit erkennen und die App-Funktionen entsprechend deaktivieren oder aktivieren.
Sensorkoordinatensystem
Im Allgemeinen verwendet das Sensor-Framework ein standardmäßiges 3-Achsen-Koordinatensystem, um Datenwerte auszudrücken. Bei den meisten Sensoren wird das Koordinatensystem relativ zum Display des Geräts definiert, wenn es in der Standardausrichtung gehalten wird (siehe Abbildung 1). Wenn ein Gerät in seiner Standardausrichtung gehalten wird, ist die X-Achse horizontal und zeigt nach rechts, die Y-Achse ist vertikal und zeigt nach oben und die Z-Achse zeigt zur Außenseite des Bildschirms. In diesem System haben Koordinaten hinter dem Bildschirm negative Z-Werte. Dieses Koordinatensystem wird von den folgenden Sensoren verwendet:
- Beschleunigungssensor
- Schwerkraftsensor
- Gyroskop
- Linearer Beschleunigungssensor
- Geomagnetischer Sensor
Das Wichtigste bei diesem Koordinatensystem ist, dass die Achsen nicht vertauscht werden, wenn sich die Bildschirmausrichtung des Geräts ändert. Das Koordinatensystem des Sensors ändert sich also nie, wenn sich das Gerät bewegt. Dieses Verhalten entspricht dem des OpenGL-Koordinatensystems.
Außerdem darf Ihre Anwendung nicht davon ausgehen, dass die Standardausrichtung eines Geräts im Hochformat ist. Die natürliche Ausrichtung vieler Tablets ist das Querformat. Außerdem basiert das Sensorkoordinatensystem immer auf der natürlichen Ausrichtung eines Geräts.
Wenn Ihre Anwendung schließlich Sensordaten mit dem Bildschirm auf dem Bildschirm abgleicht, müssen Sie die Methode getRotation()
verwenden, um die Bildschirmdrehung zu bestimmen, und dann die Methode remapCoordinateSystem()
verwenden, um die Sensorkoordinaten den Bildschirmkoordinaten zuzuordnen. Das ist auch dann erforderlich, wenn in Ihrem Manifest nur die Hochformatanzeige angegeben ist.
Hinweis:Einige Sensoren und Methoden verwenden ein Koordinatensystem, das relativ zum Bezugsrahmen der Welt (und nicht zum Bezugsrahmen des Geräts) ist. Diese Sensoren und Methoden geben Daten zurück, die die Gerätebewegung oder die Geräteposition relativ zur Erde darstellen. Weitere Informationen finden Sie unter den Methoden getOrientation()
und getRotationMatrix()
, dem Orientierungssensor und dem Rotationsvektorsensor.
Ratenbegrenzung des Sensors
Zum Schutz potenziell vertraulicher Nutzerdaten gilt Folgendes: Wenn Ihre App auf Android 12 (API-Level 31) oder höher ausgerichtet ist, legt das System ein Limit für die Aktualisierungsrate der Daten bestimmter Bewegungssensoren und Positionssensoren fest. Dazu gehören Werte, die vom Beschleunigungsmesser, Gyroskop und Sensor für das geomagnetische Feld des Geräts erfasst werden.
Die maximale Aktualisierungsrate hängt davon ab, wie Sie auf Sensordaten zugreifen:
- Wenn Sie die Methode
registerListener()
aufrufen, um Sensorereignisse zu überwachen, ist die Sensorabtastrate auf 200 Hz begrenzt. Das gilt für alle überladenen Varianten der MethoderegisterListener()
. - Wenn Sie die Klasse
SensorDirectChannel
verwenden, ist die Sensorabtastrate aufRATE_NORMAL
begrenzt, was in der Regel etwa 50 Hz entspricht.
Wenn Ihre App Bewegungssensordaten mit höherer Rate erfassen muss, müssen Sie die Berechtigung HIGH_SAMPLING_RATE_SENSORS
deklarieren, wie im folgenden Code-Snippet gezeigt. Andernfalls, wenn Ihre App versucht, Bewegungssensordaten mit einer höheren Rate zu erheben, ohne diese Berechtigung zu erklären, tritt eine SecurityException
auf.
<manifest ...> <uses-permission android:name="android.permission.HIGH_SAMPLING_RATE_SENSORS"/> <application ...> ... </application> </manifest>
Best Practices für den Zugriff auf und die Verwendung von Sensoren
Beachten Sie bei der Sensorimplementierung die in diesem Abschnitt beschriebenen Richtlinien. Diese Richtlinien sind Best Practices für alle, die das Sensor-Framework verwenden, um auf Sensoren zuzugreifen und Sensordaten zu erfassen.
Sensordaten nur im Vordergrund erheben
Auf Geräten mit Android 9 (API-Level 28) oder höher gelten für Apps, die im Hintergrund ausgeführt werden, die folgenden Einschränkungen:
- Bei Sensoren, die den kontinuierlichen Berichtsmodus verwenden, z. B. Beschleunigungsmesser und Gyroskope, werden keine Ereignisse empfangen.
- Für Sensoren, die die Berichtsmodi bei Änderung oder Einmal verwenden, werden keine Ereignisse empfangen.
Angesichts dieser Einschränkungen sollten Sie Sensorereignisse entweder erkennen, wenn sich Ihre App im Vordergrund befindet, oder als Teil eines Dienstes im Vordergrund.
Sensor-Listener abmelden
Deregistrieren Sie den Listener eines Sensors, wenn Sie ihn nicht mehr verwenden oder die Sensoraktivität pausiert. Wenn ein Sensor-Listener registriert und seine Aktivität pausiert wird, erfasst der Sensor weiterhin Daten und verwendet Akkuressourcen, bis Sie die Registrierung des Sensors aufheben. Im folgenden Code wird gezeigt, wie ein Listener mit der Methode onPause()
abgemeldet wird:
Kotlin
private lateinit var sensorManager: SensorManager ... override fun onPause() { super.onPause() sensorManager.unregisterListener(this) }
Java
private SensorManager sensorManager; ... @Override protected void onPause() { super.onPause(); sensorManager.unregisterListener(this); }
Weitere Informationen finden Sie unter unregisterListener(SensorEventListener)
.
Mit dem Android-Emulator testen
Der Android-Emulator enthält eine Reihe von virtuellen Sensorsteuerungen, mit denen Sie Sensoren wie Beschleunigungsmesser, Umgebungstemperatur, Magnetometer, Näherung und Licht testen können.
Der Emulator verwendet eine Verbindung mit einem Android-Gerät, auf dem die App SdkControllerSensor ausgeführt wird. Beachten Sie, dass diese App nur auf Geräten mit Android 4.0 (API-Level 14) oder höher verfügbar ist. Wenn auf dem Gerät Android 4.0 installiert ist, muss Revision 2 installiert sein. Die App SdkControllerSensor überwacht Änderungen an den Sensoren auf dem Gerät und überträgt sie an den Emulator. Der Emulator wird dann anhand der neuen Werte transformiert, die er von den Sensoren auf Ihrem Gerät empfängt.
Den Quellcode für die App SdkControllerSensor finden Sie hier:
$ your-android-sdk-directory/tools/apps/SdkController
So übertragen Sie Daten zwischen Ihrem Gerät und dem Emulator:
- Prüfen Sie, ob die USB-Fehlerbehebung auf Ihrem Gerät aktiviert ist.
- Verbinden Sie Ihr Gerät über ein USB-Kabel mit Ihrem Entwicklungscomputer.
- Starten Sie die App SdkControllerSensor auf Ihrem Gerät.
- Wählen Sie in der App die Sensoren aus, die Sie emulieren möchten.
Führen Sie dazu den folgenden
adb
-Befehl aus:- Starten Sie den Emulator. Sie sollten jetzt Transformationen auf den Emulator anwenden können, indem Sie Ihr Gerät bewegen.
$ adb forward tcp:1968 tcp:1968
Hinweis : Wenn sich der Simulator nicht durch die Bewegungen auf Ihrem physischen Gerät verändert, führen Sie den Befehl adb
aus Schritt 5 noch einmal aus.
Weitere Informationen finden Sie im Leitfaden zum Android-Emulator.
Blockieren Sie die Methode „onSensorChanged()“ nicht.
Sensordaten können sich sehr schnell ändern, was bedeutet, dass das System die onSensorChanged(SensorEvent)
-Methode möglicherweise ziemlich oft aufruft. Es empfiehlt sich, in der onSensorChanged(SensorEvent)
-Methode möglichst wenig zu tun, damit sie nicht blockiert wird. Wenn für Ihre Anwendung eine Datenfilterung oder eine Reduzierung von Sensordaten erforderlich ist, sollten Sie diese Arbeit außerhalb der Methode onSensorChanged(SensorEvent)
ausführen.
Nicht mehr unterstützte Methoden oder Sensortypen verwenden
Mehrere Methoden und Konstanten wurden eingestellt.
Insbesondere der Sensortyp TYPE_ORIENTATION
wurde eingestellt. Verwenden Sie stattdessen die Methode getOrientation()
, um Daten zur Ausrichtung abzurufen. Der Sensortyp TYPE_TEMPERATURE
wird ebenfalls nicht mehr unterstützt. Auf Geräten mit Android 4.0 sollten Sie stattdessen den Sensortyp TYPE_AMBIENT_TEMPERATURE
verwenden.
Prüfen Sie die Sensoren vor der Verwendung
Prüfen Sie immer, ob ein Sensor auf einem Gerät vorhanden ist, bevor Sie versuchen, Daten von ihm zu erfassen. Angenommen Sie nicht, dass ein Sensor vorhanden ist, nur weil er häufig verwendet wird. Gerätehersteller müssen keine bestimmten Sensoren in ihren Geräten bereitstellen.
Sensorverzögerungen sorgfältig auswählen
Wenn Sie einen Sensor mit der Methode registerListener()
registrieren, wählen Sie eine Übermittlungsrate aus, die für Ihre Anwendung oder Ihren Anwendungsfall geeignet ist. Sensoren können Daten mit sehr hohen Raten liefern. Wenn Sie dem System erlauben, zusätzliche Daten zu senden, die Sie nicht benötigen, werden Systemressourcen verschwendet und der Akku entlastet.