Czujniki pozycji

Platforma Android udostępnia 2 czujniki, które umożliwiają określenie położenia urządzenia: czujnik pola geomagnetycznego i akcelerometr. Platforma Android udostępnia też czujnik, który pozwala określić, jak blisko obiektu znajduje się przednia część urządzenia (tzw. czujnik zbliżeniowy). Czujnik pola geomagnetycznego i czujnik zbliżeniowy są oparte na sprzęcie. Większość producentów telefonów i tabletów instaluje czujnik pola geomagnetycznego. Podobnie producenci telefonów zwykle umieszczają w nich czujnik zbliżeniowy, który wykrywa, kiedy telefon jest trzymany blisko twarzy użytkownika (np. podczas rozmowy). Do określania orientacji urządzenia możesz używać odczytów z akcelerometru i czujnika pola geomagnetycznego.

Uwaga: czujnik orientacji został wycofany w Androidzie 2.2 (poziom API 8), a typ czujnika orientacji został wycofany w Androidzie 4.4W (poziom API 20).

Czujniki położenia są przydatne do określania fizycznego położenia urządzenia w odniesieniu do świata. Możesz na przykład użyć czujnika pola geomagnetycznego w połączeniu z akcelerometrem, aby określić położenie urządzenia względem północy magnetycznej. Możesz też używać tych czujników do określania orientacji urządzenia w ramach odniesienia aplikacji. Czujniki położenia nie są zwykle używane do monitorowania ruchu urządzenia, np. wstrząsów, przechyleń czy pchnięć (więcej informacji znajdziesz w sekcji Czujniki ruchu).

Czujnik pola geomagnetycznego i akcelerometr zwracają wielowymiarowe tablice wartości czujnika dla każdego SensorEvent. Na przykład czujnik pola geomagnetycznego dostarcza wartości siły pola geomagnetycznego dla każdej z 3 osi współrzędnych podczas jednego zdarzenia czujnika. Podobnie akcelerometr mierzy przyspieszenie, które jest przykładane do urządzenia podczas zdarzenia czujnika. Więcej informacji o układach współrzędnych używanych przez czujniki znajdziesz w artykule Układy współrzędnych czujników. Czujnik zbliżeniowy podaje jedną wartość dla każdego zdarzenia czujnika. W tabeli 1 znajdziesz podsumowanie czujników pozycji obsługiwanych na platformie Android.

Tabela 1. czujniki położenia obsługiwane na platformie Android;

Czujnik Dane zdarzeń z czujników Opis Jednostki miary
TYPE_GAME_ROTATION_VECTOR SensorEvent.values[0] Składowa wektora rotacji wzdłuż osi X (x * sin(θ/2)). Bez jednostek
SensorEvent.values[1] Składowa wektora rotacji wzdłuż osi y (y * sin(θ/2)).
SensorEvent.values[2] Składowa wektora rotacji wzdłuż osi z (z * sin(θ/2)).
TYPE_GEOMAGNETIC_ROTATION_VECTOR SensorEvent.values[0] Składowa wektora rotacji wzdłuż osi X (x * sin(θ/2)). Bez jednostek
SensorEvent.values[1] Składowa wektora rotacji wzdłuż osi y (y * sin(θ/2)).
SensorEvent.values[2] Składowa wektora rotacji wzdłuż osi z (z * sin(θ/2)).
TYPE_MAGNETIC_FIELD SensorEvent.values[0] Natężenie pola geomagnetycznego wzdłuż osi x. μT
SensorEvent.values[1] Natężenie pola geomagnetycznego wzdłuż osi y.
SensorEvent.values[2] Natężenie pola geomagnetycznego wzdłuż osi z.
TYPE_MAGNETIC_FIELD_UNCALIBRATED SensorEvent.values[0] Siła pola geomagnetycznego (bez kalibracji twardego żelaza) wzdłuż osi x. μT
SensorEvent.values[1] Siła pola geomagnetycznego (bez kalibracji twardego żelaza) wzdłuż osi Y.
SensorEvent.values[2] Siła pola geomagnetycznego (bez kalibracji twardego żelaza) wzdłuż osi z.
SensorEvent.values[3] Szacowanie odchylenia żelaza wzdłuż osi x.
SensorEvent.values[4] Szacowanie odchylenia żelaza wzdłuż osi y.
SensorEvent.values[5] Szacowanie odchylenia żelaza wzdłuż osi z.
TYPE_ORIENTATION1 SensorEvent.values[0] Azymut (kąt wokół osi Z). Stopnie
SensorEvent.values[1] Pochylenie (kąt wokół osi X).
SensorEvent.values[2] Obrót (kąt wokół osi Y).
TYPE_PROXIMITY SensorEvent.values[0] Odległość od obiektu2 cm

