Naar content
Trending apps
  • Google Meet

  • Google Duo: videogesprekken van hoge kwaliteit

  • Maps: Navigatie en OV

  • WhatsApp Messenger

  • Messenger

Trending games
  • Fortnite

  • Minecraft Earth

  • Dr. Mario World

  • Harry Potter: Wizards Unite

  • Breaking Bad: Criminal Elements

Trending smartphones
  • OPPO Find X2 Pro

  • Nokia 8.3

  • Samsung Galaxy A51

  • Poco F2 Pro

  • Xiaomi Mi Note 10 Pro

Nieuwste tablets
  • Samsung Galaxy Tab S6

  • Samsung Galaxy Tab A 10.5

  • Samsung Galaxy Tab S4

  • Samsung Galaxy Tab S3 9.7

  • Asus Zenpad 3S 10

DevTutorial 5 - Internetverbinding en de AsyncTask

· 28 september 2011

 

DevTutorial aflevering vijf. Langzamerhand begin je door te krijgen hoe Android werkt. Inmiddels heb je geleerd hoe je layouts maakt, hoe Eclipse werkt en hoe je daarmee kan debuggen. Ook heb je geleerd welke belangrijke blocks je kan gebruiken tijdens het programmeren zoals het if block, het for block en het try - en het catch block. Het is tijd om je programmeerkunsten te verbinden met het internet. Wanneer je je apps verbindt met diensten in de cloud kan je pas écht nuttige apps maken. Deze DevTutorial maakt een begin met het gebruiken van de internetverbinding. De DevTutorials die hierna komen bouwen daar op voort.

Wat gaan we doen

In deze DevTutorial gaan we een app maken die de gegevens van een Twittergebruiker downloadt en toont in een TextView: . Hierbij worden de volgende onderwerpen behandeld:

  • Hoe je effen kleuren kan gebruiken in Views.
  • Hoe je methods niet alleen in je eigen class kan schrijven om ze aan te roepen, maar ook je methods op andere Objects zoals een String kan aanroepen van buitenaf.
  • Hoe je met een ProgressDialog de gebruiker kan laten wachten en hem een tegelijkertijd een boodschap kan tonen.
  • Hoe je een internetverbinding kan instellen voor standaardgebruik in je apps.
  • Hoe je een internetpermissie kan toevoegen aan je app.
  • Hoe je twee belangrijke methods uit de AsyncTask class kan gebruiken zodat je gegevens vanaf het  internet kan downloaden.
  • Wat voor soorten statusantwoorden (aangegeven met nummers) je kan krijgen als je een internetverbinding gebruikt.
Als afsluiting van deze DevTutorial is er een extra oefening waarbij je meer leert over het opbouwen van een mooie layout door middel van enkel xml-bestanden. Herbij leer je over colors (kleuren), styles (stijlen) en de layer-list. Door op deze manier je layout op te bouwen hou je je layout overzichtelijk én schaalbaar.
Hier kan je hulp vragen op het forum als je ergens niet uitkomt.
Veel succes weer gewenst!

De app ontwerpen en de basis programmeren

Omdat je nu steeds meer weet van Androidprogrammeren, worden de basiselementen die je nodig hebt voor deze DevTutorial in sneltreinvaart behandeld: in dit geval is dat het koppelen van de Layout en Views aan de code in je class inclusief de method voor het indrukken van een Button. Mocht het toch zo zijn dat iets je onduidelijk is dan kan je het beste de de vorige DevTutorials deels opnieuw lezen, afhankelijk van wat er onduidelijk voor je is.

  • Maak een nieuw Androidproject aan met deze en deze instellingen.
  • Ga naar de layout main.xml en open hem in de Source Code Editor Tab (open main.xml en klik onderin het scherm van main.xml op de tab main.xml).
  • Verwijder alle tekst uit main.xml: .
  • Schakel terug naar de Layout Editor Tab (klik onderin op het scherm van main.xml op Graphical Layout). En sleep uit linkerlijstje van main.xml uit het mapje Layouts een RelativeLayout op het lege scherm (of op de lege outline) en laat hem daar los: .
  • (De volgende zin en de zin hieronder moet je even goed opletten dat je de Views naar het Outline Window sleept en niet naar het zwarte preview scherm). Sleep nu de volgende Views naar het Outline Window en laat ze los op de RelativeLayout die in het Outline Window staat: Button, EditText en een ScrollView. Hierdoor komen de Button, de EditText en ScrollView netjes onder elkaar in het Outline Window.
  • Je ziet dat toen je een ScrollView plaatste in de RelativeLayout er automatisch een LinearLayout werd aangemaakt in die ScrollView, deze LinearLayout moet je verwijderen (want je gaat maar 1 View in de ScrollView plaatsen, anders had je inderdaad wél een ViewGroup nodig). Sleep nu een TextView op de ScrollView in het Outline Window, hierdoor komt de TextView in de ScrollView.
  • Pas van de Views die je in de layout hebt gesleept de volgende properties aan:
