Apps bouwen met omgevingssensoren

Leer hoe u de Android Environment Sensors kunt gebruiken om informatie over de omgeving van de gebruiker te detecteren, inclusief omgevingstemperatuur, druk, vochtigheid en licht.

Het Android-systeem ondersteunt een reeks apparaatsensors, waarvan sommige zijn geïmplementeerd in hardware en sommige in software. De omgevingssensoren zijn allemaal hardwarefuncties die toegang bieden tot informatie over de omgevingstemperatuur, druk, vochtigheid en licht. Deze sensoren retourneren waarden als volgt: temperatuur wordt gemeten in graden Celsius, atmosferische druk in hPa millibar, relatieve omgevingsluchtvochtigheid als een percentage en omgevingslicht in SI lux-eenheden. In deze zelfstudie bespreken we het basisproces voor het gebruik van deze vier hoofdmilieusensoren. We gebruiken de temperatuursensor van het apparaat niet, omdat deze nu vanaf Android 4.0 is verouderd.

Er zijn veel mogelijke toepassingen voor deze sensoren, zoals barometers en thermometers. Misschien ben je al dergelijke apps tegengekomen in Google Play, maar het is de moeite waard om op te merken dat ze hun functies niet noodzakelijk implementeren met behulp van omgevingssensoren. Weerapps maken bijvoorbeeld vaak gebruik van locatiegegevens die via het web zijn opgehaald om milieu-informatie te bepalen op basis van waar u zich bevindt.

Omdat deze sensoren worden geleverd via de hardware van gebruikers, varieert de ondersteuning tussen apparaten en fabrikanten. Op het moment van schrijven ondersteunen heel weinig Android-smartphones of -tablets alle omgevingssensoren, maar veel van de meer recente modellen ondersteunen een of meer van hen. Het is van vitaal belang om na te gaan of de gebruiker bepaalde sensoren heeft en om functionaliteit te vermijden die er volledig op is aangewezen. De enige uitzondering hierop is als u ervoor zorgt dat alleen gebruikers met de vereiste hardware uw toepassing kunnen downloaden - u kunt dit doen met behulp van de filters voor een app zoals vermeld in de Google Play Store.


Stap 1: Maak een nieuw Android-project

Maak een nieuw Android-project in Eclipse en geef het een naam naar keuze. Laat Eclipse een hoofdactiviteit maken, omdat dit de enige klasse is die we nodig hebben. Voor de code die in deze zelfstudie wordt gebruikt, richten we ons op Android API level 14 (Android 4.0 - Ice Cream Sandwich), maar u kunt een nieuwere versie targeten als u dat wilt. U hoeft het Manifest-bestand niet te wijzigen. Uw hoofdactiviteitsklasse moet de volgende beginstructuur hebben, met de door u gekozen klassenaam:

 public class EnvironmentCheckerActivity breidt Activiteit uit / ** Wordt gebeld wanneer de activiteit voor het eerst wordt gemaakt. * / @Override public void onCreate (Bundle savedInstanceState) super.onCreate (savedInstanceState); setContentView (R.layout.main); 

We gaan een aantal interfaces implementeren, dus verleng uw openingsklasse-declaratie als volgt:

 public class EnvironmentCheckerActivity extends Activity implements OnClickListener, SensorEventListener 

De kliklistener is bedoeld voor gebruikersinteractie en de sensoreventluisteraar dient voor het ontvangen van gegevens van de apparaatsensoren. Eclipse moet importinstructies voor de activiteits- en bundelklassen hebben opgegeven, maar u moet ook het volgende aan de lijst toevoegen:

 importeer android.content.Context; importeer android.hardware.Sensor; importeer android.hardware.SensorEvent; importeer android.hardware.SensorEventListener; importeer android.hardware.SensorManager; import android.view.View; import android.view.View.OnClickListener; importeer android.widget.Button; import android.widget.TextView; import android.widget.Toast;

We zullen later code aan de klas toevoegen.


Stap 2: Ontwerp gebruikersinteractie

Om het basisproces voor het gebruik van de omgevingssensoren te demonstreren, gaan we een eenvoudige gebruikersinterface bouwen. De app geeft een lijst met vier knoppen weer, één voor elk van de sensoren die we gaan gebruiken. Wanneer de gebruiker een knop selecteert, probeert de app de juiste informatie op te halen en deze in een tekstweergave te presenteren. Laten we eerst enkele tekststrings definiëren die we in de interface zullen gebruiken. Open uw "res / values ​​/ strings.xml" bestand en bewerk het om het volgende te bevatten:

  Kies uit de opties om uw omgeving te controleren Environment Checker Omgevingstemperatuur Licht Druk Relatieve vochtigheid - 