1 Ten czujnik został wycofany w Androidzie 2.2 (API na poziomie 8), a ten typ czujnika został wycofany w Androidzie 4.4W (API na poziomie 20). Platforma czujników udostępnia alternatywne metody uzyskiwania orientacji urządzenia, które zostały omówione w rozdziale Obliczanie orientacji urządzenia.

2 Niektóre czujniki zbliżeniowe podają tylko wartości binarne, które oznaczają blisko i daleko.

Korzystanie z czujnika wektora rotacji gry

Czujnik wektora rotacji gry jest identyczny z czujnikiem wektora rotacji, z wyjątkiem tego, że nie korzysta z pola geomagnetycznego. Dlatego oś Y nie jest skierowana na północ, ale w innym kierunku. Odchylenie od tego punktu odniesienia może być tego samego rzędu co odchylenie żyroskopu wokół osi Z.

Czujnik wektora rotacji gry nie korzysta z pola magnetycznego, więc względne rotacje są dokładniejsze i nie mają na nie wpływu zmiany pola magnetycznego. Użyj tego czujnika w grze, jeśli nie zależy Ci na tym, gdzie jest północ, a normalny wektor rotacji nie spełnia Twoich potrzeb, ponieważ zależy od pola magnetycznego.

Poniższy kod pokazuje, jak uzyskać instancję domyślnego czujnika wektora rotacji gry:

Kotlin

private lateinit var sensorManager: SensorManager
private var sensor: Sensor? = null
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);

Korzystanie z czujnika wektora rotacji geomagnetycznej

Czujnik wektora rotacji geomagnetycznej jest podobny do czujnika wektora rotacji, ale nie korzysta z żyroskopu. Dokładność tego czujnika jest mniejsza niż w przypadku zwykłego czujnika wektora rotacji, ale zużycie energii jest mniejsze. Używaj tego czujnika tylko wtedy, gdy chcesz zbierać informacje o obrocie w tle bez nadmiernego zużywania baterii. Ten czujnik jest najbardziej przydatny w połączeniu z grupowaniem.

Poniższy kod pokazuje, jak uzyskać instancję domyślnego czujnika wektora rotacji geomagnetycznej:

Kotlin

private lateinit var sensorManager: SensorManager
private var sensor: Sensor? = null
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR);

Obliczanie orientacji urządzenia

Obliczając orientację urządzenia, możesz monitorować jego położenie względem układu odniesienia Ziemi (a konkretnie magnetycznego bieguna północnego). Poniższy kod pokazuje, jak obliczyć orientację urządzenia:

Kotlin

private lateinit var sensorManager: SensorManager
...
// Rotation matrix based on current readings from accelerometer and magnetometer.
val rotationMatrix = FloatArray(9)
SensorManager.getRotationMatrix(rotationMatrix, null, accelerometerReading, magnetometerReading)

// Express the updated rotation matrix as three orientation angles.
val orientationAngles = FloatArray(3)
SensorManager.getOrientation(rotationMatrix, orientationAngles)

Java

private SensorManager sensorManager;
...
// Rotation matrix based on current readings from accelerometer and magnetometer.
final float[] rotationMatrix = new float[9];
SensorManager.getRotationMatrix(rotationMatrix, null,
    accelerometerReading, magnetometerReading);

// Express the updated rotation matrix as three orientation angles.
final float[] orientationAngles = new float[3];
SensorManager.getOrientation(rotationMatrix, orientationAngles);