ElementPropertyWaarde
RelativeLayoutPadding10dip
ButtonId@+id/btnDownload
ButtonTextDownload
ButtonClickabletrue
ButtonOn clickdownloadUserInfo
ButtonLayout align parent toptrue
ButtonLayout align parent lefttrue
EditTextId@+id/etxtUsername
EditTextLayout align parent toptrue
EditTextLayout to right of@+id/btnDownload
EditTextLayout widthfill_parent
EditTextText 
EditTextHinttwitter username?
EditTextInput typetext
ScrollViewLayout below@+id/btnDownload
ScrollViewLayout heightfill_parent
ScrollViewLayout widthfill_parent
TextViewId@+id/txtvUserInfo
TextViewTextNog geen gebruikersgegevens bekend
  • Maak de volgende variabelen aan in je class MainActivity:

  • Maak de nodige imports.
  • Vul de variabelen daarna in de method onCreate met de method findViewById zoals in de vorige DevTutorials is beschreven.
  • Maak de method downloadUserInfo aan in je class in MainActivity:

  • Maak de nodige imports.
  • In de method downloadUserInfo, maak een if block aan die controleert of de ingedrukte knop wel de knop mBtnDownloadUserInfo is.

Je class moet er nu als volgt uit zien:

Kleuren in android: de TextView aanpassen

Kleuren in Android bestaan uit drie getallen, opgeschreven in de hexadecimale notatie waar elk getal uit twee cijfers bestaat, namelijk 0 t/m F. Dit kan je het beste begrijpen als 0 t/m 15, maar om te zorgen dat je geen twee tekens nodig hebt voor de getallen 10 t/m 15 worden in plaats daarvan A, B, C, D, E en F gebruikt. Deze drie getallen vormen samen een kleurnummer (of kleurcode), vandaar dat je het hekje # ervoor moet zetten. Een voorbeeld van zo een kleurnummer is #FF0000. Wanneer je deze kleur invult bij bijvoorbeeld de Color property van een TextView zet je de kleur van de tekst op rood. Eigenlijk voer je dan drie getallen in: FF,00 en 00. Dit zijn hexadecimale getallen en als je ze normaal zou schrijven zou je 255, 0 en 0 krijgen. Het eerste getal staat voor de roodwaarde van de kleur, doordat die op de maximale waarde FF(dus 255) is gezet is de kleur rood maximaal aanwezig. De twee getallen die daar volgen staan voor de groenwaarde en blauwwaarde van de kleur. Omdat de groenwaarde en de blauwwaarde op 0 zijn gezet, zijn die kleuren niet aanwezig. Als resultaat zou je met zo'n kleurnummer dan een puur rode kleur krijgen. Je kan proberen om als de app af is andere waarden te gebruiken voor de tekstkleur: #00FF00 voor Groen en bijvoorbeeld #0000FF voor blauw of  #FFFF66 voor geel. Je kan de kleuren ook op andere properties van Views invullen zoals bij de Background property of Text shadow property. In plaats van drie getallen kan je aan het begin van je kleurnummer nog een extra getal plaatsen: hiermee kan je de kleur transparant maken (zodat de kleuren die achter de view zitten deels doorschijnen). Hier moet je ook een hexadecimaal getal voor gebruiken: 00 staat voor compleet transparant (dus onzichtbaar) en FF staat voor compleet zichtbaar. 40 staat voor voor 25% zichtbaar, 80 staat voor voor 50% zichtbaar en C0 staat voor 75% zichtbaar. Wanneer je dan een rode kleur wil hebben die voor 75% zichtbaar is, moet je dus dit kleurnummer gebruiken: #C0FF0000. Wanneer je een roodkleur wil hebben die 100% zichtbaar is kan je #FFFF0000 gebruiken, maar dan kan je dus ook net zo goed #FF0000 gebruiken (want standaard is een kleurnummer van 3 getallen 100% zichtbaar). Vooral bij het einde van deze DevTutorial bij de extra oefening worden kleurcodes met transparantie veel gebruikt, let er dan alsjeblieft even op zodat je je bewust bent van wat je dan aan het doen bent.

  • Pas van de Views in de layout de volgende properties aan:
ElementPropertyWaarde
TextViewColor#FFFFFF
TextViewBackground#FF0066

Je layout main.xml moet er nu als volgt uit zien: .

De kleurstelling is nog niet optimaal op z'n zachtst gezet. Het ging er meer om dat je weet hoe je kleuren kan gebruiken in de layout. In één van de volgende DevTutorials die over opmaak gaat, leer je meer over kleurgebruik en styles.

De app programmeren

Voordat gegevens gedownload kunnen worden, moet de gebruikersnaam gecontroleerd worden, moet er een laad-schermpje getoond worden, moet er een internetverbinding Object worden klaargemaakt en moet je aangeven in het configuratie bestand van je app (AndroidManifest.xml) dat je de internetverbinding van het Androidtoestel wil kunnen gebruiken. Dat gaan we eerst doen. Als dat is klaargezet kan er worden begonnen met het programmeren van het downloaden van de gegevens van een Twittergebruiker. Omdat dat ietsje ingewikkelder is, is de tekst die daarbij hoort geplaatst in een apart onderdeel van deze DevTutorial. Dat onderdeel komt na dit onderdeel.

Methods aanroepen op een object: ingevoerde Twitter-gebruikersnaam controleren

