[android] Geomagnetic sensor support, compass calibration toasts

- Avoid allocation on each sensor data.
- Fixed non-working device orientation/compass on some devices without gyroscope
  (SM-C7000). Now Geomagnetic Rotation Vector sensor is used as a fallback.
- Ignore unreliable sensor events
- Removed unnecessary axes remapping for sensor data

Signed-off-by: Alexander Borsuk <me@alex.bio>
This commit is contained in:
Alexander Borsuk 2023-05-11 01:15:05 +02:00 committed by Alexander Borsuk
parent 3bbc4a15bf
commit 8ed32f934a
2 changed files with 144 additions and 26 deletions

View file

@ -5,67 +5,101 @@ import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import app.organicmaps.MwmApplication;
import app.organicmaps.R;
class SensorHelper implements SensorEventListener
{
@Nullable
@NonNull
private final SensorManager mSensorManager;
@Nullable
private Sensor mRotation;
@SuppressWarnings("NotNullFieldNotInitialized")
private final Sensor mRotationVectorSensor;
@NonNull
private final MwmApplication mMwmApplication;
private final float[] mRotationMatrix = new float[9];
private final float[] mRotationValues = new float[3];
// Initialized with purposely invalid value.
private int mLastAccuracy = -42;
@Override
public void onSensorChanged(SensorEvent event)
{
if (!mMwmApplication.arePlatformAndCoreInitialized())
// Here we can have events from one out of these two sensors:
// TYPE_GEOMAGNETIC_ROTATION_VECTOR
// TYPE_ROTATION_VECTOR
if (mLastAccuracy != event.accuracy)
{
mLastAccuracy = event.accuracy;
switch (mLastAccuracy)
{
case SensorManager.SENSOR_STATUS_ACCURACY_HIGH:
break;
case SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM:
Toast.makeText(mMwmApplication,
mMwmApplication.getString(R.string.compass_calibration_recommended),
Toast.LENGTH_LONG).show();
break;
case SensorManager.SENSOR_STATUS_ACCURACY_LOW:
case SensorManager.SENSOR_STATUS_UNRELIABLE:
default:
Toast.makeText(mMwmApplication,
mMwmApplication.getString(R.string.compass_calibration_required),
Toast.LENGTH_LONG).show();
}
}
if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE)
return;
notifyInternal(event);
}
SensorManager.getRotationMatrixFromVector(mRotationMatrix, event.values);
SensorManager.getOrientation(mRotationMatrix, mRotationValues);
private void notifyInternal(@NonNull SensorEvent event)
{
if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) {
float[] rotMatrix = new float[9];
SensorManager.getRotationMatrixFromVector(rotMatrix, event.values);
SensorManager.remapCoordinateSystem(rotMatrix,
SensorManager.AXIS_X, SensorManager.AXIS_Y, rotMatrix);
float[] rotVals = new float[3];
SensorManager.getOrientation(rotMatrix, rotVals);
// rotVals indexes: 0 - yaw, 2 - roll, 1 - pitch.
LocationHelper.INSTANCE.notifyCompassUpdated(rotVals[0]);
}
// mRotationValues indexes: 0 - yaw (azimuth), 1 - pitch, 2 - roll.
LocationHelper.INSTANCE.notifyCompassUpdated(mRotationValues[0]);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {}
public void onAccuracyChanged(Sensor sensor, int accuracy)
{
Log.w("onAccuracyChanged", "Sensor " + sensor.getStringType() + " has changed accuracy to " + accuracy);
// This method is called _only_ when accuracy changes. To know the initial startup accuracy,
// and to show calibration warning toast if necessary, we check it in onSensorChanged().
// Looks like modern Androids can send this event after starting the sensor.
}
SensorHelper(@NonNull Context context)
{
mMwmApplication = MwmApplication.from(context);
mSensorManager = (SensorManager) mMwmApplication.getSystemService(Context.SENSOR_SERVICE);
if (mSensorManager != null)
mRotation = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
Sensor sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR);
if (sensor == null)
{
Log.w("SensorHelper", "WARNING: There is no ROTATION_VECTOR sensor, requesting GEOMAGNETIC_ROTATION_VECTOR");
sensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GEOMAGNETIC_ROTATION_VECTOR);
if (sensor == null)
Log.w("SensorHelper", "WARNING: There is no GEOMAGNETIC_ROTATION_VECTOR sensor, device orientation can not be calculated");
}
// Can be null in rare cases on devices without magnetic sensors.
mRotationVectorSensor = sensor;
}
void start()
{
if (mRotation != null && mSensorManager != null)
mSensorManager.registerListener(this, mRotation, SensorManager.SENSOR_DELAY_UI);
if (mRotationVectorSensor != null)
mSensorManager.registerListener(this, mRotationVectorSensor, SensorManager.SENSOR_DELAY_UI);
}
void stop()
{
if (mSensorManager != null)
if (mRotationVectorSensor != null)
mSensorManager.unregisterListener(this);
}
}

View file