Deze vertegenwoordigen de titel, inleidende tekst, knoplabels en een tijdelijke aanduiding voor de tekstweergaven. We gaan een aantal bruikbare bronnen gebruiken voor het ontwerp, maar je kunt ze weglaten als je dat wilt. Als u ze wilt gebruiken, moet u in de mappen met alle layables van uw app twee extra bestanden maken, "back.xml" en "btn.xml" (selecteer elke tekenbare map om en om en kies "Bestand"> "Nieuw"> " Bestand ", voer vervolgens de bestandsnaam in). Voer voor het bestand "back.xml" de volgende code in:

   

Voer het volgende in voor het bestand "btn.xml":

     

De achterkant is te tekenen voor de Activiteit-achtergrond en het "btn" -schema is voor de achtergrond van de knop. U kunt deze ontwerpen op elke gewenste manier wijzigen. Zorg ervoor dat u deze kopieert naar elke mogelijke map in uw app.

Open nu het lay-outbestand 'main.xml' van de app (res / layout / main.xml). Voer een Scroll View en Linear Layout als volgt in:

    

Voeg in de lineaire lay-out de inleiding toe en vervolgens een knop- en tekstweergave voor elk van de vier sensoren:

  

Elk Button en Text View-paar is vrijwel identiek, met ID-attributen om ze in de Java-code te identificeren. U kunt natuurlijk alle ontwerpelementen wijzigen als u dat wilt. De lay-out verwijst naar de trekbare bronnen en strings.


Stap 3: Omgaan met gebruikersinteractie

Open de hoofdactiviteitsklasse van uw app. Voeg de volgende instantievariabelen toe boven aan de klassendeclaratie vóór de methode "onCreate":

 private Button ambientBtn, lightBtn, pressureBtn, humidityBtn; private TextView ambientValue, lightValue, pressureValue, humidityValue;

Deze vertegenwoordigen de knoppen en tekstweergaven die we in de lay-out hebben gemaakt. We gaan een array gebruiken om de tekstweergave-items bij te houden, omdat deze worden bijgewerkt met informatie wanneer de sensoren deze retourneren, dus voeg de volgende array-variabele vervolgens toe:

 private TextView [] valueFields = new TextView [4];

Voeg nu deze constanten toe om te verwijzen naar elk sensortype:

 privé finale int AMBIENT = 0; privé finale int LICHT = 1; privé-finale int PRESSURE = 2; privé-finale int HUMIDITY = 3;

Binnen de "onCreate" -methode, na de regel waarin de inhoudsweergave is ingesteld, haalt u als volgt een verwijzing naar elke knop op met behulp van de ID-kenmerken die we in de lay-out hebben opgenomen:

 ambientBtn = (Button) findViewById (R.id.ambient_btn); lightBtn = (Button) findViewById (R.id.light_btn); pressureBtn = (Button) findViewById (R.id.pressure_btn); humidityBtn = (Button) findViewById (R.id.humidity_btn);

Stel nu elk van deze in om de Activity-klasse te gebruiken als kliklistener:

 ambientBtn.setOnClickListener (deze); lightBtn.setOnClickListener (deze); pressureBtn.setOnClickListener (deze); humidityBtn.setOnClickListener (deze);

Wanneer deze knoppen worden ingedrukt, wordt de Activity "onClick" -methode uitgevoerd. Haal vervolgens de tekstweergave-items op en voeg een referentie toe aan elk in de array die we hebben verklaard, met behulp van de constanten om elke index te specificeren:

 ambientValue = (TextView) findViewById (R.id.ambient_text); valueFields [AMBIENT] = ambientValue; lightValue = (TextView) findViewById (R.id.light_text); valueFields [LIGHT] = lightValue; pressureValue = (TextView) findViewById (R.id.pressure_text); valueFields [PRESSURE] = pressureValue; humidityValue = (TextView) findViewById (R.id.humidity_text); valueFields [HUMIDITY] = humidityValue;

Nu moeten we de "onClick" -methode opgeven en deze aan de klasse toevoegen na de methode "onCreate":

 openbare ongeldig onClick (View v) 

Binnen de methode moeten we bepalen op welke knop is geklikt met behulp van een voorwaardelijke:

 if (v.getId () == R.id.ambient_btn) // omgevingstemperatuur else if (v.getId () == R.id.light_btn) // light else if (v.getId () == R.id.pressure_btn) // pressure else if (v.getId () == R.id.humidity_btn) // humidity