Net zoals MainActivity methods heeft die je aan kan roepen zijn er veel andere zogenaamde Objects in Android waarvan je methods kan gebruiken. Een voorbeeld hiervan is het String Object waar je onder andere methods op kan aanroepen die je vertellen wat de lengte van het woord of de zin is die in de String zit of welk karakter er staat op op een bepaalde plek in de String. Vooral deze eerste kunnen we nu goed gebruiken: voordat gegevens van een twittergebruiker gedownload kunnen worden moet er überhaupt wel een Twittergebruiker ingevuld zijn. Of met andere woorden: de lengte van de String die je haalt uit etxtvUserName moet langer zijn dan nul. Om dit te controleren moet je eerst de tekst opvragen uit de EditText die we gebruiken onder de naam mExtUsername. Deze tekst wordt in een String gestopt:Vervolgens controleren we op de String username of de lengte daarvan groter is dan nul, je vraagt dan dus eigenlijk: ”staan er meer dan 0 karakters in deze String die ik heb gevuld vanuit mExtUsername?”. Nu ga je iets nieuws leren dat belangrijk is: een String is net zoals een Activity een object waar je methods op kan aanroepen. Denk anders nog even terug aan de vorige DevTutorial waar je in het begin van je class Activity de volgende zin gebruikte:Vervolgens werd in die DevTutorial uitgelegd dat je met de class MainActivity een kopie maakt van de class Activity en daarmee alle methods kan gebruiken die al aanwezig zijn in Activity. Op die manier gebruik je bijvoorbeeld nu in bijna elke DevTutorial de method findViewByID. En die method findViewByID kan je alleen maar gebruiken omdat je aan het begin van al je classes hebt beschreven dat je door wilt bouwen op de method Activity (dat doe je met het woordje extends): want in de class Activity zijn al een heleboel methods aanwezig zoals je hier kan zien. Nu weer even terug naar een String: wanneer je een String gebruikt in je code dan kan je daar methods op aanroepen die aanwezig zijn in de String. Het verschil tussen hoe je String gebruikt en hoe je Activity gebruikt is dat je een Activity van binnenuit gebruikt terwijl je een String van buitenaf gebruikt. Met Activity bouw je voort op de bestaande class en is het alsof je verder bouwt aan de class Activity (door middel van extends). Maar met een String bouw je er niet op verder, je gebruikt hem alleen maar. Een String aanmaken om hem daarna te kunnen gebruiken doe je steeds met:Zoals je weet heb je dit al meerdere keren gedaan. Maar naast het feit dat je er karakters, woorden of lappen van tekst in kan stoppen kan je er ook methods op aanroepen waarmee je eigenlijk vragen stelt aan de String die je op dat moment gebruikt. Al de vragen die je aan een String kan stellen kan je op deze pagina vinden: java.lang.String. De vragen die je van buitenaf kan stellen staan onder het kopje public methods (methods die je alleen vanuit binnen kan aanroepen zijn protected methods, die zie je bijvoorbeeld bij de Activity class staan). Je ziet bijvoorbeeld staan charAt(int index) waarmee je kan vragen wat voor karakter er op een bepaalde plek in de String staat (en als extra bericht geef je dan mee van welke plek in de String je het wilt weten – dat is de int index die daarachter tussen haakjes staat). Op dezelfde manier staat er ergens length() en daarmee kan je vragen: wat de lengte is van de String? Ik ga het je nog ietsje verder uitleggen, maar als je dat aardig begrijpt dan ben je al best ver met Android, dus probeer nog even goed op te letten. Ergens in Android is door de makers van Android beschreven wat een String is. Toen ze beschreven wat een String is, hebben ze dezelfde woorden en syntax gebruikt die jij nu gebruikt om te coden. De makers van Android hebben toen een class gemaakt die ze String hebben genoemd (en hebben die geplaatst in de package java.lang). Om je een idee te geven zie je hieronder een klein deel van deze class staan:Wanneer je dan in je code schrijft:dan kijkt Android naar bovenstaande class (de beschrijving van de complete versie van die class vind je dus hier) en stopt een lege versie daarvan in username (in programmeertaal heet die lege versie null). Als je hem vervolgens vult met een tekst dan is die tekst opgeslagen in username, en daarna kan je ook de methods aanroepen die in de class staan. Bij bijvoorbeeld length() staat aan het eind van de method return count;. Dat betekent dat een berichtje terug wordt gegeven aan het stukje code dat de method length() opvraagt. In dit geval is de count een int, dat is dus een getal zonder cijfers achter de komma. Op dezelfde manier kan je ook de andere vragen stellen aan een String door de methods te gebruiken die bij String horen. Ik raad je aan om even naar de methods te kijken op de link die ik je net gaf: kijk bijvoorbeeld eens naar endsWith(String suffix) en indexOf(String string) en probeer te begrijpen wat ze doen. Nu kan je door middel van een if code block kijken of er een username is ingevuld en een foutmelding geven als dat niet zo is.

  • Voeg onderstaande code in in het if code block dat controleert of de juiste knop was ingedrukt in de method downloadUserInfo:

ProgressDialog: Bezig met het ophalen van gegevens...

