Czujniki/Sensory Kontynuacja projektu "Stan urządzenia" Dla ułatwienia kod do odczytywania stanu urządzenia można zamknąć w komentarze //region STAN URZĄDZENIA ... //endregion i zwinąć. 1. SensorManager - zarejestrujemy nasluchiwacz (klasa aktywności będzie go implementować), którego metoda onSensorChanged będzie wywoływana gdy zmieni się stan czujnika. Nie będziemy jednak od razu wyświetlać wyniku, a zapiszemy go do pól, które co 2 sekundy będzi odczytywany i zapisywany do struktur wyświetlanych w liście. a. Dodajemy do klasy StanActivity informację o implementowaniu SensorEventListener. Interfejs ten rządza zdefiniowania dwóch metod onAccuracyChanged (będzie pusta) i onSensorChanged (zrobimy to później) public class StanActivity extends Activity implements SensorEventListener { ... b. Definiujemy prywatne pola: //zarzadca czujnikow private SensorManager sensorManager = null; Sensor akcelerometr = null; Sensor magnetometr = null; //Sensor orientacja = null; //pola, w ktorych zapisywane beda przyspieszenie, pole mg i orientacja static float ax = 0; //m/s^2 static float ay = 0; static float az = 0; static float a = 0; static float mx = 0; //mT static float my = 0; static float mz = 0; static float m = 0; /* static float oz_azymut = 0; //stopnie static float ox_pochylenie = 0; static float oy_nachylenie = 0; */ c. Pierwsza grupe pól inicjujemy w metodzie StanActivity.onResume @Override protected void onResume() { super.onResume(); //czujniki if(sensorManager==null) { //Toast.makeText(getApplicationContext(), "Rozpoczynam odczyty czujników", Toast.LENGTH_LONG).show(); sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); akcelerometr = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); magnetometr = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); //orientacja = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); sensorManager.registerListener(this,akcelerometr,SensorManager.SENSOR_DELAY_NORMAL); sensorManager.registerListener(this,magnetometr,SensorManager.SENSOR_DELAY_NORMAL); //sensorManager.registerListener(this,orientacja,SensorManager.SENSOR_DELAY_NORMAL); } } d. Wyrejestrowujemy w onPause: @Override protected void onPause() { super.onPause(); if(batteryReceiver!=null) this.getApplicationContext().unregisterReceiver(batteryReceiver); if(sensorManager!=null) sensorManager.unregisterListener(this); //czujniki } e. Definiujemy metody interfejsu SensorEventListener (może to za nas zrobić Eclipse): //metody SensorEventListener public void onAccuracyChanged(Sensor sensor, int accuracy) { // } public void onSensorChanged(SensorEvent event) { switch(event.sensor.getType()) { case Sensor.TYPE_ACCELEROMETER: ax = event.values[0]; ay = event.values[1]; az = event.values[2]; a = (float)Math.sqrt(ax*ax+ay*ay+az*az); //FloatMath jest deprecated break; case Sensor.TYPE_MAGNETIC_FIELD: mx = event.values[0]; my = event.values[1]; mz = event.values[2]; m = (float)Math.sqrt(mx*mx+my*my+mz*mz); break; /* case Sensor.TYPE_ORIENTATION: oz_azymut = event.values[0]; ox_pochylenie = event.values[1]; oy_nachylenie = event.values[2]; break; */ } } f. Zapisane w tych metodach pola odczytujemy w metodach odczyta.. static private UrzadzenieInfo odczytajAkcelerometr(Activity activity) { UrzadzenieInfo akcelerometrInfo = new UrzadzenieInfo(); akcelerometrInfo.typInformacji = TypInformacji.Czujnik; akcelerometrInfo.nazwa="Akcelerometr"; akcelerometrInfo.opis = "ax=" + ax + "\nay=" + ay + "\naz=" + az + "\na=" + a + " [m/s^2]"; akcelerometrInfo.polozeniePaska = (a>100)?100:(int)a; return akcelerometrInfo; } static private UrzadzenieInfo odczytajMagnetometr(Activity activity) { UrzadzenieInfo magnetometrInfo = new UrzadzenieInfo(); magnetometrInfo.typInformacji = TypInformacji.Czujnik; magnetometrInfo.nazwa="Magnetometr"; magnetometrInfo.opis = "Bx=" + mx + "\nBy=" + my + "\nBz=" + mz + "\nB=" + m + " [mT]"; magnetometrInfo.polozeniePaska = (m>100)?100:(int)m; return magnetometrInfo; } /* static private UrzadzenieInfo odczytajOrientacje(Activity activity) { UrzadzenieInfo orientacjaInfo = new UrzadzenieInfo(); orientacjaInfo.typInformacji = TypInformacji.Czujnik; orientacjaInfo.nazwa="Orientacja"; orientacjaInfo.opis = "azymut=" + oz_azymut + "\npochylenie=" + ox_pochylenie + "\nnachylenie=" + oy_nachylenie + " [stopnie]"; orientacjaInfo.polozeniePaska = -1; return orientacjaInfo; } */ g. Wywolania tych metod dodajemy do metody odswiezListe: listaUrzadzen.add(odczytajAkcelerometr(this)); listaUrzadzen.add(odczytajMagnetometr(this)); //listaUrzadzen.add(odczytajOrientacje(this)); 2. LocationManager - lokacja (nie mylić z lokalizacją) - schemat identyczny jak wyżej a. Zaczynamy od uprawnień, jakie musi zadeklarować aplikacja, aby korzystać z lokalizacji (zgrubnej i dokładnej). Dodajemy poniższe znaczniki do pliku manifestu (za uses-sdk): b. Definiujemy pole LocationManager i pole Location, w którym będziemy zapisywać położenie odczytane w metodzie związanej z kolejnym interfejsem - LocationListener (trzeba go dodać!!) public class StanActivity extends Activity implements SensorEventListener, LocationListener { ... private LocationManager locationManager = null; static Location lokacja; c. Inicjujemy pierwsze z nich w onResume i zwalniamy w onPause: @Override protected void onResume() { super.onResume(); //Toast.makeText(getApplicationContext(), "Rozpoczynam odczyty czujników", Toast.LENGTH_LONG).show(); //czujniki if(sensorManager==null) { sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); akcelerometr = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); magnetometr = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD); orientacja = sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION); sensorManager.registerListener(this,akcelerometr,SensorManager.SENSOR_DELAY_NORMAL); sensorManager.registerListener(this,magnetometr,SensorManager.SENSOR_DELAY_NORMAL); sensorManager.registerListener(this,orientacja,SensorManager.SENSOR_DELAY_NORMAL); } //lokacja - wymaga dodatkowych uprawnien!!! if(locationManager==null) locationManager=(LocationManager) getSystemService(LOCATION_SERVICE); String dostawca = locationManager.getBestProvider(new Criteria(), true); try { lokacja = locationManager.getLastKnownLocation(dostawca); locationManager.requestLocationUpdates(dostawca, 60000, 1, this); } catch(SecurityException exc) //alternatywnie checkPermissions() { Toast.makeText(getApplicationContext(), "Brak uprawnień do odczytania położenia", Toast.LENGTH_LONG).show(); } } @Override protected void onPause() { super.onPause(); if(batteryReceiver!=null) this.getApplicationContext().unregisterReceiver(batteryReceiver); if(sensorManager!=null) sensorManager.unregisterListener(this); //czujniki if(locationManager!=null) locationManager.removeUpdates(this); //lokacja } d. Definiujemy metody interfejsu, ale tylko jednej używamy: //metody LocationListener public void onLocationChanged(Location location) { StanActivity.lokacja=location; } public void onProviderDisabled(String provider) { // TODO Auto-generated method stub } public void onProviderEnabled(String provider) { // TODO Auto-generated method stub } public void onStatusChanged(String provider, int status, Bundle extras) { // TODO Auto-generated method stub } e. Definiujemy metodę odczytującą zdobyte w onLocationChanged static private UrzadzenieInfo odczytajPolozenie(Activity activity) { double lDlugoscGeograficzna=0; double lSzerokosc=0; double lWysokosc=0; double lSzybkosc=0; double lNamiar=0; long lCzas=0; String lDostawca=""; if(lokacja!=null) { lDlugoscGeograficzna=lokacja.getLongitude(); lSzerokosc=lokacja.getLatitude(); lWysokosc=lokacja.getAltitude(); lSzybkosc=lokacja.getSpeed(); lNamiar=lokacja.getBearing(); lCzas=lokacja.getTime(); lDostawca=lokacja.getProvider(); } UrzadzenieInfo polozenieInfo = new UrzadzenieInfo(); polozenieInfo.typInformacji = TypInformacji.Czujnik; polozenieInfo.nazwa="Położenie"; polozenieInfo.opis = "czas: " + lCzas + "\ndługość geograficzna: " + lDlugoscGeograficzna + "\nszerokość geograficzna: " + lSzerokosc + "\nwysokość: " + lWysokosc; polozenieInfo.opis += "\nnamiar (kierunek): " + lNamiar + "\nszybkość: " + lSzybkosc + "\ndostawca: " + lDostawca; polozenieInfo.polozeniePaska = (lSzybkosc>100)?100:(int)lSzybkosc; return polozenieInfo; } f. Wywołujemy ją w metodzie odswiezListe. [DALEJ NIE ZWERYFIKOWANE W ANDROID STUDIO] 3. W emulatorze nie ma emulacji wyników GPS i innych czujników - można do tego użyć SensorSimulator (u mnie nie zadziałał, testowałem na rzeczywistych urządzeniach) WWW: http://code.google.com/p/openintents/wiki/SensorSimulator The Android emulator doesn't support it itself but OpenIntents' SensorSimulator fills the void. Download and unpack the zip file, then start the standalone jar file: $ java -jar bin/sensorsimulator.jar Next, install SensorSimulatorSettings on the emulator using the adb tool which comes with the SDK: $ adb -s install bin/SensorSimulatorSettings.apk (run adb devices to find the emulator device name). Finally, run the installed SensorSimulatorSettings app in the emulator and enter the IP address 10.0.2.2 (despite what the SensorSimulator application might suggest. This is an alias to the loopback device of the development host so should always be valid.