Referències:
Quan parlem de «sensors» en Android solem referir-nos als de moviment: l'acceleròmetre i el giroscopi (brúixola 3D).
També son sensors (però no de moviment) la càmera, el micro, la pantalla tàctil i el GPS.
Si mirem la documentació oficial podrem veure que la llibreria Android disposa dels següents deteccions:
Els dos darrers son les dades «en cru» tal i com arriben dels sensors. Els altres son mecanismes de la llibreria per facilitar-nos la programació.
En aquesta versió apareix la clàssica herència de AppCompatActivity
però alhora s'aplica la interface SensorEventListener
, fet que ens obligarà a implementar els mètodes onSensorChanged
i onAccuracyChanged
:
class MainActivity : AppCompatActivity(), SensorEventListener { private lateinit var sensorManager: SensorManager private lateinit var accelerometre: Sensor private lateinit var binding: ActivityMainBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() // Utilitzem bindings per facilitar accés als elements gràfics // recorda activar-los a build.gradle.kts afegint: // viewBinding { enable = true } binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) // escoltar variacions dels sensors sensorManager = getSystemService( Context.SENSOR_SERVICE) as SensorManager accelerometre = sensorManager.getDefaultSensor( Sensor.TYPE_ACCELEROMETER) as Sensor sensorManager.registerListener(this, accelerometre, SensorManager.SENSOR_DELAY_NORMAL) } override fun onSensorChanged(event: SensorEvent) { // emprem les dades del sensor val x = event.values[0] val y = event.values[1] val z = event.values[2] // 1g = 9,8 m/s² , què és un valor força alt. // Al fer *10 ens acostem als 100, que és el valor màxim per defecte de la ProgressBar binding.xProgressBar.progress = abs(x*10.0).toInt() binding.yProgressBar.progress = abs(y*10.0).toInt() binding.zProgressBar.progress = abs(z*10.0).toInt() } override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { // TODO("Not yet implemented") } }
Versió amb objecte SensorEventListener
que encapsula les callbacks onSensorChanged
i onAccuracyChanged
:
public class MainActivity extends AppCompatActivity { private SensorManager sensorManager; private Sensor sensor; SensorEventListener sensorListener; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); sensorListener = new SensorEventListener() { @Override public void onSensorChanged(SensorEvent sensorEvent) { // Valors de l'acceleròmetre en m/s^2 float xAcc = sensorEvent.values[0]; float yAcc = sensorEvent.values[1]; float zAcc = sensorEvent.values[2]; // Processament o visualització de dades... } @Override public void onAccuracyChanged(Sensor sensor, int i) { // Es pot ignorar aquesta CB de moment } }; // Seleccionem el tipus de sensor (veure doc oficial) sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); // registrem el Listener per capturar els events del sensor if( sensor!=null ) { sensorManager.registerListener(sensorListener,sensor, SensorManager.SENSOR_DELAY_NORMAL); } } }
Implementa una app que visualitzi els valors de l'acceleròmetre seguint l'exemple anterior on emprem el Sensor.TYPE_ACCELEROMETER
. Tens unes captures de pantalla més a baix de com pots fer la app.
Llença l'app al teu dispositiu mòbil.
Com has de col·locar el mòbil per aconseguir aquests valors (aproximats)?:
Substitueix els TextView
amb número per una ProgressBar
, i mostra-ho en valor absolut (si no, els valors negatius no es visualitzaran).
Compara amb el resultat de Sensor.TYPE_LINEAR_ACCELERATION
. Quina diferència veus?
Double «thud»
Normalment parlem de tap o double tap per a interaccions de «toc» de la pantalla. Aquest exercici vol detectar «tocs» però no de pantalla, sinó «tocs» a qualsevol part del mòbil. Per això en direm thud enlloc de tap (consultant un sinònim de "tap").
Implementarem un detector de «double thud». No ha de reaccionar amb 1 sol «thud» ni tampoc si ens desplacem ràpid o fem una sacsejada del mòbil.
Una primera aproximació podria ser implementar un comptador de thuds en cadascun dels eixos XYZ. Hauràs d'establir un llindar d'acceleració a partir del qual consideres que ha succeït un «thud». Defineix el llindar en una constant de l'aplicació (fàcilment localitzable i ajustable).
Assegura que al canviar la orientació (portrait/landscape) no es reinicien els comptadors a zero (un canvi d'orientació reconstrueix l'objecte Activity de nou). El mètode més directe és implementar onSaveInstanceState de la Activity Lifecycle.