Een ProgressDialog is een zwart rechthoekig schermpje met meestal een laad-boodschap (bijvoorbeeld "gegevens worden gedownload...") die ervoor zorgt dat je gebruiker de app tijdelijk niet kan besturen. Deze ProgressDialog gebruik je wanneer je de gebruiker gedwongen wil laten wachten op een taak die op de achtergrond wordt uitgevoerd. Vaak is dat wanneer je gegevens aan het downloaden bent van het internet: dat is ook met onze app het geval wanneer we Twitter-gebruikersgegevens willen downloaden vanaf twitter.com. Voordat je een ProgressDialog kan gebruiken moet je hem een naam geven: je moet hem zo als dat heet 'definiëren'. Dit moet je doen in het code block van je class. Als je dit namelijk doet in het code block van je method dan is hij voor Android niet zichtbaar in andere methods (dat is de scope van deze variabele). Dit terwijl je in een andere method je later opdracht moet geven om de ProgressDialog te laten verdwijnen.

  • Ga dus op zoek naar de plek waar je de TextView, de EditText en de Button definieërt en definiëer daar ook de ProgressDialog:

Vergeet niet de import te doen. Blijf met je muis hangen op het woordje ProgressDialog en klik op import ‘ProgressDialog’ (android.app). Nu kan je de lege ProgressDialog die je mProgressDialog genoemd hebt vullen met een nieuwe ProgressDialog en vervolgens de titel instellen en vervolgens hem tonen.

  • Voeg de volgende code toe aan het if code block:

Je weet nu wel hoe je een ProgressDialog een tekst mee moet geven met setMessage en hem tonen met show, maar je weet nog niet hoe je hem moet laten verdwijnen. Verderop in deze DevTutorial wordt je uitgelegd dat je dat met hide method kan doen.

DefaultHttpClient (i.c.m. HttpGet & HttpResponse): de internetverbinding gereed maken

Met een Activity kan je controleren wat er op het scherm gebeurt door slim gebruik te maken van onder andere de methods onCreate, setContentView en findViewById. Met een String kan je letters opslaan en door middel van methods er vragen over stellen en opdrachten op uitvoeren (door onder andere de methods  length, indexOf en replace te gebruiken). Op dezelfde manier heb je de DefaultHttpClient waar je door middel van de method execute gegevens kan downloaden. Je kan de DefaultHttpClient het beste begrijpen als een soort tunnel naar het internet waar je een internet adres-aanvraag in kan stoppen en je een antwoord uit terug krijgt. De DefaultHttpClient kan nog veel meer dan alleen een internetpagina downloaden, daarom moet je best veel instellingen doen voordat je hem eenmaal kan gebruiken. Maar omdat we het nu alleen over het downloaden van een internet pagina hebben, gaan we het niet over de andere details hebben.

  • Kopieer deze code in je het code block van je class MainActivity:

(En vergeet niet om de imports te doen) Wat er precies gebeurt is nu nog te ingewikkeld om uit te leggen. Maar het belangrijke hiervan is dat er een DefaultHttpClient gemaakt wordt op de een-na laatste regel van het code block van deze method: DefaultHttpClient httpClient = ….. De regel daarna wordt deze DefaultHttpClient (die we httpclient genoemd hebben) terug gegeven als antwoord van deze method: return httpclient. Wanneer je nu in je class de method createHttpClient aanroept krijg je dus een DefaultHttpClient (een tunnel naar het internet) terug waar je aanvragen in kan stoppen en anwoorden uit kan krijgen. Een aanvraag heet een HttpGet en die kan je zo maken:Vervolgens kan je die gebruiken in de method execute van de DefaultHttpClient en als resultaat krijg je daar een HttpResponse van terug:Straks gaan we dit gebruiken in je class.

android.permission.INTERNET: toestemming hebben tot de internetverbinding

Om een internetverbinding (en andere speciale functies zoals gps, telefoonboek en vibratiefunctie) te kunnen gebruiken moet je dit aangeven in het bestand AndroidManifest.xml. Daarna pas stelt Android de internetverbinding aan jou beschikbaar. De reden hiervoor is dat bij het installeren van een app naar AndroidManifest.xml wordt gekeken om te kijken welke speciale toestemmingen (permissies) nodig zijn voor het uitvoeren van de app. De gebruiker moet hiervoor toestemming geven in het machtigingen-scherm als hij/zij de app installeert (dit heb je als Androidgebruiker waarschijnlijk al meerdere keren gedaan).

Voeg toestemming voor de internetverbinding toe in AndroidManifest.xml door de volgende stappen te volgen:

  • Ga naar het bestand AndroidManifest.xml en klik op het Permission editor perspective: .
  • Klik op de knop Add... en selecteer Uses Permission en klik op Ok: .
  • Er is een nieuwe Permission toegevoegd. Selecteer nu in de rechterhelft van je editor scherm android.permission.INTERNET: .
  • (En sla je bestand AndroidManifest.xml op en sluit het bestand)

AsyncTask class

Om de volgende alinea voldoende te kunnen begrijpen moet je de volgende concepten je nog goed kunnen herinneren: subclass, overriden en extends. Weet je dat niet meer, lees dan eerst nog even de paragraaf "public class MainActivity extends Activity" uit DevTutorial 3.