Binnen elk van deze zullen we proberen de relevante omgevingsgegevens op te halen.


Stap 4: Stel de omgevingssensor in

Voeg aan de bovenkant van de klas een aantal variabelen toe voor het proces voor omgevingsdetectie:

 privé SensorManager senseManage; privé Sensor envSense;

Terug in de "onCreate" -methode, voeg na de bestaande code het volgende toe om een ​​instantie van de Sensor Manager-klasse te maken:

 senseManage = (SensorManager) getSystemService (Context.SENSOR_SERVICE);

We hebben de Sensor Manager nodig voor alle omgevingsdetectieprocessen. We gebruiken het om specifieke sensoren op te halen. Probeer in de "onClick" methode "if" -instructie voor de omgevingstemperatuur de omgevingstemperatuursensor als volgt op te halen:

 envSense = senseManage.getDefaultSensor (Sensor.TYPE_AMBIENT_TEMPERATURE);

Nu moeten we zorgen voor gevallen waarin de sensor niet wordt aangeboden door het apparaat van de gebruiker, dus voeg de volgende test toe:

 if (envSense == null) Toast.makeText (this.getApplicationContext (), "Sorry - uw apparaat heeft geen omgevingstemperatuursensor!", Toast.LENGTH_SHORT) .show ();

We voeren gewoon een foutmelding uit. Als de sensor aanwezig is, moeten we ons registreren om de gegevens te ontvangen die het retourneert, dus voeg het volgende toe na deze "als" -instructie:

 else senseManage.registerListener (this, envSense, SensorManager.SENSOR_DELAY_NORMAL);

Voer nu hetzelfde proces uit voor elk van de knoppen in de "onClick" -methode. Voor de lichtknop (in de "als" -instructie binnen "onClick"):

 envSense = senseManage.getDefaultSensor (Sensor.TYPE_LIGHT); if (envSense == null) Toast.makeText (this.getApplicationContext (), "Sorry - uw apparaat heeft geen lichtsensor!", Toast.LENGTH_SHORT) .show (); else senseManage.registerListener (this, envSense, SensorManager.SENSOR_DELAY_NORMAL);

Merk op dat we hier de "TYPE_LIGHT" -sensor vragen en de foutmelding afstemmen op het sensortype. Voor de drukknop:

 envSense = senseManage.getDefaultSensor (Sensor.TYPE_PRESSURE); if (envSense == null) Toast.makeText (this.getApplicationContext (), "Sorry - uw apparaat heeft geen druksensor!", Toast.LENGTH_SHORT) .show (); else senseManage.registerListener (this, envSense, SensorManager.SENSOR_DELAY_NORMAL);

Tot slot, in de "if" -instructie voor de vochtigheidsknop:

 envSense = senseManage.getDefaultSensor (Sensor.TYPE_RELATIVE_HUMIDITY); if (envSense == null) Toast.makeText (this.getApplicationContext (), "Sorry - uw apparaat heeft geen vochtsensor!", Toast.LENGTH_SHORT) .show (); else senseManage.registerListener (this, envSense, SensorManager.SENSOR_DELAY_NORMAL);

Stap 5: Nauwkeurigheidsgegevens ophalen

Naast het retourneren van de gevraagde omgevingsgegevens, geeft de sensor ook nauwkeurigheidsgegevens terug. Voeg de volgende methode toe aan uw klasse, die vereist is bij het implementeren van de sensorevent-luisteraarinterface:

 @Override openbare laatste ongeldigheid opAccuracyChanged (sensor sensor, int nauwkeurigheid) 

Begin binnen de methode met het bouwen van een bericht over de nauwkeurigheid:

 String accuracyMsg = "";

We zullen een switch-instructie gebruiken voor de parameter voor doorgegeven nauwkeurigheidsinteger:

 switch (nauwkeurigheid) case SensorManager.SENSOR_STATUS_ACCURACY_HIGH: accuracyMsg = "Sensor heeft een hoge nauwkeurigheid"; breken; case SensorManager.SENSOR_STATUS_ACCURACY_MEDIUM: accuracyMsg = "Sensor heeft gemiddelde nauwkeurigheid"; breken; case SensorManager.SENSOR_STATUS_ACCURACY_LOW: accuracyMsg = "Sensor heeft een lage nauwkeurigheid"; breken; case SensorManager.SENSOR_STATUS_UNRELIABLE: accuracyMsg = "Sensor heeft een onbetrouwbare nauwkeurigheid"; breken; standaard: pauze; 

