Beschleunigungssensoren unter Android [] (Beschleunigungssensoren unter Android), Lektion, Seite 722740
https://www.purl.org/stefan_ram/pub/beschleunigungssensoren_android (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
Android-Entwicklung

Beschleunigungssensoren unter Android 

Ein Programm kann Informationen über die Beschleunigungsmeßwerte  erhalten, indem es diese abonniert. Der Sensor ruft danach immer, wenn neue Meßwerte verfügbar sind, die Methode »Main#onSensorChanged(android.hardware.SensorEvent)« mit den neuen Meßwerten im Argumentobjekt auf.

In der folgenden Hauptklasse der Anwendung erfolgt das Abonnieren mit »new Sense( this )«. Das damit nur vorübergehend erzeugte Objekt der Klasse »Sense« sorgt dafür, daß die Methode »Main#onSensorChanged(android.hardware.SensorEvent)« nun wiederholt mit den Meßwerten aufgerufen wird. Dabei ist »Sense« eine Hilfsklasse, die weiter unten vorgestellt wird, aber hier zur Vereinfachung noch nicht abgedruckt wurde.

Die Methode »Main#onSensorChanged(android.hardware.SensorEvent)« zeigt den Namen des aktuellen Verlaufs an, um zu zeigen, daß diese Methode auf dem Hauptverlauf (UI-Verlauf) läuft und gibt die Meßwerte aus.

»Main« (Klasse)
/** Diese Klasse definiert eine Aktivität, die unter Android
ausgeführt werden kann. */

public class
Main extends android.app.Activity
{ /** Dieser Zeichenfolgenbauer dient zum Aufbau der dann in dem Textfeld
angezeigten Zeichenfolge. */

java.lang.StringBuilder
builder; /** Dieses Textfeld wird im Fenster der Aktivität angezeigt. */
android.widget.TextView
textView; /** Diese Methode legt fest, was das Objekt bei Erhalt der Nachricht
{@code onCreate(android.os.Bundle)} tun soll. Hier wird ein Textfeld
angezeigt, und ein Abonnement von Nachrichten über Gravitationsmessungen
gestartet. */

@java.lang.Override public void
onCreate( final android.os.Bundle bundle )
{ super.onCreate( bundle );
Main.this.textView = new android.widget.TextView( this );
setContentView( Main.this.textView );
Main.this.builder = new java.lang.StringBuilder();
new Sense( this ); } /* TODO */ /*
protected void onResume()
{ super.onResume();
mSensorManager.registerListener(this, mAccelerometer, SensorManager.SENSOR_DELAY_NORMAL); } */
/* TODO */
/* hardware sensor could run down battery */ /*
protected void onPause()
{ super.onPause();
mSensorManager.unregisterListener( this );} */
/** Diese Methode legt fest, was das Objekt bei Erhalt der Nachricht
{@code onCreate(android.os.Bundle)} tun soll. Hier wird ein Textfeld
angezeigt, und ein Abonnement von Nachrichten über Gravitationsmessungen
gestartet. */

public void
onSensorChanged( final android.hardware.SensorEvent event )
{ Main.this.builder.setLength( 0 );
Main.this.builder.append( java.lang.Thread.currentThread().getName() );
Main.this.builder.append( "\nx = " ); builder.append( event.values[ 0 ]);
Main.this.builder.append( "\ny = " ); builder.append( event.values[ 1 ]);
Main.this.builder.append( "\nz = " ); builder.append( event.values[ 2 ]);
Main.this.textView.setText( builder.toString() ); }}

Hier folgt nun noch das vollständige Programm mit den beiden Hilfsklassen »SensorUtils« und »Sense«.

Die Klasse »SensorUtils« exportiert im wesentlichen nur eine Methode, nämlich »SensorUtils#register(android.app.Activity activity,android.hardware.SensorEventListener)«, welche es erlaubt, ein android.hardware.SensorEventListener-Objekt als Empfänger für Beschleunigungsmessungen zu registrieren.

Objekte der Klasse »Sense« sind android.hardware.SensorEventListener-Objekte, welche dafür bestimmt sind von den Beschleunigungssensoren aufgerufen zu werden, und dann die interessante Nachricht »android.hardware.SensorEventListener#onSensorChanged(android.hardware.SensorEvent)« an das Hauptprogramm (ein Objekt der Klasse »Main«) weiterleiten können.