System oblicza kąty orientacji za pomocą czujnika pola geomagnetycznego urządzenia w połączeniu z akcelerometrem urządzenia. Dzięki tym 2 czujnikom sprzętowym system dostarcza dane dotyczące tych 3 kątów orientacji:

  • Azymut (stopnie obrotu wokół osi –z). Jest to kąt między bieżącym kierunkiem kompasu urządzenia a północą magnetyczną. Jeśli górna krawędź urządzenia jest skierowana na północ magnetyczną, azymut wynosi 0 stopni, a jeśli jest skierowana na południe – 180 stopni. Podobnie, jeśli górna krawędź jest skierowana na wschód, azymut wynosi 90 stopni, a jeśli jest skierowana na zachód – 270 stopni.
  • Pochylenie (stopnie obrotu wokół osi x). Jest to kąt między płaszczyzną równoległą do ekranu urządzenia a płaszczyzną równoległą do podłoża. Jeśli trzymasz urządzenie równolegle do podłoża, a dolna krawędź jest skierowana w Twoją stronę, i przechylisz górną krawędź urządzenia w kierunku podłoża, kąt pochylenia będzie dodatni. Przechylenie w przeciwnym kierunku – przesunięcie górnej krawędzi urządzenia w górę – powoduje, że kąt pochylenia staje się ujemny. Zakres wartości wynosi od -90 do 90 stopni.
  • Obrót (stopnie obrotu wokół osi Y). Jest to kąt między płaszczyzną prostopadłą do ekranu urządzenia a płaszczyzną prostopadłą do podłoża. Jeśli trzymasz urządzenie równolegle do podłoża, a dolna krawędź jest skierowana w Twoją stronę, i przechylisz lewą krawędź urządzenia w kierunku podłoża, kąt przechyłu będzie dodatni. Przechylenie w przeciwnym kierunku – przesunięcie prawej krawędzi urządzenia w stronę podłoża – powoduje, że kąt przechyłu staje się ujemny. Zakres wartości to od -180 do 180 stopni.

Uwaga: definicja obrotu czujnika została zmieniona, aby odzwierciedlać zdecydowaną większość implementacji w ekosystemie czujników geograficznych.

Pamiętaj, że te kąty działają w innym systemie współrzędnych niż ten używany w lotnictwie (w przypadku odchylenia, pochylenia i przechylenia). W systemie lotniczym oś X przebiega wzdłuż dłuższego boku samolotu, od ogona do dziobu.

Czujnik orientacji uzyskuje dane, przetwarzając nieprzetworzone dane z akcelerometru i czujnika pola geomagnetycznego. Ze względu na duże obciążenie procesora dokładność i precyzja czujnika orientacji są mniejsze. W szczególności ten czujnik jest wiarygodny tylko wtedy, gdy kąt przechyłu wynosi 0. W związku z tym czujnik orientacji został wycofany w Androidzie 2.2 (poziom interfejsu API 8), a typ czujnika orientacji został wycofany w Androidzie 4.4W (poziom interfejsu API 20). Zamiast używać surowych danych z czujnika orientacji, zalecamy używanie metody getRotationMatrix() w połączeniu z metodą getOrientation() do obliczania wartości orientacji, jak pokazano w tym przykładzie kodu: W ramach tego procesu możesz użyć metody remapCoordinateSystem() do przetłumaczenia wartości orientacji na układ odniesienia aplikacji.

Kotlin

class SensorActivity : Activity(), SensorEventListener {

    private lateinit var sensorManager: SensorManager
    private val accelerometerReading = FloatArray(3)
    private val magnetometerReading = FloatArray(3)

    private val rotationMatrix = FloatArray(9)
    private val orientationAngles = FloatArray(3)

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
        // Do something here if sensor accuracy changes.
        // You must implement this callback in your code.
    }

    override fun onResume() {
        super.onResume()

        // Get updates from the accelerometer and magnetometer at a constant rate.
        // To make batch operations more efficient and reduce power consumption,
        // provide support for delaying updates to the application.
        //
        // In this example, the sensor reporting delay is small enough such that
        // the application receives an update before the system checks the sensor
        // readings again.
        sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)?.also { accelerometer ->
            sensorManager.registerListener(
                    this,
                    accelerometer,
                    SensorManager.SENSOR_DELAY_NORMAL,
                    SensorManager.SENSOR_DELAY_UI
            )
        }
        sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)?.also { magneticField ->
            sensorManager.registerListener(
                    this,
                    magneticField,
                    SensorManager.SENSOR_DELAY_NORMAL,
                    SensorManager.SENSOR_DELAY_UI
            )
        }
    }

    override fun onPause() {
        super.onPause()

        // Don't receive any more updates from either sensor.
        sensorManager.unregisterListener(this)
    }

    // Get readings from accelerometer and magnetometer. To simplify calculations,
    // consider storing these readings as unit vectors.
    override fun onSensorChanged(event: SensorEvent) {
        if (event.sensor.type == Sensor.TYPE_ACCELEROMETER) {
            System.arraycopy(event.values, 0, accelerometerReading, 0, accelerometerReading.size)
        } else if (event.sensor.type == Sensor.TYPE_MAGNETIC_FIELD) {
            System.arraycopy(event.values, 0, magnetometerReading, 0, magnetometerReading.size)
        }
    }

    // Compute the three orientation angles based on the most recent readings from
    // the device's accelerometer and magnetometer.
    fun updateOrientationAngles() {
        // Update rotation matrix, which is needed to update orientation angles.
        SensorManager.getRotationMatrix(
                rotationMatrix,
                null,
                accelerometerReading,
                magnetometerReading
        )

        // "rotationMatrix" now has up-to-date information.

        SensorManager.getOrientation(rotationMatrix, orientationAngles)

        // "orientationAngles" now has up-to-date information.
    }
}