Voor het downloaden van de gegevens van een Twittergebruiker moet je een speciale inner class (een class die je aanmaakt in het block van je hoofd-class) gebruiken die je subclasst op basis van de AsyncTask class, dat is een erg belangrijke class in Android. De AsyncTask class is een beetje ingewikkeld dus hij wordt in drie afzonderlijke paragrafen behandeld. De zin die nu komt wist je al: met je class MainActivity subclass je eigenlijk de class Activity en daardoor heb je onder andere de methods onCreateonPause of onDestroy die je kan overriden zodat je code kan schrijven specifiek voor die situaties (als de app wordt opgestart, gepauzeerd en afgesloten). Dit is ook van toepassing op de AsyncTask class: op dezelfde manier heeft de class AsyncTask de twee belangrijke methods doInBackground en onPostExecute die respectievelijk worden aangeroepen voor het uitvoeren van zwaar werk op de achtergrond én wanneer het uitvoeren van het zware werk voltooid is. Wanneer je deze methods overridet kan je code schrijven specifiek voor deze twee situaties: het uitvoeren van het zware werk op de achtergrond en wanneer het uitvoeren van het zware werk voltooid is. Wanneer dat is uitgelegd en je de inner class hebt aangemaakt wordt het uitvoeren van het zware werk geprogrammeerd: het downloaden van de gegevens van de Twittergebruiker. Daarna wordt de method ingevuld die wordt uitgevoerd wanneer het downloaden voltooid is, deze controleert op fouten en laat indien mogelijk de resultaten zien in de TextView.

Twee methods om een internetverbinding uit te voeren

Wanneer je via een internetverbinding iets wilt downloaden of uploaden kan je hier het beste de AsyncTask class voor gebruiken als hulpmiddel. Met de AsyncTask class kan je je code splitsen in een gedeelte dat op de achtergrond moet gebeuren en een gedeelte dat op de voorgrond moet gebeuren nadat het eerste gedeelte is uitgevoerd. Wanneer je alle code op de normale manier achter elkaar zou uitvoeren zou je app een tijdje onbestuurbaar zijn. Duurt dit onbestuurbaar zijn zelfs langer dan een paar seconden, dan denkt Android (omdat je app (tijdelijk) bevroren is) dat je app is gecrashd en probeert deze vervolgens te sluiten door middel van een vraag aan de gebruiker (“het proces X reageert niet meer, wilt u deze afsluiten?”). Naast het gebruik van de AsyncTask zijn bij het gebruiken van een internetverbinding de volgende drie punten belangrijk om rekening mee te houden: (1) het kan lang duren voordat je een reactie krijgt van de server waarmee je communiceert, (2) je weet niet zeker of je überhaupt wel verbinding hebt (3) en je weet niet zeker of je wel de juiste gegevens van de server krijgt. Het eerste punt kan je oplossen door de AsyncTask class te gebruiken. Deze class kan je maken in het code block van je eigen class. Voor nu is het handig om te weten dat je de class moet beschrijven door daar twee methods in te maken. Voeg onderstaande code toe onderin het block van de class MainActivity in MainActivity.java:Wanneer je deze class maakt in de class die hem gebruikt, wordt je op twee manieren geholpen: de code die je in de method doInbackground schrijft, wordt in de achtergrond uitgevoerd en de code die je schrijft in de method onPostExecute wordt uitgevoerd wanneer de code van de method doInBackground afgelopen is. Wanneer je bijvoorbeeld Twittergegevens downloadt, zou je het downloaden van deze gegevens kunnen doen in de method doInBackground. Het vervolgens tonen van de gegevens (of een foutmelding als het anders gaat dan je dacht!) doe je in de method onPostExecute. De methods worden automatisch na elkaar opgestart, het enige dat je moet doen is AsyncTask zelf opstarten. Dat doe je met:

  • Voeg bovenstaande regel toe in het einde van het tweede if code block van je method downloadUserInfo zodat de methods gestart worden van de de AsyncTask class die je hebt gesubclasst in de class DownloadUserInfoTask:

Nu wordt de AsyncTask opgestart wanneer je op de mBtnDownload drukt én er een gebruikersnaam is ingevuld. Wat er precies moet gebeuren in de DownloadUserInfoTask class, bepalen we in de volgende paragraaf.

Internetverbinding uitvoeren

Je hebt nu net een private class beschreven in je class MainActivity. Om deze class verder te gebruiken moet je een paar class variables toevoegen, net zoals je bijvoorbeeld steeds Buttons en TextViews definiëerde in de vorige DevTutorials.

  • Maak een String, een int en een Exception aan in het code block van de private class die je net gemaakt hebt:

Nu gaan we de method doInBackground(Void … args) invullen: het internetadres waarvandaan gegevens gedownload moeten worden en het opstarten van downloadverbinding. Bij het opvragen van Twittergegevens moet je een url aanspreken waarin de username zit verwerkt. Dus je moet de username die is ingevuld in de EditText pakken en in een String stoppen. Daarna moet je special characters die in de string zitten encoderen zodat je ze kan gebruiken in je url. Het encoderen is het herschrijven van special characters naar een bepaalde standaardnotatie zodat je ze kan gebruiken in je url. Een spatie wordt bijvoorbeeld veranderd in %20 en een komma wordt bijvoorbeeld veranderd in %2C. Dit moet je altijd doen als je tekst gaat plaatsen in een url.

  • Voeg daarom onderstaande toe in de method doInBackground(Void … args):

Nu heb je de String encodedUsername waarin je username zit die is ingevuld met inhoud van de EditText mEtxtUsername, geëncodeerd naar de vereisten om hem te gebruiken in een url. Nu kan je de url opbouwen die je gebruikt om de gegevens te downloaden. De url die je hiervoor moet gebruiken is http://api.twitter.com/1/users/show.json?screen_name en daarachter de gebruikersnaam, zoals je hier kan lezen. Dit leidt ertoe dat we de complete url op de volgende manier kunnen maken,

  • voeg deze toe aan je method:

Je kan deze trouwens ook testen in je browser door bijvoorbeeld als username androidworld te gebruiken. In dat geval ga je in je browser naar bijvoorbeeld http://api.twitter.com/1/users/show.json?screen_name=androidworld (er hoeft niks geëncodeerd te worden omdat er geen speciale karakters in zitten). Vervolgens wordt de String fetchUrl gebruikt om de data op te vragen. Om de verbinding in te stellen wordt de method createHttpClient() gebruikt. Wanneer je deze aanroept, krijg je een DefaultHttpClient terug die je nodig hebt om de verbinding op te starten. Het tweede onderdeel dat je nodig hebt is een opdracht voor de verbinding die je uit kan voeren. In programmeertermen noem je dit een HTTP GET en in Android gebruik je daarvoor een object van het type HttpGet. Deze opdracht kan je aanmaken door een opdracht uit te voeren.

  • Voeg deze toe aan je method:

De DefaultHttpClient (die je gebruikt onder de naam httpclient) en de Httpget (die je gebruikt onder de naam httpget) kan je nu samen gebruiken om de gebruikersgegevens te downloaden. Dit doe je door van de DefaultHttpClient de method execute te gebruiken en als bericht de httpget mee te geven. Als resultaat van het aanroepen krijg je een object terug dat van het type HttpResponse is, deze noemen we response. In normaal simpel Nederlands gezegd, krijg je dus een antwoord terug wanneer je de url aanroept en in Android wordt het Object HttpResponse gebruikt om dat antwoord op te slaan (want dat “antwoord” heeft speciale eigenschappen die je nodig hebt om verder te kunnen programmeren zoals je zo zult zien):

  • Voeg dit doe aan je method:

De opdracht hierboven, dat is de opdracht die lang kan duren (daarom plaats je deze in een aparte method in een speciale inner class die ervoor zorgt dat je achtergrond taken uit kan voeren). Na deze regel wil je weten wat het resultaat is van de opdracht. Die kan je vragen door de method getStatusLine() aan te roepen op het HttpResponse object dat je gebruikt onder de naam response. Het resultaat van die vraag naar die method is een StatusLine Object die je statusLine noemt (het verschil tussen de namen zit ‘m in de hoofdletter S). En dat object heeft een method getStatusCode() die een int (dus een getal zonder cijfers achter de komma) teruggeeeft (alle methods van een StatusLine object kan je hier vinden, zoek even de method getStatusCode() op in die pagina om een idee te krijgen). Op basis van dat getal kan je bepalen of de download succesvol was of niet. Wij gebruiken in onze code alleen de getallen 200 en 404, maar er zijn er nog veel meer zoals je hier kan zien <– kijk daar even naar, en merk op dat het eerste getal van de response code (een 1,2,3,4 of 5) aangeeft wat voor soort response het is.  (Oh, en kijk ook even naar code 418 ;) ).

  • Voeg dit toe aan je method:

Voor ons is het belangrijk te weten of de download succesvol was en dat is wanneer de statuscode het getal 200 is. Dat controleren we met een if code block waarna vervolgens het resultaat (de platte tekst) wordt uitgelezen in de String mResultString.

  • Dat uitlezen gebeurt als volgt (voeg dit toe aan je method):

In het uitvoeren van bovenstaande code kunnen fouten optreden, de Twitterserver kan bijvoorbeeld uitstaan (en dat gebeurt bij Twitter regelmatig) of de verbinding vanaf je telefoon kan eruit liggen. Het enige dat je moet doen met de code die ik net met je doorliep, is het inpakken in een try catch code block.

  • Voeg het try catch code block toe zodat je method er als volgt uit komt te zien:

Zoals je ziet zijn er twee catch-blokken die verschillende soorten fouten opvangen. Zoals je misschien nog weet van de vorige DevTutorials, worden de catch code blocks alleen aangeroepen als er een fout ontstaat tijdens het uitvoeren van de code in het try code block. In het uitzonderlijke geval van zo'n fout, wordt gekeken welke fout het meest lijkt op de soorten fouten die in de catch code blocks zijn beschreven. Het code block met de eerste de beste match wordt aangeroepen en vervolgens wordt de fout in de variabele gestopt. Vervolgens wordt die fout geplaatst in de variabele mConnectionException (als er geen match is gevonden crasht de app).

Resultaat van de internetverbinding verwerken