Um weitere Details zu verstehen kann der folgende mit Dokumentationskommentaren versehene Quellcode gelesen werden.

Main.java
package com.example;

/** Diese nicht-anwendungsspezifische Klasse unterstützt die Registrierung
für Nachrichten über Beschleunigung. */

class
SensorUtils
{ /** Die Aktivität, deren Methode {@code getSystemService} dieses
Objekt verwenden soll, um den Sensor-Manager zu erhalten. */

private android.app.Activity
activity = null; /** Ein Sensormanager des Sensordienstes. */
private android.hardware.SensorManager
manager = null; /** Diese Funktion beschafft einen Sensor-Manager, falls
noch keiner vorhanden ist. */

private void
obtainManager()
{ if( SensorUtils.this.manager == null )
SensorUtils.this.manager =( android.hardware.SensorManager )
SensorUtils.this.activity.getSystemService
( android.content.Context.SENSOR_SERVICE ); }

/** Eine Liste der Beschleunigungssensoren. */
private java.util.List accelerometerSensors = null; /** Diese Funktion beschafft eine Liste der Beschleunigungssensoren, falls
noch keine vorhanden ist. */

private void
obtainAccelerometerSensors()
{ obtainManager();
if( SensorUtils.this.accelerometerSensors == null )
SensorUtils.this.accelerometerSensors = SensorUtils.this.manager.getSensorList
( android.hardware.Sensor.TYPE_ACCELEROMETER ); } /** Der als Nachrichtensender ausgewählte Beschleunigungssensor. */
private android.hardware.Sensor
accelerometerSensor = null; /** Diese Funktion beschafft einen Beschleunigungssensor, falls
noch keiner vorhanden ist. */

private void
obtainAccelerometerSensor()
{ obtainAccelerometerSensors();
if( SensorUtils.this.accelerometerSensors.size() > 0 )
SensorUtils.this.accelerometerSensor =( android.hardware.Sensor )
SensorUtils.this.accelerometerSensors.get( 0 ); } /** Diese Funktion registriert einen Empfänger für Beschleunigungsmeßwerte.
@param activity Die Aktivität, deren Methode {@code getSystemService} dieses
Objekt verwenden soll, um den Sensor-Manager zu erhalten.
@param listener Der Empfänger, der Beschleunigungsnachrichten verarbeiten kann
@return ein Wahrheitswert, der true bei Erfolg ist */

public boolean register
( final android.app.Activity activity,
final android.hardware.SensorEventListener listener )
{ SensorUtils.this.activity = activity;
obtainAccelerometerSensor();
if( SensorUtils.this.accelerometerSensor != null )
{ obtainManager();
return SensorUtils.this.manager.registerListener
( listener, SensorUtils.this.accelerometerSensor,
android.hardware.SensorManager.SENSOR_DELAY_GAME ); }
else return false; }} /** Diese anwendungsspezifische Klasse unterstützt das Erhalten von
Beschleunigungsnachrichten, indem sie die Schnittstelle
{@code android.hardware.SensorEventListener} implementiert. */

class
Sense implements android.hardware.SensorEventListener
{ final Main main; /** Dieser Konstruktor initialisiert dieses Objekt und startet
das Senden von Nachrichten über Beschleunigungsmessung an die
dieses Objekt.
@param main Ein main-Objekt, an welches die Nachrichten weitergeleitet
werden sollen. */

public
Sense( final Main main )
{ this.main = main; new SensorUtils().register( main, this ); } /** Diese Methode dient zur Implementation der Schnittstelle
{@code android.hardware.SensorEventListener} und zur Weiterleitung
an die Methode {@code onSensorChanged(android.hardware.SensorEvent)}
des main-Objektes, das im Konstruktor übergeben wurde. */

@java.lang.Override public void
onSensorChanged
( final android.hardware.SensorEvent event )
{ this.main.onSensorChanged( event ); } /** Diese Methode dient zur Implementation der Schnittstelle
{@code android.hardware.SensorEventListener}. Nachrichten über
Änderungen der Genauigkeit werden absichtlich ignoriert.
@param sensor wird absichtlich ignoriert
@param accuracy wird absichtlich ignoriert */

@java.lang.Override public void
onAccuracyChanged
( final android.hardware.Sensor sensor, final int accuracy ) { }} /** Diese Klasse definiert eine Aktivität, die unter Android
ausgeführt werden kann. */