We stemmen het bericht af op het nauwkeurigheidsniveau van de sensor, met behulp van de Sensor Manager-klasse. Voer de nauwkeurigheid uit wanneer deze als volgt wordt ontvangen, maar na de instructie switch:

 Toast accuracyToast = Toast.makeText (this.getApplicationContext (), accuracyMsg, Toast.LENGTH_SHORT); accuracyToast.show ();

Binnen de "onAccuracyChanged" -methode kunt u ook het sensortype van de gepasseerde parameter bepalen als dat nodig is.


Stap 6: Sensorgegevens ophalen

Nu kunnen we eindelijk de geretourneerde gegevens van de sensoren ophalen met behulp van een sensorgebeurtenis - dit doen we in de "onSensorChanged" -methode, die ook nodig is om de interface te implementeren:

 @Override openbare laatste ongeldige onSensorChanged (SensorEvent -gebeurtenis) 

De sensorgebeurtenis retourneert zijn gegevens op verschillende manieren, afhankelijk van het sensortype. Voor alle vier de typen die we gebruiken, wordt het op dezelfde manier opgehaald uit het eerste item in een array met drijvende-kommawaarden. Voeg het volgende toe aan de methode:

 float sensorValue = event.values ​​[0];

We gaan nu een tekststring maken met deze gegevens en deze naar de relevante tekstweergave schrijven zodat de gebruiker deze kan zien. Eerst maken we een variabele Tekstweergave en geven deze een standaardwaarde (deze waarde wordt overschreven - we nemen deze op om Eclipse tevreden te houden):

 TextView currValue = ambientValue;

Vervolgens verklaren we de string:

 Draad;

De inhoud van de string hangt af van het type sensor, dus laten we uitvinden welke het is:

 int currType = event.sensor.getType ();

Nu kunnen we een switch-instructie gebruiken voor deze waarde:

 switch (currType) case Sensor.TYPE_AMBIENT_TEMPERATURE: envInfo = sensorValue + "degrees Celsius"; currValue = valueFields [OMGEVINGS-]; breken; case Sensor.TYPE_LIGHT: envInfo = sensorValue + "SI lux-eenheden"; currValue = valueFields [LIGHT]; breken; case Sensor.TYPE_PRESSURE: envInfo = sensorValue + "hPa (millibars)"; currValue = valueFields [PRESSURE]; breken; case Sensor.TYPE_RELATIVE_HUMIDITY: envInfo = sensorValue + "procent vochtigheid"; currValue = valueFields [HUMIDITY]; breken; standaard: pauze; 

In elk geval bouwen we de informatieve string op met behulp van de opgehaalde sensorwaarde en een tekstfragment dat relevant is voor het type. We stellen ook de tekstweergave in op het relevante gebruikersinterface-item met behulp van de array en constanten. Na de instructie switch geeft u de informatie weer:

 currValue.setText (envInfo);

Stel nu de sensorvariabele opnieuw in en stop met luisteren naar updates om onnodig batterijgebruik te voorkomen:

 envSense = null; senseManage.unregisterListener (deze);

Ten slotte willen we niet dat de app onnodige bronnen gebruikt wanneer deze is onderbroken, dus voeg deze methode toe aan de klas:

 @Override beschermde leegte onPause () super.onPause (); senseManage.unregisterListener (deze); 

Stap 7: Probeer het uit

Dat is de complete demonstratie-app! Het heeft geen zin om deze app te gebruiken op de standaard Android-emulator, omdat deze geen omgevingssensoren biedt. U kunt het echter op een daadwerkelijk apparaat uitvoeren of het hulpprogramma Sensor Simulator gebruiken, waarmee u bepaalde aspecten van de omgeving kunt simuleren. Het volgende is een screenshot van de app die actief is op de Samsung Galaxy S III net na het ophalen van de licht- en drukgegevens:

Hier is het voor de andere twee sensoren, die niet worden ondersteund:


Conclusie

De omgevingssensoren zijn een opwindende maar nog steeds ontwikkelende functie van het Android-platform. Het is echter een beetje vroeg om daarop te focussen. Als u met behulp van deze sensoren op meer geavanceerde manieren wilt verkennen, raadpleegt u de sectie Ontwikkelaarshandleiding voor het berekenen van het dauwpunt en de absolute vochtigheid op basis van de relatieve vochtigheid en de omgevingstemperatuur. Anders dan dat - probeer geduldig te zijn!