@ -6178,6 +6178,90 @@
zh-Hans = 指南针校准
zh-Hant = 指南針校準
[compass_calibration_recommended]
comment = Toast text when compass calibration may improve the correctness of the current position arrow
tags = android
en = Improve arrow direction by moving the phone in a figure-eight motion to calibrate the compass.
ar = قم بتحسين اتجاه السهم عن طريق تحريك الهاتف في حركة على شكل ثمانية لمعايرة البوصلة.
be = Палепшыце кірунак стрэлкі, перамяшчаючы тэлефон у выглядзе васьмёркі, каб адкалібраваць компас.
bg = Подобрете посоката на стрелката, като движите телефона с движение тип "осмица", за да калибрирате компаса.
ca = Milloreu la direcció de la fletxa movent el telèfon amb un moviment de vuit per calibrar la brúixola.
cs = Zlepšete směr šipky pohybem telefonu do osmičky a zkalibrujte kompas.
da = Forbedre pilens retning ved at bevæge telefonen i en ottetalsbevægelse for at kalibrere kompasset.
de = Verbessern Sie die Pfeilrichtung, indem Sie das Telefon in einer Achterbewegung bewegen, um den Kompass zu kalibrieren.
el = Βελτιώστε την κατεύθυνση των βελών μετακινώντας το τηλέφωνο με μια κίνηση σχήματος οκτώ για να βαθμονομήσετε την πυξίδα.
es = Mejora la dirección de la flecha moviendo el teléfono en forma de ocho para calibrar la brújula.
et = Parandage noole suunda, liigutades telefoni kaheksakäigulise liigutusega, et kalibreerida kompass.
eu = Hobetu geziaren norabidea telefonoa zortzi irudiko mugimenduan mugituz iparrorratza kalibratzeko.
fa = برای کالیبره کردن قطب نما، جهت پیکان را با حرکت دادن تلفن در یک حرکت شکل هشت بهبود دهید.
fi = Paranna nuolien suuntaa liikuttamalla puhelinta kahdeksikon suuntaisesti kompassin kalibroimiseksi.
fr = Améliorez la direction de la flèche en déplaçant le téléphone en huit pour calibrer la boussole.
he = שפר את כיוון החץ על ידי הזזת הטלפון בתנועה של שמונה כדי לכייל את המצפן.
hu = Javítsa a nyíl irányát a telefon nyolcas mozgatásával az iránytű kalibrálásához.
id = Perbaiki arah panah dengan menggerakkan ponsel dalam gerakan angka delapan untuk mengkalibrasi kompas.
it = Migliorare la direzione della freccia muovendo il telefono con un movimento a otto per calibrare la bussola.
ja = 携帯電話を8の字に動かしてコンパスを較正することで、矢印の方向を改善します。
ko = 나침반을 보정하기 위해 휴대폰을 8자 모양으로 움직여 화살표 방향을 개선하세요.
lt = Patobulinkite rodyklės kryptį judindami telefoną aštuoniukės judesiu, kad kompasas būtų sukalibruotas.
mr = कंपास कॅलिब्रेट करण्यासाठी फोनला आकृती-आठ मोशनमध्ये हलवून बाणाची दिशा सुधारा.
nb = Forbedre pilretningen ved å bevege telefonen i en åttetallsbevegelse for å kalibrere kompasset.
nl = Verbeter de richting van de pijl door de telefoon in een achtvormige beweging te bewegen om het kompas te kalibreren.
pl = Popraw kierunek strzałki, poruszając telefonem w ruchu w kształcie ósemki, aby skalibrować kompas.
pt = Melhore a direcção das setas movendo o telemóvel num movimento em forma de oito para calibrar a bússola.
pt-BR = Melhore a direção da seta movendo o telefone em um movimento em forma de oito para calibrar a bússola.
ro = Îmbunătățiți direcția săgeții prin mișcarea telefonului într-o mișcare în opt pentru a calibra busola.
ru = Улучшите направление стрелки, перемещая телефон восьмеркой, чтобы откалибровать компас.
sk = Zlepšite smer šípok pohybom telefónu v tvare osmičky, aby ste kalibrovali kompas.
sv = Förbättra pilens riktning genom att flytta telefonen i en åttarörelse för att kalibrera kompassen.
th = ปรับปรุงทิศทางลูกศรโดยขยับโทรศัพท์เป็นเลขแปดเพื่อปรับเทียบเข็มทิศ
tr = Pusulayı kalibre etmek için telefonu sekiz şeklinde hareket ettirerek ok yönünü iyileştirin.
uk = Покращіть напрямок стрілки, повернувши телефон вісімкою, щоб відкалібрувати компас.
vi = Cải thiện hướng mũi tên bằng cách di chuyển điện thoại theo chuyển động hình số tám để hiệu chỉnh la bàn.
zh-Hans = 通过以八字形运动移动手机来改善箭头方向,以校准罗盘。
zh-Hant = 通過以八字形移動手機來校準指南針來改善箭頭方向
[compass_calibration_required]
comment = Toast text when compass calibration may improve the correctness of the current position arrow
tags = android
en = Move the phone in a figure-eight motion to calibrate the compass and fix the arrow direction on the map.
ar = حرك الهاتف في حركة على شكل ثمانية لمعايرة البوصلة وإصلاح اتجاه السهم على الخريطة.
be = Перамяшчайце тэлефон у выглядзе васьмёркі, каб адкалібраваць компас і зафіксаваць кірунак стрэлкі на карце.
bg = Преместете телефона с движение тип "осмица", за да калибрирате компаса и да фиксирате посоката на стрелката върху картата.
ca = Moveu el telèfon amb un moviment de vuit per calibrar la brúixola i fixar la direcció de la fletxa al mapa.
cs = Pohybem telefonu do osmičky zkalibrujte kompas a zafixujte směr šipky na mapě.
da = Bevæg telefonen i en ottetalsbevægelse for at kalibrere kompasset og fastgøre pilens retning på kortet.
de = Bewegen Sie das Telefon in einer Achterbewegung, um den Kompass zu kalibrieren und die Pfeilrichtung auf der Karte festzulegen.
el = Μετακινήστε το τηλέφωνο με μια κίνηση σχήματος οκτώ για να βαθμονομήσετε την πυξίδα και να καθορίσετε την κατεύθυνση του βέλους στο χάρτη.
es = Mueve el teléfono en forma de ocho para calibrar la brújula y fijar la dirección de la flecha en el mapa.
et = Liigutage telefoni kaheksakandilise liigutusega, et kalibreerida kompass ja määrata noole suund kaardil.
eu = Mugitu telefonoa zortzi irudiko mugimenduan iparrorratza kalibratzeko eta geziaren norabidea mapan finkatzeko.
fa = تلفن را به شکل هشت حرکت دهید تا قطب نما را کالیبره کنید و جهت پیکان را روی نقشه ثابت کنید.
fi = Liikuta puhelinta kahdeksikon suuntaisella liikkeellä kompassin kalibroimiseksi ja nuolen suunnan määrittämiseksi kartalla.
fr = Déplacez le téléphone en huit pour calibrer la boussole et fixer la direction de la flèche sur la carte.
he = הזז את הטלפון בתנועה של דמות שמונה כדי לכייל את המצפן ולתקן את כיוון החץ במפה.
hu = Mozgassa a telefont egy nyolcas mozdulattal az iránytű kalibrálásához és a nyíl irányának rögzítéséhez a térképen.
id = Gerakkan ponsel dengan gerakan angka delapan untuk mengkalibrasi kompas dan memperbaiki arah panah pada peta.
it = Muovere il telefono con un movimento a otto per calibrare la bussola e fissare la direzione della freccia sulla mappa.
ja = 携帯電話を8の字に動かしてコンパスを校正し、地図上の矢印の方向を固定します。
ko = 휴대폰을 8자 모양으로 움직여 나침반을 보정하고 지도에서 화살표 방향을 수정합니다.
lt = Judinkite telefoną aštuoniukės formos judesiu, kad sukalibruotumėte kompasą ir žemėlapyje nustatytumėte rodyklės kryptį.
mr = होकायंत्र कॅलिब्रेट करण्यासाठी आणि नकाशावर बाणाची दिशा निश्चित करण्यासाठी फोनला आकृती-आठ मोशनमध्ये हलवा.
nb = Beveg telefonen i en åttetallsbevegelse for å kalibrere kompasset og fikse pilretningen på kartet.
nl = Beweeg de telefoon in een achtvormige beweging om het kompas te kalibreren en de richting van de pijl op de kaart vast te stellen.
pl = Przesuń telefon ruchem w kształcie ósemki, aby skalibrować kompas i ustalić kierunek strzałki na mapie.
pt = Mova o telemóvel num movimento em forma de oito para calibrar a bússola e fixar a direcção da seta no mapa.
pt-BR = Mova o telefone em um movimento em forma de oito para calibrar a bússola e fixar a direção da seta no mapa.
ro = Mișcați telefonul într-o mișcare în formă de opt pentru a calibra busola și a fixa direcția săgeții pe hartă.
ru = Двигайте телефон восьмеркой, чтобы откалибровать компас и зафиксировать направление стрелки на карте.
sk = Pohybom telefónu v tvare osmičky kalibrujte kompas a zafixujte smer šípky na mape.
sv = Flytta telefonen i en åttarörelse för att kalibrera kompassen och fastställa pilens riktning på kartan.
th = ขยับโทรศัพท์เป็นเลขแปดเพื่อปรับเทียบเข็มทิศและกำหนดทิศทางลูกศรบนแผนที่
tr = Pusulayı kalibre etmek ve haritadaki ok yönünü sabitlemek için telefonu sekiz şeklinde hareket ettirin.
uk = Рухайте телефон вісімкою, щоб відкалібрувати компас і зафіксувати напрямок стрілки на карті.
vi = Di chuyển điện thoại theo chuyển động hình số tám để hiệu chỉnh la bàn và cố định hướng mũi tên trên bản đồ.
zh-Hans = 以八字动作移动手机,校准罗盘,并在地图上固定箭头方向。
zh-Hant = 以 8 字形移動手機以校準指南針並固定地圖上的箭頭方向
[downloader_update_all_button]
comment = Update all button text
tags = android,ios