public class
Main extends android.app.Activity
{ /** Dieses Textfeld wird im Fenster der Aktivität angezeigt. */
java.lang.StringBuilder builder;
android.widget.TextView textView; /** Diese Methode legt fest, was das Objekt bei Erhalt der Nachricht
{@code onCreate(android.os.Bundle)} tun soll. Hier wird ein Textfeld
angezeigt, und ein Abonnement von Nachrichten über Gravitationsmessungen
gestartet.
@param bundle enthält zuletzt mit onSaveInstanceState(android.os.Bundle)
gespeicherte Daten */

@java.lang.Override /* android.app.Activity */ public void
onCreate /* Main */
( final android.os.Bundle bundle )
{ super.onCreate( bundle );
Main.this.textView = new android.widget.TextView( this );
setContentView( Main.this.textView );
Main.this.builder = new java.lang.StringBuilder();
new Sense( this ); }

/** Diese Methode legt fest, was das Objekt bei Erhalt der Nachricht
{@code onCreate(android.os.Bundle)} tun soll. Hier wird ein Textfeld
angezeigt, und ein Abonnement von Nachrichten über Gravitationsmessungen
gestartet. */

public void
onSensorChanged /* Main */
( final android.hardware.SensorEvent event )
{ Main.this.builder.setLength( 0 );
Main.this.builder.append( java.lang.Thread.currentThread().getName() );
Main.this.builder.append( "\nx = " ); builder.append( event.values[ 0 ]);
Main.this.builder.append( "\ny = " ); builder.append( event.values[ 1 ]);
Main.this.builder.append( "\nz = " ); builder.append( event.values[ 2 ]);
Main.this.textView.setText( builder.toString() ); }}

Übungsaufgaben

/   Darstellung von Meßwerten durch Farben

Wir hatten schon behandelt, wie farbige Flächen  dargestellt werden können. Kombinieren Sie die Darstellung einer farbigen Fläche  nun mit dem Empfangen von Beschleunigungsdaten, so daß eine Fläche angezeigt wird, deren Farbe durch die Beschleunigungsmeßwerte bestimmt wird!

Dazu sollten die Beschleunigungsdaten von »Main#onSensorChanged(android.hardware.SensorEvent)« abgespeichert und in »onDraw(android.graphics.Canvas)« ausgelesen werden. Dazu kann die Klasse »Rect« aus dem ersten Beispielprogramm der Zeichenflächen-Lektion in das Programm dieser Lektion kopiert werden. Außerdem müssen dann noch Hilfsvariablen zur Klasse »Main« hinzugefügt werden, um die Werte zu speichern, und es müssen einige Anweisungen etwas angepaßt werden. Wenn man Java  gut kennt, dauert das nur wenige Minuten, aber wenn man Java  gut kennt, kann man auch einen anderen Lösungsweg beschreiten als den im vorherigen Satz beschriebenen.

Ein besonderes hierbei auftretendes Problem ist noch die Umrechnung der Beschleunigungswerte in Farbwerte. Hier gibt es verschiedene mögliche  Vorgehensweisen, aber es kommt hierbei sicher gelegen, daß es drei  Beschleunigungsmeßwerte gibt und eine Farbe auch drei  Farbkomponenten umfaßt. Die Details sind dem Bearbeiter überlassen, doch sollte der Farbraum einigermaßen ausgenutzt werden, so daß möglichst jeder Beschleunigung eine andere Farbe entspricht, außerdem sollten die Farbwerte zweier Beschleunigungsmessungen, die sich nur wenig voneinander unterscheiden, sich auch nur wenig voneinander unterscheiden. Bei der Realisierung der Umrechnung sind Personen mit guten Mathematikkenntnissen etwas im Vorteil. Man sollte daran denken, daß ein Beschleunigungsmeßwert auch negativ werden kann, während eine Farbintensität (RGB) stets positiv ist. Außerdem ist die Größe einer Beschleunigung theoretisch nach oben hin fast nicht begrenzt, während ein Argumentwert von »android.graphics.Canvas#drawRGB(int,int,int)« zwischen 0 und 255 liegen muß.

Der Effekt dieser Übung ist erst richtig sichtbar, wenn man ein Programm auf einem physikalischen  Android -Gerät laufen läßt und nicht auf dem Emulator, da der Emulator kaum zur Messung von Beschleunigungswerten geeignet ist. Jedoch kann man den mit dem Emulator viele Beschleunigungssensorprogramme testen, wenn man die gemessen Werte durch Addition von kleinen Zufallszahlen etwas „verrauscht“.