We hebben de DownloadUserInfoTask zo ingericht dat het resultaat van het zware werk van de method doInBackground wordt opgeslagen in drie variabelen: (1) de statuscode van de internetverbinding is opgeslagen in mStatusCode, (2) als de aanvraag succesvol was, wordt de gedownloade tekst opgeslagen in de String mResultString en (3) als er een fout was opgetreden, wordt die opgeslagen in mConnectionException. Nu kunnen we deze gegevens gebruiken in de method onPostExecute. Deze methode wordt aangeroepen als het zware werk gedaan is, dus je kan sowieso de ProgressDialog laten verdwijnen:Het enige dat er nu nog verder moet gebeuren is: (1) controleren of statuscode gelijk is aan 200 en dan mTxtvUserInfo vullen met de mResultString, of anders (2) controleren of de statuscode gelijk is aan 404 en een melding geven dat de gebruiker niet bestaat, of (3) gewoon de statuscode weergeven of (4) de gebruiker informeren als er een fout was opgetreden tijdens de verbinding. Dit kan je doen met een if code block gevolgd door twee else if code blocks en daarna één else code block. Probeer dit zelf eerst te maken: door de method setText te gebruiken op mTxtvUserInfo en als parameter mResultString mee te geven kan je de tekst veranderen. En door te controleren of de statusCode groter is dan 0 kan je controleren of de statuscode veranderd is. Is dit niet het geval, dan was er een fout opgetreden en kan je dat in een Toast weergeven. Probeer dit alsjeblieft zelf eerst even, ga dus met je gedachten van de automatische piloot af als je daar op stond en kijk of je dit aan elkaar kan maken. Er is een aardige kans dat het je lukt met de kennis die je tot nu toe hebt opgedaan. Geprobeerd? Je method onPostExecute zou er als volgt uit kunnen zien:Probeer niet meteen alles over te nemen van hierboven. Probeer eerst te kijken of je met je eigen code de app uit kan voeren. Als er crashes komen, probeer dan te kijken in de logcat bij het Debugger perspectief en probeer te begrijpen wat er gebeurt. Weet je niet wat je fout doet, neem dan stukje bij beetje de code van hierboven over in je method onPostExecute. Nu kan je je app opstarten in de emulator. Let er op dat wanneer je de gebruikersgegevens wilt downloaden bovenin in het Androidscherm van je emulator het interneticoon aangeeft dat je verbinding hebt. Heb je geen internetverbinding in je emulator, dan zie je waarschijnlijk als je de app uitvoert deze foutmelding: . Dit komt dus doordat je rechtsbovenin het icoontje ziet staan dat aangeeft dat je geen internetverbinding hebt. Heb je geen internetverbinding, sluit dan de emulator af door op het kruisje of het rode bolletje te klikken en druk opnieuw op run zodat de emulator opnieuw wordt opgestart. Vaak helpt dit om je internetverbinding in de emulator te activeren. Wanneer je de app werkend heb, kan je bijvoorbeeld dit als resultaat krijgen (afhankelijk van welke gebruikersnaam je invoerde): . Je ziet dat de gegevens niet netjes getoond worden: er staan komma's, dubbele punten en andere leestekens doorheen. In de volgende DevTutorial gaan we een eigen class TwitterUser maken in een nieuw bestand TwitterUser.java. Daarin maken we onze methods getUsername en andere methods. Die methods gaan we gebruiken om de juiste gegevens op te kunnen vragen zodat we die in een mooie layout kunnen tonen.

Object(s): de belangrijkste bouwstenen van Android

Een belangrijk onderwerp in deze DevTutorial is het begrip Object. Wanneer je ook maar ergens in Android methods aanroept of laat gebruiken, horen die altijd bij een Object. Bij je MainActivity in deze DevTutorial worden bijvoorbeeld de methods downloadUserInfo en createHttpClient gebruikt. Op dezelfde manier gebruikte je in deze DevTutorial het Object DefaultHttpClient waarop je de method execute uitvoert en gebruikte je de method length op het Object String. Objects (dat is het engelse meervoud voor het engelse woord object) horen bijde belangrijkste bouwstenen in Android. Een String is een Object, een View is een Object, een Exception is een Object, een TextView is een Object, een HttpGet is een Object, een layout - of shape xml-bestand is uiteindelijk ook een Object in je code  en ga zo maar door. Je zult wel denken: wat heb ik er nou aan dat ik weet dat dit allemaal Objects zijn? Het belangrijke van een Object is dat hij methods bevat die je kan gebruiken wanneer je in Android programmeert. Dit is namelijk hoe Android is opgebouwd: een groot netwerk van Objects die met elkaar communiceren via methods. Zo heb je bijvoorbeeld het ActivityManager Object en die wordt aangeroepen door Android als de gebruiker aan heeft gegeven dat hij een app wil starten. De ActivityManager roept dan op een gegeven moment de method onCreate aan in je Activity zodat hij de controle geeft aan de programmeur die die method heeft geschreven (jij dus in dit geval). Het idee van Androidexpert zijn, is dat je precies weet welke Objects zweven op welke plek in Android en hoe ze met elkaar via welke methods communiceren. Als je dat weet, weet je precies wat er waar gebeurt op welk moment in het Androidsysteem. Ook weet je dan welke soorten functionaliteit op wat voor moment worden aangeroepen zodat je daar op in kan spelen met je eigen code en zo een crash-vrije en nuttige app kan maken. Vraag je af wat ik bedoelde met de laatste twee zinnen? Een simpel voorbeeld is het opvragen van GPS-coördinaten. Wanneer je in de toekomst meer kennis hebt van Android weet je dat je daarvoor de method getSystemService voor moet gebruiken in je Activity en dat je als resultaat van de method aanvraag een LocationManager object terug krijgt. Ook weet je dan dat je op het Object LocationManager de method requestLocationUpdates moet aanroepen om de GPS-coördinaten door te krijgen. Nu is het in werkelijkheid nog ietsje ingewikkelder, maar het idee blijft hetzelfde: des te meer je van Android weet, des te meer je weet van verschillende stukken functionaliteit hoe je ze moet gebruiken, welke Objects je daarvoor nodig hebt en welke methods je nodig hebt om die Objects met elkaar te kunnen laten praten. Wat is dan het verschil tussen een Object en een class? Een class is het ontwerp, de blauwdruk van het object. Of anders gezegd: een class is een bouwtekening: op basis van een class kan je een Object aanmaken in je code. Wanneer je dus bijvoorbeeld een DefaultHttpClient aanmaakt (zoals je deed in deze DevTutorial) dan schrijf je eigenlijk: ik wil een nieuw Object op basis van de DefaultHttpClient class. Het Object dat je dan hebt aangemaakt, is dan een Object van het type DefaultHttpClient (omdat je hem op de DefaultHttpClient class hebt gebaseerd).