Java

public class SensorActivity extends Activity implements SensorEventListener {

    private SensorManager sensorManager;
    private final float[] accelerometerReading = new float[3];
    private final float[] magnetometerReading = new float[3];

    private final float[] rotationMatrix = new float[9];
    private final float[] orientationAngles = new float[3];

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Do something here if sensor accuracy changes.
        // You must implement this callback in your code.
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Get updates from the accelerometer and magnetometer at a constant rate.
        // To make batch operations more efficient and reduce power consumption,
        // provide support for delaying updates to the application.
        //
        // In this example, the sensor reporting delay is small enough such that
        // the application receives an update before the system checks the sensor
        // readings again.
        Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
        if (accelerometer != null) {
            sensorManager.registerListener(this, accelerometer,
                SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
        }
        Sensor magneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
        if (magneticField != null) {
            sensorManager.registerListener(this, magneticField,
                SensorManager.SENSOR_DELAY_NORMAL, SensorManager.SENSOR_DELAY_UI);
        }
    }

    @Override
    protected void onPause() {
        super.onPause();

        // Don't receive any more updates from either sensor.
        sensorManager.unregisterListener(this);
    }

    // Get readings from accelerometer and magnetometer. To simplify calculations,
    // consider storing these readings as unit vectors.
    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
          System.arraycopy(event.values, 0, accelerometerReading,
              0, accelerometerReading.length);
        } else if (event.sensor.getType() == Sensor.TYPE_MAGNETIC_FIELD) {
            System.arraycopy(event.values, 0, magnetometerReading,
                0, magnetometerReading.length);
        }
    }

    // Compute the three orientation angles based on the most recent readings from
    // the device's accelerometer and magnetometer.
    public void updateOrientationAngles() {
        // Update rotation matrix, which is needed to update orientation angles.
        SensorManager.getRotationMatrix(rotationMatrix, null,
            accelerometerReading, magnetometerReading);

        // "rotationMatrix" now has up-to-date information.

        SensorManager.getOrientation(rotationMatrix, orientationAngles);

        // "orientationAngles" now has up-to-date information.
    }
}

Zwykle nie musisz przetwarzać ani filtrować surowych kątów orientacji urządzenia, poza przetłumaczeniem układu współrzędnych czujnika na układ odniesienia aplikacji.

Korzystanie z czujnika pola geomagnetycznego

Czujnik pola geomagnetycznego umożliwia monitorowanie zmian w polu magnetycznym Ziemi. Poniższy kod pokazuje, jak uzyskać instancję domyślnego czujnika pola geomagnetycznego:

Kotlin

private lateinit var sensorManager: SensorManager
private var sensor: Sensor? = null
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);

Uwaga: jeśli Twoja aplikacja jest kierowana na Androida 12 (poziom API 31) lub nowszego, ten czujnik ma ograniczoną częstotliwość.

Ten czujnik dostarcza surowe dane o sile pola (w μT) dla każdej z 3 osi współrzędnych. Zwykle nie musisz używać tego czujnika bezpośrednio. Zamiast tego możesz użyć czujnika wektora rotacji, aby określić surowy ruch obrotowy, lub użyć akcelerometru i czujnika pola geomagnetycznego w połączeniu z metodą getRotationMatrix(), aby uzyskać macierz rotacji i macierz nachylenia. Następnie możesz użyć tych macierzy z metodami getOrientation()getInclination(), aby uzyskać dane o azymucie i inklinacji geomagnetycznej.

Uwaga: podczas testowania aplikacji możesz zwiększyć dokładność czujnika, poruszając urządzeniem w kształcie ósemki.

Korzystanie z niekalibrowanego magnetometru

Nie skalibrowany magnetometr jest podobny do czujnika pola geomagnetycznego, z tym że do pola magnetycznego nie jest stosowana kalibracja twardego żelaza. Kalibracja fabryczna i kompensacja temperatury są nadal stosowane do pola magnetycznego. Nie skalibrowany magnetometr przydaje się do obsługi nieprawidłowych szacunków twardego żelaza. Ogólnie rzecz biorąc, geomagneticsensor_event.values[0] będzie zbliżone do uncalibrated_magnetometer_event.values[0] - uncalibrated_magnetometer_event.values[3]. Oznacza to, że