Zusatzaufgaben

/   Glätten der Werte

(Diese Übungsaufgabe ist nur sinnvoll, wenn das obenstehende Programm auf einem realen Gerät läuft, weil die Anzeigewerte sich dann manchmal ständig verändern und „hin- und herwackeln“.)

1.) Schreiben Sie das Programm so um, daß „geglättete“ Werte angezeigt werden. (Der angezeigte Wert soll sich aus einer Mittelung der letzten Werte erhalten. Das genaue zur Mittelung verwendete Verfahren kann dabei vom Bearbeiter dieser Übungsaufgabe festgelegt werden.)

2.) Schreiben Sie das Programm so um, daß das Dezimaltrennzeichen der angezeigten Werte immer an derselben Stelle auf dem Bildschirm erscheint. Die Werte sollen also nicht „hin- und herwackeln“.

3.) Falls Sie die Aufgabe zur Anzeige von Beschleunigungsmeßwerten durch Farben schon gelöst haben, bauen Sie die Glättung auch in dieses Programm ein.

/   Wasserwaage *

Programmieren Sie eine Wasserwaage.

/   Seismograph *

Programmieren Sie einen Seismographen. Das Gerät soll bei der Nutzung auf einer Fläche so fixiert werden, daß die Anzeige nach oben zeigt.

/   Integration **

Programmieren Sie ein Gerät, das die Geschwindigkeit und die zurückgelegte Strecke anzeigt. Dabei wird angenommen, daß das Gerät immer so gehalten wird, daß die Anzeige genau vom Erdmittelpunkt weg zeigt.

Das Gerät soll einen Taster haben, um es bei Ruhe auf die Geschwindigkeit 0 zu eichen.

/   Ball *

Programmieren Sie einen Ball, dessen Position oder Geschwindigkeit oder Beschleunigung der gemessenen Beschleunigung gleicht.

Der Openintents-Sensorsimulator *

Der Openintents-Sensorsimulator erlaubt es, Bewegungen auf dem Emulator  zu simulieren. Er ist aber doch so unhandlich, daß er in diesem Kurs nicht  verwendet wird, insbesondere, weil man doch das Programm, welches die Sensordaten liest, und dessen Manifest-Datei anpassen muß (dann kann man dieses Programm auch gleich so umschreiben, daß es die Daten aus einer anderen Quelle bezieht). Trotzdem finden sich hier einige Notizen zu seiner Verwendung, die aber noch nicht vollständig erprobt wurden.

1. download
http://openintents.googlecode.com/files/sensorsimulator-1.0.0-beta1.zip
2. entpacken
3. starten von
sensorsimulator.jar
4.
@CALL "env.cmd"
%ADB% install SensorSimulatorSettings.apk
PAUSE

C:\Users\...\AppData\Local\android-sdk_r24.0.2-windows\android-sdk-windows\platform-tools\adb.exe" -e install SensorSimulatorSettings.apk
1232 KB/s (48266 bytes in 0.031s)
pkg: /data/local/tmp/SensorSimulatorSettings.apk
Success
5.
Diese Anwendung verwenden, um die IP-Adresse aus dem Jar-Programm, das im Schritt 3 gestartet wurde, einzustellen. Diese Einstellungen werden dann auch von der im nächsten Schritt eingebundenen Bibliothek verwendet.
6.
Die Bibliothek »sensorsimulator-lib.jar« in den lib-Ordner des Projektes legen und in das Projekt aufnehmen.
7.
Die Berechtigung »<uses-permission android:name="android.permission.INTERNET"/>« in die Manifest-Datei des Projektes eintragen.
8.
Statt des System-Sensor-Managers, den des Simulators verwenden:
    final android.hardware.SensorManager manager =( android.hardware.SensorManager )
super.getSystemService( android.content.Context.SENSOR_SERVICE );
--> final android.hardware.SensorManager manager =( android.hardware.SensorManager )
org.openintents.sensorsimulator.hardware.SensorManagerSimulator.getSystemService
( this, android.content.Context.SENSOR_SERVICE );
9.
Verbindung herstellen (Dabei werden die Einstellungen aus Schritt 5 verwendet).
mSensorManager.connectSimulator();

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram722740 stefan_ram:722740 Beschleunigungssensoren unter Android Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd722740, slrprddef722740, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/beschleunigungssensoren_android