Extra oefening: layer-list xml-bestand, @style, @color

Ook deze DevTutorial heeft een extra oefening. Bij deze oefening staan alleen hints over hoe je deze op kan lossen en er wordt minimale theorie-uitleg gegeven. Kom je er niet uit dan kan je het internet gebruiken of kijken op het forum. Eerst gaan we colors (kleuren) invoeren zodat we deze kunnen gebruiken als we layer-list xml-bestanden maken en styles maken (styles lijken een beetje op css-bestanden van html pagina's). Een layer-list is een verzameling van afbeeldingen die op elkaar gestapeld worden zodat je dynamische achtergronden voor Views kan maken. Deze gebruiken we om een mooie titelbalk voor de app te maken. Als je deze titelbalk straks uitvergroot zie je dit: . Bovenin de balk is een lichte streep, in het midden is een gewone blauwe gradient en onderin is een donkere streep. Deze is gemaakt door drie afbeeldingen boven op elkaar te stapelen: een blauwe gradient, een half-doorzichtige gradient die boven wit is en onder zwart, en daar bovenop weer een blauwe gradient die boven en onder ruimte over laat zodat je boven een lichte streep ziet en onderin een donkere streep. Dit soort (schaduw) effecten zorgen ervoor dat je app er gelikt uit ziet. Styles zullen gebruikt worden om de TextView die in de titelbalk staat op te maken. De colors die je invoert worden door de layer-lists en de styles gebruikt. De styles en de layer-lists gebruik je vervolgens in je layout: .

  • Maak een nieuw Android XML File aan net zoals je zou doen wanneer je een nieuwe layout aanmaakt (kijk eventueel bij DevTutorial 3 onder het kopje 'De app ontwerpen: LinearLayout'.
  • Kies bij de vraag 'What type of resource would you like to create?' voor Values en noem het bestand colors.xml en klik op Finish.
  • Op het bestand res/values/colors.xml in de Source Code Editor Tab en zorg dat de inhoud van het bestand als volgt wordt:
  • Maak een nieuw Android XML File aan, kies als type voor Drawable en selecteer Shape als root element. Geef het bestand de naam glare.xml .
  • Vul glare.xml met deze code (merk op dat je nu geen uitgetypte kleuren meer invoert maar verwijst naar de kleuren uit je bestand colors.xml):
  • Maak een nieuw Android XML File aan, kies als type voor Drawable. Geef het bestand de naam bg_header.xml . Het maakt niet uit wat je als root element selecteert, dat halen we toch zo weg.
  • Vul bg_header.xml met deze code:
  • Maak een nieuw Android XML File aan, kies als type voor Values. Geef het bestand de naam design.xml .
  • Vul het bestand met de volgende code:
  • Maak net zoals de oefening uit de vorige DevTutorial een kopie van je layout main.xml die je nicelayout.xml noemt.
  • Voeg op dezelfde manier als in de oefening uit de vorige DevTutorial een titelbalk toe door gebruik te maken een extra RelativeLayout met daarin een extra TextView.
  • Zorg via het bestand AndroidManifest.xml dat de standaard titelbalk niet meer wordt weergegeven (zie extra oefening uit vorige DevTutorial).
  • Van de RelativeLayout die je net hebt toegevoegd, zet de Background property op @drawable/bg_header .
  • Van de TextView die je net hebt toegevoegd, zet de Style property op @style/text_h1 .
Als je verder onder andere de layout_height van de RelativeLayout op 44dip hebt gezet, de juiste tekst hebt ingevoerd in de TextView en ervoor gezorgd hebt dat de TextView gecentreerd wordt gepositioneerd dan heb je nu dezelfde titelbalk als in deze screenshot: . Je kan nu proberen de rest van de layout na te maken door onder andere:
  • Een zelfde soort gradient te gebruiken voor de achtergrond van de app.
  • De achtergrond van de grote TextView een lichtere variant te geven van glare.xml.
  • De tekst in de TextView op te maken met een nieuwe style die je text_p noemt (deze kan je toevoegen onder de style text_h1 in design.xml).
  • Alle kleuren die je gebruikt in de app op te slaan in colors.xml .
De sourcecode van deze DevTutorial (zie volgend kopje) bevat al deze verbeteringen.

Sourcecode & Forum

De sourcecode kan je bekijken op github.
Hier is de forum thread voor al je vragen die horen bij deze DevTutorial.

 

Spelfouten, taalfouten of inhoudelijke fouten ontdekt? Stuur dan een mailtje naar de auteur van dit artikel!

Reacties (31)
Bezig met laden van reacties...