calibrated_x ~= uncalibrated_x - bias_estimate_x

Uwaga: niekalibrowane czujniki dostarczają więcej surowych wyników i mogą zawierać pewne odchylenia, ale ich pomiary zawierają mniej skoków wynikających z korekt stosowanych podczas kalibracji. Niektóre aplikacje mogą preferować te niekalibrowane wyniki, ponieważ są one bardziej płynne i wiarygodne. Jeśli na przykład aplikacja próbuje przeprowadzić własną fuzję czujników, wprowadzenie kalibracji może zniekształcić wyniki.

Oprócz pola magnetycznego niekalibrowany magnetometr podaje też szacunkowe odchylenie spowodowane przez ferromagnetyzm w każdej osi. Poniższy kod pokazuje, jak uzyskać instancję domyślnego niekalibrowanego magnetometru:

Kotlin

private lateinit var sensorManager: SensorManager
private var sensor: Sensor? = null
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD_UNCALIBRATED);

Korzystanie z czujnika zbliżeniowego

Czujnik zbliżeniowy pozwala określić, jak daleko obiekt znajduje się od urządzenia. Poniższy kod pokazuje, jak uzyskać instancję domyślnego czujnika zbliżeniowego:

Kotlin

private lateinit var sensorManager: SensorManager
private var sensor: Sensor? = null
...
sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)

Java

private SensorManager sensorManager;
private Sensor sensor;
...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);

Czujnik zbliżeniowy jest zwykle używany do określania, jak daleko głowa osoby znajduje się od przedniej części urządzenia (np. podczas wykonywania lub odbierania połączenia telefonicznego). Większość czujników zbliżeniowych zwraca bezwzględną odległość w centymetrach, ale niektóre zwracają tylko wartości „blisko” i „daleko”.

Uwaga: w niektórych modelach urządzeń czujnik zbliżeniowy znajduje się pod ekranem, co może powodować miganie kropki na ekranie, jeśli jest włączony, gdy ekran jest włączony.

Poniższy kod pokazuje, jak używać czujnika zbliżeniowego:

Kotlin

class SensorActivity : Activity(), SensorEventListener {

    private lateinit var sensorManager: SensorManager
    private var proximity: Sensor? = null

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main)

        // Get an instance of the sensor service, and use that to get an instance of
        // a particular sensor.
        sensorManager = getSystemService(Context.SENSOR_SERVICE) as SensorManager
        proximity = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY)
    }

    override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {
        // Do something here if sensor accuracy changes.
    }

    override fun onSensorChanged(event: SensorEvent) {
        val distance = event.values[0]
        // Do something with this sensor data.
    }

    override fun onResume() {
        // Register a listener for the sensor.
        super.onResume()

        proximity?.also { proximity ->
            sensorManager.registerListener(this, proximity, SensorManager.SENSOR_DELAY_NORMAL)
        }
    }

    override fun onPause() {
        // Be sure to unregister the sensor when the activity pauses.
        super.onPause()
        sensorManager.unregisterListener(this)
    }
}

Java

public class SensorActivity extends Activity implements SensorEventListener {
    private SensorManager sensorManager;
    private Sensor proximity;

    @Override
    public final void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        // Get an instance of the sensor service, and use that to get an instance of
        // a particular sensor.
        sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
        proximity = sensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
    }

    @Override
    public final void onAccuracyChanged(Sensor sensor, int accuracy) {
        // Do something here if sensor accuracy changes.
    }

    @Override
    public final void onSensorChanged(SensorEvent event) {
        float distance = event.values[0];
        // Do something with this sensor data.
    }

    @Override
    protected void onResume() {
        // Register a listener for the sensor.
        super.onResume();
        sensorManager.registerListener(this, proximity, SensorManager.SENSOR_DELAY_NORMAL);
      }

    @Override
    protected void onPause() {
        // Be sure to unregister the sensor when the activity pauses.
        super.onPause();
        sensorManager.unregisterListener(this);
    }
}

Uwaga: niektóre czujniki zbliżeniowe zwracają wartości binarne, które oznaczają „blisko” lub „daleko”. W takim przypadku czujnik zwykle zgłasza maksymalną wartość zakresu w stanie dalekim i mniejszą wartość w stanie bliskim. Zwykle wartość daleka jest większa niż 5 cm, ale może się różnić w zależności od czujnika. Maksymalny zasięg czujnika możesz określić za pomocą getMaximumRange().

Warto też przeczytać