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 oder Änderungen in der Umgebung eines Geräts überwachen 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 große Sensorkategorien:
- Bewegungssensoren
Diese Sensoren messen Beschleunigungs- und Drehkräfte entlang von 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. Zu dieser Kategorie gehören Barometer, Fotometer und Thermometer.
- Positionssensoren
Diese Sensoren messen die physische Position eines Geräts. Diese Kategorie umfasst Ausrichtungssensoren und Magnetometer.
Mit dem Android-Sensor-Framework können Sie auf die auf dem Gerät verfügbaren Sensoren zugreifen und Rohdaten 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:
- Sie können prüfen, 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 Thema 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
Über das 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 nachahmen. 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 mehr als einen Sensor 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 | Misst die Beleuchtungsstärke in Lux. | 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. | Einen 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 ermitteln |
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 Smartphones 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
Sie können über das Android-Sensor-Framework auf diese Sensoren zugreifen und Rohdaten 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
- Anhand dieser Klasse erstellt das System ein Sensorereignisobjekt, das Informationen zu einem Sensorereignis enthält. Ein Sensorereignisobjekt enthält die folgenden Informationen: die Rohsensordaten, den Sensortyp, der das Ereignis generiert hat, die Genauigkeit der Daten und den Zeitstempel für das Ereignis.
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 zur Laufzeit ist nützlich, wenn Ihre Anwendung Funktionen hat, 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, um die Sensorimplementierung mit der optimalen Leistung für Ihre Anwendung auszuwählen.
- Sensorereignisse überwachen
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. So wurden beispielsweise viele Sensoren in Android 1.5 (API-Level 3) eingeführt, aber einige wurden erst in Android 2.3 (API-Level 9) implementiert und waren erst dann verfügbar. Ebenso 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 erforderlich waren. 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 | –1 | –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 | –1 | –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 zur Laufzeit ganz einfach ermitteln können, welche Sensoren sich auf einem Gerät befinden. Die API bietet auch Methoden, mit denen Sie die Funktionen der einzelnen Sensoren ermitteln können, z. B. ihren maximalen Bereich, ihre Auflösung und ihre 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, indem Sie die Methode getSensorList()
mit der Konstante TYPE_ALL
aufrufen. 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 feststellen, ob ein bestimmter Sensortyp auf einem Gerät vorhanden ist, indem Sie die Methode getDefaultSensor()
verwenden und die Typkonstante für einen bestimmten Sensor übergeben. 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 die Funktionen und Attribute einzelner Sensoren mithilfe der öffentlichen Methoden der Klasse Sensor
ermitteln. Das ist nützlich, wenn sich Ihre Anwendung je nach Sensoren oder Sensorfunktionen auf einem Gerät unterschiedlich verhalten soll. Mit den Methoden getResolution()
und getMaximumRange()
können Sie beispielsweise die Auflösung und den maximalen Messbereich eines Sensors 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 eine Reihe von Datenfilterregeln und -optimierungen für neuere Geräte mit dem Gravitationssensor eines bestimmten Anbieters und eine weitere Reihe von Datenfilterregeln und -optimierungen für Geräte erstellen, die keinen Gravitationssensor, sondern nur einen Beschleunigungsmesser haben. Das folgende Codebeispiel zeigt, wie Sie dazu die Methoden getVendor()
und getVersion()
verwenden können. In diesem Beispiel suchen wir nach einem Gravitationssensor, bei dem Google LLC als Anbieter angegeben ist und der die Versionsnummer 3 hat. Wenn dieser Sensor nicht auf dem Gerät vorhanden ist, versuchen wir, das Gyroskop 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 getMinDelay()
-Methode, mit der das minimale Zeitintervall (in Mikrosekunden) zurückgegeben wird, das ein Sensor zum Erfassen von Daten verwenden kann. Jeder Sensor, der für die Methode getMinDelay()
einen Wert ungleich 0 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 über Sensorereignisse. Die Häufigkeit, mit der Ihre Anwendung Sensorereignisse empfängt, wird von mehreren Faktoren beeinflusst. 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 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 Ihnen einSensorEvent
-Objekt zur Verfügung. 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 Einrichtung nicht mehr geändert werden müssen. Wenn Sie die Verzögerung aus irgendeinem Grund ändern müssen, müssen Sie den Sensor-Listener unregisteren und neu 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 erfordert, 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:
- Sensoren zur Laufzeit erkennen und Anwendungsfunktionen entsprechend aktivieren oder deaktivieren
- 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 darauf angewiesen ist, können Sie mit dem Sensor-Framework den Sensor zur Laufzeit erkennen und dann die Anwendungsfunktionen entsprechend deaktivieren oder 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 mit dem Sensor-Framework das Fehlen des Drucksensors zur Laufzeit erkennen und dann den Teil der Benutzeroberfläche Ihrer Anwendung deaktivieren, in dem der Druck angezeigt wird. Mit dem folgenden Code wird beispielsweise geprüft, ob sich auf einem Gerät ein Drucksensor 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 Sie Ihre App bei Google Play veröffentlichen, können Sie mit dem Element <uses-feature>
in Ihrer Manifestdatei Ihre App von Geräten herausfiltern, die nicht die richtige Sensorkonfiguration für Ihre App haben. Das Element <uses-feature>
hat mehrere Hardware-Beschreibungen, mit denen Sie Anwendungen basierend auf der Anwesenheit 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 wird, sollten Sie den Sensor im Element <uses-feature>
angeben, aber den Descriptor auf android:required="false"
festlegen. So können Geräte Ihre App auch dann installieren, wenn sie diesen bestimmten 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 der 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 Displays. In diesem System haben Koordinaten hinter dem Bildschirm negative Z-Werte. Dieses Koordinatensystem wird von den folgenden Sensoren verwendet:
- Beschleunigungssensor
- Gravitationsensor
- 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 Standardausrichtung vieler Tablets ist Querformat. Das Sensorkoordinatensystem basiert immer auf der natürlichen Ausrichtung eines Geräts.
Wenn Ihre Anwendung Sensordaten mit dem Displayinhalt abgleicht, müssen Sie die Methode getRotation()
verwenden, um die Bildschirmdrehung zu ermitteln, und dann die Methode remapCoordinateSystem()
, um 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 sich auf den Weltkoordinatenbezug bezieht (im Gegensatz zum Gerätekoordinatenbezug). 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.
Sensor-Ratenbegrenzung
Wenn Ihre App auf Android 12 (API-Level 31) oder höher ausgerichtet ist, schränkt das System zum Schutz potenziell vertraulicher Nutzerdaten die Aktualisierungsrate von Daten bestimmter Bewegungs- und Positionssensoren ein. Dazu gehören Werte, die vom Beschleunigungsmesser, Gyroskop und Magnetfeldsensor des Geräts erfasst wurden.
Das Limit für die 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 deklarieren, 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.
Nur Sensordaten 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.
Registrierung von Sensor-Listenern aufheben
Deregistrieren Sie den Listener eines Sensors, wenn Sie ihn nicht mehr verwenden oder die Sensoraktivität pausiert. Wenn ein Sensor-Listener registriert ist und seine Aktivität pausiert wird, erfasst der Sensor weiterhin Daten und verbraucht Akkuressourcen, es sei denn, Sie heben die Registrierung des Sensors auf. 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 zu einem Android-Gerät, auf dem die App SdkControllerSensor ausgeführt wird. Diese App ist nur auf Geräten mit Android 4.0 (API-Level 14) oder höher verfügbar. 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 Anwendung 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, innerhalb 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.
Verwenden Sie keine eingestellten Methoden oder Sensortypen.
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.
Sensoren vor der Verwendung prüfen
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 sind nicht verpflichtet, bestimmte Sensoren in ihren Geräten zu verwenden.
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.