DevTutorial 2 - Je eerste echte app

DevTutorial 2 - Je eerste echte app

Hier is hij weer: DevTutorial nummer twee in de reeks van tien tutorials die je stevig leren hoe je apps voor Android kan programmeren. Ik wil deze DevTutorial even beginnen met te zeggen dat ik het heel leuk vond jullie reacties te lezen over de eerste DevTutorial : op het forum, in de comments, op Twitter en op Google Plus. Bedankt daarvoor! Dat motiveert me om mooie tutorials te proberen schrijven. Deze DevTutorial is een pittige: hij was moeilijk voor mij om hem zo duidelijk mogelijk te schrijven en ik kan me voorstellen dat bepaalde onderwerpen voor jullie soms alleen gedeeltelijk zijn te begrijpen. Dat komt doordat programmeren op zichzelf een best ingewikkeld onderwerp is. Hopelijk weerhoudt het jullie er niet van om er toch aardig wat Androidkennis van op te steken. Zolang je een beetje door hebt waar je mee bezig bent, zit je goed qua hoeveel je ervan begrijpt (maar het mooiste is natuurlijk als je alles begrijpt). Als je later meer werkt met Android, zullen al deze onderwerpen je langzamerhand duidelijker worden. Als je ergens niet uitkomt en je hebt het eerst zelf even geprobeerd, kijk dan in deze thread of je vraag ertussen staat. Is dit niet het geval, post je vraag en dan zullen wij je er graag mee helpen. Ook als je zelf iets lastigs tegenkwam en zelf de oplossing hebt ontdekt, kan dit ook heel nuttig zijn om als 'tip' te posten in het forum: zo maken we samen een verzameling van tips die ik na verloop van tijd zal verwerken in de DevTutorials.

Wat gaan we doen

In deze DevTutorial gaan we onze eerste echte app maken: een app die euro's om kan rekenen naar dollars en vervolgens het resultaat aan de gebruiker laat zien: . Alles wat je ziet op dat screenshot gaan we zelf programmeren. Zelfs bij het programmeren van zo'n simpele app zijn veel verschillende onderwerpen betrokken, die uiteindelijk wel weer allemaal met elkaar te maken hebben. Daarom zal ik eerst een aantal van die onderwerpen op een simpele manier proberen uit te leggen. Het begint met een algemeen voorbeeld van hoe namen worden gebruikt in Android en vervolgens laat ik je een paar voorbeelden zien hoe je hier fouten in kan maken. Hierdoor krijg je een beetje een idee in wat voor (programmeer)wereld je verzeild bent geraakt. Verder leg ik je de volgende belangrijke begrippen beknopt uit:

Daarna zul je genoeg basiskennis van Android hebben om aardig te kunnen begrijpen wat we gaan doen in de rest van deze DevTutorial. Onze app moet het volgende kunnen doen:

Om bovenstaande te kunnen doen, leg ik je eerst uit hoe een scherm opgebouwd wordt door middel van een layout die Views bevat. Vervolgens ga je je layout maken. Daarna moet je app aangestuurd worden door regels code die in een Activity geplaatst zijn. Ik leg je uit wat een Activity is en vervolgens programmeren we de volgende dingen in je Activity::

Net zoals de vorige DevTutorial heb je een Androidproject nodig:

Nu kunnen we beginnen. Succes ermee!

De programmeer-wereld van Android

Programmeren gaat stapje voor stapje en is erg gedetailleerd. Elke knop of invoerveld die je ziet op het scherm en elke berekening/reactie die je app uitvoert moet je van tevoren beschrijven. Heb je bijvoorbeeld een app die een knop laat zien waar je op moet drukken, dan moet je op zijn minst beschrijven waar de knop staat, wanneer de knop getoond en geladen moet worden en wat je app moet doen zodra je op die knop drukt. Een ander voorbeeld hiervan waar ik nu verder op in ga is hoe je met een aanpasbaar tekstveld moet werken. Stel je voor dat je in een programma een tekstveld hebt waar je tekst in kan typen (een aanpasbaar tekstveld) zoals je dat bijvoorbeeld in de sms-app hebt van Android. Een wit rechthoekig vlak waar je tekst in kan typen: Wanneer je gaat programmeren met een aanpasbaar tekstveld moet je deze een naam geven. Je kan deze eis beter begrijpen door je een situatie in te denken waarin je een sms-app hebt programmeeerd waarin je twee tekstvelden hebt; eentje voor het telefoonnumer van de geadresseerde en eentje voor het sms-bericht zelf. Als je dan via programmeren de tekst uit wil lezen van het sms-bericht kan je niet zeggen : "geef me de inhoud van het aanpasbare tekstveld", omdat Android niet weet welk aanpasbaar tekstveld je bedoelt. Je moet dat eerst aangeven door te programmeren dat je twee aanpasbare tekstvelden hebt en ze dáárna beide een naam geven: dan pas kan je de verschillende aanpasbare tekstvelden aanspreken (in dit voorbeeld: die voor het telefoonnummer en die voor de inhoud van het sms-bericht). Omdat je altijd meerdere aanpasbare tekstvelden kan gebruiken moet je dus altijd elk aanpasbaar tekstveld dat je gebruikt een naam geven. (Android heeft geen mechaniekje om na te gaan of je alleen maar één aanpasbaar tekstveld hebt of meerdere aanpasbare tekstvelden en op basis daarvan te gokken welk aanpasbaar tekstveld je bedoelt). Dit geldt trouwens niet alleen voor een aanpasbaar tekstveld maar met alles wat je ooit gebruikt in Android, zoals bijvoorbeeld een gebruikersnaam die je opslaat, een knop die je gebruikt of een scherm dat je laadt in je app. Stel je voor dat we een aanpasbaar tekstveld hebben dat we de volgende naam gegeven hebben: [gist id=1053524]

Waarom er "mEtxt" voor staat en waarom alleen de eerste letter van message een hoofdletter is zal in een van de volgende DevTutorial behandeld worden. Waarom ik het Engelse woord voor bericht (Message) gebruik kan ik al wel verklappen: alle standaard woorden/namen in Android die al voor jou bepaald zijn, zijn Engels. Het is dan onlogisch om voor de woorden/namen die je zelf kan kiezen, Nederlandse woorden/namen te gebruiken.

Met een aanpasbaar tekstveld kan je onder andere de twee volgende dingen doen:

Het eerste kan je doen door bijvoorbeeld te schrijven (dit hoef je nog niet uit te proberen, straks bij het onderdeel "De app ontwerpen" krijg je de echte opdrachten): [gist id=1052140] Het tweede kan je doen door te schrijven: [gist id=1052141] Mooi, we weten nu hoe we tekst kunnen instellen van een tekstveld én deze vervolgens weer opvragen. Vol goede moed probeer je het volgende uit: [gist id=1052144] Vervolgens probeer je het uit te voeren en tot je verbazing krijg je drie foutmeldingen. Ook als je het verandert, lukt het niet: [gist id=1052146] Dit komt omdat Java (en dus Android) erg precies is in wat voor code geaccepteerd wordt en welke niet. Het is misschien leuk om eerst even snel voor jezelf te bedenken wat deze drie foutmeldingen kunnen zijn (kijk voor inspiratie naar de bovenste twee code voorbeelden). Geprobeerd? De foutmeldingen zijn:

Nu we dit geleerd hebben kunnen we het alsnog correct uitvoeren: [gist id=1052148] Het is dus belangrijk om goed op te letten wat voor namen je gebruikt voor aanpasbare tekstvelden (en andere objecten zoals een knop of een scherm) en dat bij het gebruiken van deze objecten je ze via erg precieze manieren aanspreekt. Nu je een eerste indruk hebt van programmeren behandelen we de volgende belangrijke Androidbegrippen: Source, Syntax, Block, Activity en View.

Source Code

De bestanden waarin je met Java-taal programmeert, worden opgeslagen in de map src: hierin staan de instructies die ingelezen worden door een Androidapparaat. Deze map kan je zien in je Package Explorer Window, en dan direct onder het mapje van je Androidproject als je hem hebt uitgeklapt. Src is een afkorting van het engels woord source dat in het Nederlands bron betekent. Dit woord is gekozen omdat alle Java-code die je schrijft in de map src uiteindelijk wordt verwerkt naar een installatiepakketje (een .apk bestand) waarmee je de app kan installeren op je telefoon. De door jou geprogrammeerde Java-bestanden worden dus als bron genomen voor je uiteindelijke installatiepakketje. De combinaties van woorden en tekens die je gebruikt om Java te programmeren worden om deze reden Source Code genoemd (Nederlands woord: broncode). Tijdens het genereren van dit pakketje wordt er ook gebruik gemaakt van de bestanden die staan in de andere mappen (gen, assets, res). Maar in de bestanden die staan in de map src staat beschreven op welk moment de bestanden uit de andere mappen gebruikt moeten worden. Het genereren van dit pakketje word compileren genoemd. Tijdens dit proces wordt de programmacode die je hebt opgeschreven, vertaald naar Dalvik bytecode (in zijn geheel opgeschreven in enen en nullen), dat is de taal die een Androidapparaat kan begrijpen en dus uit kan voeren. Het programmaatje wat deze Dalvik-bytecode uitvoert heet de Dalvik Virtuele Machine, vaak afgekort als de DVM. Sommige mensen gebruiken in plaats van source code alleen het woord code. Het verschil tussen source code en code is nergens afgesproken. Maar voor deze DevTutorials spreken we het volgende af: met source code bedoelen we álle programmeer-zinnen uit je app of álle programmeer-zinnen uit een .java-bestand (bijvoorbeeld: de source code kan je hier downloaden), en met code bedoelen we alleen een paar programmeer-zinnen (bijvoorbeeld: voeg nu de volgende regels code toe...).

Voor de lezers die al programmeer-ervaring hebben: hieronder staan twee uitgebreide video's over de werking van Android en de DVM. Het is wel interessant om te kijken hoe Android en de DVM samenwerken, al is deze kennis niet noodzakelijk om Android te leren (de absolute-programmeer beginners kunnen beter deze video's over slaan; veel dingen snap je waarschijnlijk niet waardoor het lange en saaie videos voor je zijn):https://sites.google.com/site/io/dalvik-vm-internalshttps://sites.google.com/site/io/anatomy--physiology-of-an-android

Syntax

Met Java (Android is een op zichzelf staande variant afgeleid van Java) programmeren wordt bedoeld het opschrijven van combinaties van tekens en woorden op een manier die specifiek voor Java is. Een voorbeeld kan je zien als je MainActivity.java opent. Je zou kunnen zeggen dat Java zijn eigen grammatica heeft, net zoals een menselijke taal (bijvoorbeeld Nederlands of Engels) zijn eigen grammatica heeft. In de programmeerwereld gebruik je hiervoor het woord 'syntax', dit komt van het Oudgriekse woord syntaxis dat bestaat uit syn(samen) en taxis(regeling of ordening). Het Nederlandse woord hiervoor is "syntaxis" dat in gewone taal betekent "ordering" en dat dus slaat op hoe de combinaties van woorden en tekens geordend dienen te zijn in een programmeertaal. Voorbeelden van deze syntax-regels zijn:

Als je je niet aan deze regels voor deze ordering houdt dan krijg je een syntax error (een syntaxis-fout). Net ben je al twee voorbeelden tegen gekomen van zo'n syntax error: (1) wanneer je een woord encapsuleert in (") of (') moet je aan het begin en het eind van de encapsulering hetzelfde teken gebruiken en (2) elke opdracht die je geeft afsluiten met een ";". Die andere fout van de naam verkeerd spellen was een verwijzingsfout; je wees met je code naar iets dat niet bestond (omdat er geen tekstveld bestaat met die verkeerde gespelde naam).

Block

Een block is een manier van code schrijven waarin je aangeeft dat code die je plaatst tussen een '{' en een '}' bij elkaar hoort. Er zijn verschillende soorten blocks. De soort van het block geef je aan voordat je het block begint met een '{'. Deze regel sluit je dus niet af met een ';' maar je begint daar juist een nieuw block met een '{'. Een voorbeeld van een block kan je zien op regel 9 t/m 12 van MainActivity.java: [gist id=1053572]

In dit geval is het een block van het type public void onCreate(Bundle savedInstanceState), achter die beschrijving wordt het block gestart met een { en op regel 12 wordt het afgesloten met een }. Wat je net zag was een method block: door de naam van het method block te gebruiken kan je vanuit andere plekken in je code een ander method block aanroepen en uitvoeren (de naam van dit method block is onCreate). Hieronder zie je nog meer voorbeelden van andere soorten blocks (je kan ze het beste zien als voorbeeld, je hoeft de code die er staat nog niet te kunnen begrijpen):

[gist id=1053594]

[gist id=1053590]

[gist id=1053598]

Het belangrijke aan zo'n block is dat er eerst een beschrijving komt van wat voor block het is en dat daarna het block geopend wordt met '{' en gesloten wordt met een '}'. Op dezelfde manier zijn er nog andere blocks, deze kom je vanzelf tegen als je verder komt in het programmeren (bijvoorbeeld een while block of een interface block).

De app ontwerpen

Nu je genoeg basiskennis hebt, kan je bezig gaan met de app te ontwerpen die euro's om kan omrekenen naar dollars. Het begint met een layout maken. In Android is dat een bestand waarin je achter en/of onder elkaar opschrijft wat voor Views er in de layout zitten. Vervolgens wordt de layout geladen op het scherm zodat de gebruiker een interface (knoppen/tekstvelden/scheidingsruimtes/titelbalk etcetera) van een app voor zich ziet. Voordat je een layout kan maken moet je weten wat een View is. Dat wordt eerst uitgelegd, en daarna ga je je eigen Views maken in je layout.

View: een rechthoekig vlak op je scherm

Elk scherm dat je ooit in Android zult zien is opgebouwd uit zogenaamde Views. Een View is een rechthoekig gedeelte op je scherm waarin een bepaalde afbeelding is geladen. Die afbeelding kan van alles zijn: een bepaalde tekst met een bepaalde kleur en grootte, een plaatje van een knop, een plaatje van een zoekbalk, een rechthoekig vlak als leegruimte op je scherm, een grote lap tekst en ga zo maar door. Doordat er een bepaalde afbeelding in een View is geladen herkent de gebruiker een View als een knop, een stuk tekst, of iets anders. 'View' is zoals je weet het engelse woord voor 'kijken' en heeft in Android betrekking op elk element dat je ooit ziet op je Androidscherm en dat je er ooit op zult zien. Voorbeelden hiervan zijn:

Zoals je bij het tweede voorbeeld en het laatste voorbeeld kon lezen, kunnen Views ook zelf weer Views bevatten. Dit is nodig voor als je meer dan één View wilt tonen op een bepaalde gedeelte van het scherm. Wanneer je in een Views andere Views stopt, kan je tegelijkertijd ook goed aangeven hoe de Views die in een andere View zitten ten opzichte van elkaar weergegeven moeten worden. In de volgende DevTutorial leer je meer over hoe je Views in andere Views kan stoppen.

Layout: Een verzameling van Views, opgeschreven in een xml-bestand

Voor wat nu van je gevraagd wordt, is het belangrijk dat je nog weet wat het Package Explorer Window is, het Outline Window, het Properties Window en hoe die met elkaar samen kunnen werken zodat je properties aan kan passen. Ook moet je nog weten wat Editor Tabs zijn. Al deze dingen staan beschreven in de vorige DevTutorial bij het kopje "De windows van Eclipse en de Editor Tabs van het Editor Window". Lees dit nog even als je niet meer alles scherp hebt.

Voor elk scherm dat je ziet in een app moet je een layout ontwerpen. In Android is een layout een xml-bestand, waarin staat welke en hoeveel Views je in je scherm hebt en op wat voor manier de Views moeten worden weergeven. Instellen op wat voor manier je Views moeten worden weergeven, doe je door de properties van een View aan te passen (zoals je bijvoorbeeld in de vorige DevTutorial hebt gedaan door te tekst te veranderen naar "Hello Androidworld!"). Omdat je de ADT hebt geïnstalleerd voor Eclipse, kan je de layouts aanpassen met een handige Layout Editor binnen Eclipse (goed om te beseffen: Wanneer je een layout aanpast, voeg je eigenlijk dus je Views toe en pas je de Views zelf aan). Alle layouts die je voor je app maakt, worden opgeslagen in de hoofdmap res, dat staat voor resources. We houden deze app simpel, dus we maken we alleen de standaard layout. Standaard layouts worden opgeslagen in de map layout die weer in de map reszit. Toen we een nieuwe Androidproject aan gingen maken hebben we een vinkje gezet bij Create Activity. Dit zorgde er ook voor dat er al een layout is aangemaakt. Zoals je weet, wordt in Eclipse een bestand geopend in het Editor Window en vervolgens kan je de verschillende onderdelen van het bestand als een soort samenvatting in het Outline Window bekijken. Doordat een layout uit allemaal Views bestaat, zie je in het Outline Window de verschillende Views van de layout als je de layout geopend hebt in de de Editor Window. Als je dan in het Outline Window op een View klikt, kan je de properties van de View aanpassen in het Properties Window (een een property van een View kan bijvoorbeeld zijn de breedte, hoogte, margin, padding, achtergrondkleur of lettertype). Om onze app te maken hoeven we deze layout alleen nog maar aan te passen. In de app die wij willen maken willen we een invoerveld hebben waar het eurobedrag in ingevoerd kan worden. Ook moet er een knop (Button) komen die de berekening uitvoert en het resultaat laat zien als je erop drukt:

Dit heb je zojuist gedaan: Er was al een standaard layout voor je gegenereerd. Deze heb je geopend in Eclipse en je hebt deze leeggemaakt door de text "Hello World, MainActivity!" te verwijderen. Vervolgens heb je een tekstveld (EditText) en een knop (Button) toegevoegd. Je hebt het tekstveld en de knop een naam gegeven en je hebt nog andere properties (eigenschappen) ervan ingesteld. Je hebt nu een layout gemaakt die je kan laden in je app.

De app programmeren

Nu het ontwerp van je app is kan je verder met het schrijven van de regels code die je app aansturen (en dus ook de layout laden op je scherm). De basis van de code die je app aanstuurt schrijf je in een Activity, in het Code Editor Window van Eclipse. Omdat we een simpele app maken, schrijven we alle regels code in de Activity. Eerst wordt je uitgelegd wat een Activity is in grote lijnen wat hij betekent voor de Androidgebruiker. Daarna wordt uitgelegd welke regels code er vaak in een Activity zitten. Die kennis wordt gebruikt om de layout die je hebt gemaakt te laden in je Activity. Vervolgens worden de knop en het aanpasbare tekstveld opgezocht in de geladen layout en gekoppeld aan je code in je Activity. Daarna wordt uitgelegd hoe je regels code kan organiseren in methods, zodat je verschillende groepjes van regels code afzonderlijk aan kan spreken. Vervolgens maken we een method, die we aan laten roepen door de knop als deze ingedrukt wordt. Deze method vullen we vervolgens met code die het door de gebruiker ingevulde getal uitleest, deze omrekent naar dollars en vervolgens het resultaat toont aan de gebruiker in een zwart zwevend balkje (een Toast). Dat wordt je app:)

Activity

Toen je het Androidproject ging aanmaken heb je aangegeven dat je al een Activity wilde generen (je had een vinkje gezet bij Create Activity). Deze Activity noemde je MainActivity. Een Activity (meervoudsvorm: Activities) is een belangrijk begrip in Android. De Nederlandse vertaling hiervoor kan je vast al raden: 'Activiteit'. Een Activity is een stukje Androidcode waarmee de gebruiker een activiteit uit kan voeren op zijn telefoon. Bij een Activity kan je denken aan:

Zo'n activiteit heeft meestal één scherm (opgebouwd door middel van een layout) waarop hij (en de kleine activiteiten die bij de 'echte' activiteit horen) wordt uitgevoerd . De code die je opschrijft in je Activity wordt gebruikt om het scherm aan te sturen dat bij de Activity hoort. Bij het gebruiken van een rekenmachine heb je bijvoorbeeld 10 knoppen voor alle cijfers en nog een paar knoppen zoals vermenigvuldigen, optellen en uitrekenen: . Wanneer je op één van de knoppen drukt, roep je eigenlijk code aan die bij die knop hoort. De code bij de = knop bestaat uit meerdere regels code onder elkaar die de som uitrekenen die net is ingevoerd en toont de uitkomst vervolgens op het scherm (Voor het uitvoeren van code ben je als programmeur trouwens niet enkel gebonden aan de knoppen, je kan ook zelf je momenten uitkiezen waarop bepaalde code wordt uitgevoerd). Nog een voorbeeld is bij het invoeren van een notitie: je kan een scherm hebben waarop een groot tekstveld staat met daaronder een knop voor opslaan en een knop voor verwijderen. Een Androidapplicatie bestaat vaak uit meerdere activiteiten. Zo bestaat je notitie-app bijvoorbeeld uit een Activity die je alle notities laat zien, een activity waar je je notities kan doorzoeken en een Activity waarin je een bestaande notitie kan aanpassen of een nieuwe notitie kan toevoegen. Elke Activity heeft dan zijn eigen layout.

Een ander voorbeeld is een app die ik (eigenlijk wij: Moop.me) gemaakt heb: de EHBO-app van het Rode kruis. In deze screenshots zie je alle aparte Activities waaruit deze app is opgebouwd: . Eigenlijk zie je de Activities hier niet op, je ziet alleen maar de layouts van de Activities en je vertrouwde mij waarschijnlijk toen ik schreef dat achter die schermen Activities met code hangen.

Een app bestaat dus (meestal) uit meerdere Activities. Dit was meer een algemene beschrijving van wat een Activity is. Nu volgt een basis-uitleg van de technische werking achter een Activity.

Een belangrijke Class:  de Activity class

Wat je ziet op het scherm als je een Activity aan heb staan, kan je aanpassen in een layout-bestand (met de Layout Editor, zoals je net gedaan hebt). Verder had je net gelezen dat een app bestaat uit meerdere Activities die na elkaar getoond worden, afhankelijk van welke knoppen worden ingedrukt of welke andere acties uitgevoerd worden.

Wat je nog niet hebt gedaan is beschrijven hoe je Activity moet reageren op het indrukken van de knoppen of andere acties van de gebruiker. Je hebt ook nog niet beschreven wat er moet gebeuren als je eerste Activity van je app opstart en of er bijvoorbeeld nog iets moet gebeuren als hij wordt afgesloten. Dit noem je programmeren: het opschrijven van een reeks instructies die uitgevoerd moeten worden door het Androidapparaat. Zoals je weet noem je die teksten je code. Bij Android staat je sourcecode in Java-bestanden in de map src in (het Package Explorer window). Deze code is in dit geval opgeschreven in een class. Een uitgebreidere beschrijving van een Class volgt nog in een latere DevTutorial, maar voor nu kan je het beste onthouden dat een Class een .java-bestand is waar je regels java-code in kan schrijven. Een belangrijk type class is de Activity class, deze was al je voor aangemaakt toen je een nieuw Androidproject aanmaakte, door een vinkje te hebben gezet bij Create Activity.

Ga in het Package Explorer Window naar de map src, vervolgens naar de package me.moop.moneyconverter en open het bestand MainActivity.java door erop te klikken. Klik op het plusje dat helemaal links op regel 3 staat. Je hebt nu het Java-bestand voor je dat hoort bij de Activity genaamd "MainActivity" die we willen gaan programmeren. Op de volgende screenshot heb ik het bestand opgedeeld in drie delen: .

We gaan het eerst over het belangrijkste gedeelte hebben, het onderste gedeelte. In het onderste gedeelte, de eigenlijke broncode (regel 6 t/m regel 13), beschrijf je wat dit Java-bestand doet: hierin schrijf je de instructies die het Androidapparaat uit moet voeren wanneer die dit bestand uitvoert. De naam van het bestand (MainActivity.java) vind je terug aan het begin van het bovenste gedeelte (dus op regel 6): je ziet daarin het woord "MainActivity" staan. Wanneer je dit bestand wilt gebruiken op een andere plek in je Androidapplicatie, zul je dit woord ("MainActivity") moeten gebruiken. Zoals je misschien al op regel 6 ziet staan, noem je dit gedeelte van het bestand een class (Nederlands woord klasse of type). In Android betekekent "klasse" zoiets als: wat voor type java bestand is dit en wat kan je ermee. Wat het precies voor een type bestand is en wat je ermee kan beschrijf je in de broncode van de klasse als je hem gaat vullen met andere blocks. De broncode van de klasse begint na de allereerste { aan het eind van regel 6, en eindigt bij de laatste } op regel 13. Je zou ook kunnen zeggen: het block van de klasse MainActivity begint aan het eind van regel 6 en eindigt op regel 13.

Een klassenaam moet uniek zijn: er mag niet een andere klasse bestaan die ook "MainActivity" heet. Hier is een belangrijke uitzondering op en daarvoor moet je even kijken naar het bovenste gedeelte van het Java-bestand op regel 1. Op die regel staat de groepnaam (Engels woord: package name) van de groep van bestanden waar dit Androidbestand bij hoort. Wanneer je dit Androidbestand wilt gebruiken, moet je daarbij zijn groepnaam (package name) meegeven. In dit geval is de package name me.moop.moneyconverter. Wanneer je deze klasse gebruikt, dan moet je zijn package name en zijn class name meegeven: me.moop.moneyconverter.MainActivity. Het is dus niet zo dat de klassenaam (class name) uniek moet zijn, maar de combinatie van de groep naam (package name) en de klassenaam (class name) moeten uniek zijn.

Nu weet je grotendeels de indeling van een veel voorkomend Java-bestand: op de eerste regel staat bij welke package (groep) hij hoort en daaronder staat de klasse die begint na de eerste { en eindigt bij de laatste } (wat die zinnen met import betekenen, kom ik later op terug).

Views: Imports, definiëren en koppelen aan je layout

Ga terug naar Eclipse en open MainActivity.java als je die alweer gesloten had. Je ziet dat de klasse MainActivity welgeteld één method block heeft: onCreate. Deze methode (dus alles dat tussen regel 9 en 12 staat) wordt uitgevoerd wanneer deze Activity wordt opgestart. Wat je van deze methode nu moet weten, is dat in regel 11 opdracht wordt gegeven om de layout "main" te laden. Deze layout heb je net zelf gemaakt bij "Layout: Een verzameling van Views, opgeschreven in een xml-bestand". Nu wil je de EditText en de Button gebruiken die je in je layout hebt gestopt. Je hebt de EditText namelijk nodig om het ingevoerde eurobedrag uit te kunnen lezen en je hebt de Button nodig om te kunnen weten wanneer hij is ingedrukt, zodat je het resultaat van de berekening kan laten zien. Toen de layout geladen werd, werd het scherm gevuld met de layout die je aangaf maar je hebt nog niet aangewezen welke views je wilt gebruiken van de views die in je layout zitten. Maar eerst moet je, voordat je de Button en de EditText kan gebruiken, eerst aangeven dat je überhaupt met een Button en een TextView wil gaan werken en je moet ze een unieke naam meegeven. Dit doe je door de twee volgende regels toe te voegen, direct na het begin van je class op regel 8 en 9, met daarboven en daaronder een lege regel: [gist id=1054115] Je scherm moet er nu als volgt uitzien: . Met deze twee regels heb je gezegd: Ik wil een gaan EditText gebruiken, deze noem ik eTtxtAmount en ik wil ook nog een Button gaan gebruiken, deze noem ik mBtnCalculate. In programmeertaal zou je kunnen zeggen: ik heb een EditText gedefiniëerd die ik mEtxtAmount noem en ik heb een Button gedefinieerd die ik mBtnCalculate noem. Ik raad je aan te onthouden wat definiëren is: dit zul je nog vaak gebruiken wanneer je voor Android programmeert. Tot je verbazing zie je twee fouten aangegeven aan het begin van regel 8 en aan het begin van regel 9 (en je deed nog wel precies wat ik van je vroeg...). Als je met je muis stil blijft staan op de fout op regel 8 dan zie je het volgende: . Er staat: EditText cannot be resolved to a type. In gewoon Nederlands betekend dat: ik weet niet wat je bedoelt met een EditText, ik kan daar niks mee. Dit heeft wat uitleg nodig. Android weet niet wat je bedoeld met een EditText, omdat hij nog niet weet dat je die wilt gebruiken in je Activity. Er zijn namelijk zo ontzettend veel componenten die je kan gebruiken in Android, dat Android niet automatisch bij kan houden welke componenten je wel en niet wilt gebruiken in een Java-bestand. Conclusie: voordat je het woord EditText gebruikt in je Java-klasse, die MainActivity heet, moet je deze eerst zélf introduceren in je Java-bestand. In gewoon Nederlands uitgedrukt moet je zoiets als dit doen: Hey Android, ik wil je een nieuw component voorstellen en hij heet EditText. Dit kan je doen door te beschrijven wat de locatie is van het EditText component en dit neer te zetten aan het begin van je Java-bestand. Het woord dat je hiervoor moet gebruiken is import,gevolgd door de package name + de naam van de class.

[gist id=1054161]

Je vraagt  je misschien af waar de EditText vandaan komt en hoe ik je weet te vertellen dat hij in de package android.widget zit. Net las je namelijk nog iets over de naam die je aan een Class kan geven en dat je hem in een groep (package) moet zetten. Maar je hebt alleen nog maar een Androidproject aangemaakt en je hebt nog maar één class, namelijk MainActivity. Waar komt die EditText dan vandaan? Het handige van Android is dat je al heel veel andere classes kan gebruiken die door de makers van Android gemaakt zijn. Al deze classes kan je hier vinden, dat is de catalogus van alle Androidclasses (en andere objecten) die je kan gebruiken. Als oefening kan je proberen om op die pagina te zoeken naar android.widget, op de volgende pagina te zoeken naar EditText en dan te zoeken naar de method getText(). Probeer de Engelse beschrijving van deze method een beetje te begrijpen (over deze method schreef ik namelijk wat aan het begin van deze DevTutorial). Terwijl je dat zoekt, ben je dus eigenlijk aan het zoeken in de groepen (packages) van Android, op zoek naar een class in de package, op zoek naar een method.

Je scherm moet er nu als volgt uitzien: . Je hebt nu het EditText component geïntroduceerd, en zoals je kan zien weet Android nu wél wat je bedoelt met een EditText en is de foutmelding op regel 9 (was eerst regel 8 ) verdwenen. Laat me je nu helpen te begrijpen wat de regels 3 t/m 5 betekenen: wanneer je het woord "import" gebruikt, verwijs je dus eigenlijk naar een ander Java-bestand (class). Dit, zodat wanneer je later een naam gebruikt van die class (in dit geval EditText) in je huidige class (in dit geval MainActivity), Android weet wat je ermee bedoelt. Misschien was het je al opgevallen, de woorden die je gebruikt nadat je import hebt getypt: daarmee verwijs je naar een andere class en tegelijkertijd geef je aan in welke groep (package) die class zich bevindt. Wanneer je deze zin typte: [gist id=1054161] Verwijs je dus naar de de class EditText, die zich bevindt in de de groep (package) "android.widget". Het kunnen verwijzen naar andere classes, zodat je deze kan gebruiken in je eigen class, is een erg belangrijk en veel gebruikt principe in Android. Probeer dit extra goed te begrijpen, lees bovenstaande alinea desnoods nog een paar keer door. Als je het daarna niet meteen begrijpt is dat heel normaal. Het gaat mij er even om dat je de woorden package, class en importeen paar keer voorbij ziet komen en een klein beetje weet wat ze betekenen. Door middel van het woord import kan je een andere class uit een andere package gebruiken in je eigen class.

Wanneer de class die je wilt gebruiken in precies dezelfde groep (package) zit, dan hoef je ze niet te introduceren met een import; Android onthoudt die classes dan vanuit zichzelf al.

Nu gaan we de fout op regel 10 oplossen. Zoals je nu misschien zou kunnen raden, geeft die fout aan dat Android niet weet wat je bedoelt met een Button. Dit los je op door in het begin van je Java-bestand de class Button te introduceren.

[gist id=1054181] Ik beschreef net dat op regel 11 (inmiddels regel 17), opdracht wordt gegeven om de layout te laden die "main" heet. Als gevolg hiervan wordt het tekstveld en de knop die je in de layout "main" beschreven hebt, op het scherm geladen. Hiermee koppel je dus eigenlijk je layout aan je Activity. Android weet nu wel dat de layout en de Activity bij elkaar horen, maar heeft nog geen flauw idee hoe je die knoppen wil gebruiken die je vanuit de layout op je scherm hebt geladen. Je moet ze nu koppelen aan de EditText mEtxtAmount en Button mBtnCalculatedie je op regel 10 en 11 hebt beschreven.

[gist id=1054192] Bovenstaande zin kan je opdelen in het gedeelte voor het =-teken en het gedeelte na het =-teken. Het gedeelte na het =-teken, betekent dat je wilt dat Android op zoek gaat naar een EditText die als Id (identifcatie), dus als naam, etxtAmount heeft. Toen je eerder in deze DevTutorial met de layout main bezig was, heb je een EditText in de layout geplaatst en vervolgens zijn Id (naam) gezet op @+id/etxtAmount. Toen Android de layout main ging laden, kwam hij die EditText tegen in de layout. Daar stond dus ook in dat je de EditText als naam @+id/etxtAmount hebt gegeven. Door het woordje findViewByID te gebruiken, zorgde je ervoor dat Android op zoek gaat naar een View die als Id de waarde etxtAmount heeft. Het =-teken betekent dat wat je aan de rechterkant beschrijft, plaatst in het object dat je links van het =-teken hebt. Conclusie: met bovenstaande zin heb je Android opdracht gegeven te zoeken naar een EditText met Id etxtAmounten deze in mEtxtAmount gestopt. Hiermee heb je dus de "fysieke" knop op het scherm gekoppeld aan de naam mEditText in je class.

[gist id=1054204] Je class MainActivity moet er nu als volgt uitzien: [gist id=1054212]

Method: Het groeperen van instructies en die samen één naam geven

Een klasse is opgedeeld in kleine stukjes functionaliteit die je afzonderlijk kan aanroepen. Het officiële woord hiervoor is een method (Nederlands woord: methode). Zoals je eerder las zijn deze methods aangegeven met method blocks. Het woord methode slaat op het idee dat je binnenin de methode beschrijft wat het Androidapparaat moet doen, of anders gezegd: hoe moet het Androidapparaat omgaan met de informatie die hij op dit moment beschikbaar heeft en/of af kan afleiden aan de hand van beredeneringen die je in die method beschrijft. Informatie die op dat moment beschikbaar is, kan bijvoorbeeld de naam van de gebruiker zijn die eerder is ingevoerd, de huidige datum en tijd, hoeveel euro's de gebruiker bezit en wat de huidige euro-dollar koers is. Uit die informatie kan je, door middel van beredeneringen die je opschrijft, het Androidapparaat bijvoorbeeld zelfstandig de euro's van de gebruiker om laten rekenen naar dollars. Die manier van omgaan met informatie en het afleiden ervan, specificeer je door het Androidapparaat instructies te geven in je sourcecode (en die instructies, die moet je nou juist elke keer afsluiten met een ; ).

Een method beschrijf je door een nieuw method block in te typen binnen het block van de klasse. In het volgende screenshot kan je bij wijze van voorbeeld drie methods zien: (deze code hoef je niet over te nemen). In het voorbeeld zijn dit drie methods die op een bepaald moment worden aangeroepen:

Zoals je in de laatste screenshot kan zien, schrijf je de instructies voor het Androidapparaat dus niet zomaar in het block van je class. Alle instructies groepeer je dus in aparte methods. Het handige daarvan is dat je verschillende methods hebt met hun eigen namen, die hun eigen taken uitvoeren. Hierdoor kan je je code in kleine stukjes (=methods) opbouwen, die elkaar aanroepen wanneer ze elkaar nodig hebben. Stel je hebt een app die een lampje bovenin het scherm heeft. Met de app kan je to-do-items invoeren en afvinken. Stel nou dat je het lampje bovenin je app aan wilt laten gaan wanneer een to-do-item al drie dagen open staat óf wanneer er meer dan tien to-do-items nog niet afgevinkt zijn. Je hebt dan sowieso twee methods nodig. Eén controleert of er to-do- items meer dan drie dagen open staan, deze method noemen we even checkThreeTodoItems. De andere method controleert of er meer dan tien to-do-items niet afgevinkt zijn, deze method noemen we even checkTenTodoItems. Je zou in de methods ook in kunnen bouwen dat ze na hun controle meteen het lampje in je app aan zetten als dat nodig is, zodat je twee methods hebt. Je kunt echter veel beter een aparte method aanmaken die het lampje in de app aan zet, bijvoorbeeld een method met de naam turnLampOn. Op deze manier kunnen de twee aparte methods deze ene method aanroepen en hoef je de code die je nodig hebt om het lampje aan te zetten niet twee keer te typen. Ook is dit erg handig wanneer je in de toekomst de kleur van het lampje aan wilt passen, dat hoef je dan maar in één method te doen in plaats van twee methods. Ook wordt je code er overzichtelijker van: doordat je kleine methods hebt met makkelijke namen, zie je in één opslag welke method wat doet. Als je in totaal maar twee methods zou hebben, dan zou je twee dingen die eigenlijk niet bij elkaar horen (het controleren van een getal én het scherm aanpassen) in één method stoppen waardoor je code rommeliger wordt.

Button: On click

Met setContentView heb je een layout geladen in je app en met findViewById heb je de Views in je class MainActivity gekoppeld aan de Views in je layout. Je hebt nog niet beschreven hoe je Activity moet reageren als op de Button mBtnCalculate wordt gedrukt. Het mooiste zou zijn als je op één of andere manier aan kan geven dat een aantal regels code moeten worden uitgevoerd wanneer op de knop wordt gedrukt. Dan zou je zelf die regels code kunnen schrijven en daardoor heb je precies controle over het gedrag van de Button mBtnCalculate. In die regels code zou je dan schrijven dat met het ingevulde eurobedrag een berekening uitgevoerd moet worden en het resultaat ervan getoond moet worden. Gelukkig is dit ook mogelijk: als je main.xml opent in de Graphical Layout Editor Tab, dan kan je de property On clickaanpassen van je Button. In die property moet je dan aangeven welke method moet worden uitgevoerd als op de Button wordt gedrukt. Die method moet je dan zelf aanmaken in je Activity waarin je de layout gebruikt. Dan wordt de Button automatisch gekoppeld aan de genoemde method:

[gist id=1056204]

[gist id=1056209]

If block

Alles wat je typt in de method die je net aanmaakte, wordt uitgevoerd wanneer op de knopt wordt gedrukt. Een controle die je altijd moet uitvoeren wanneer je met het indrukken van Buttons (knoppen) werkt, is controleren of de Button die is ingedrukt wel de Button is welke je dacht. Je moet dus eigenlijk een vraag kunnen stellen in Android: de knop die net was ingedrukt, is dat de knop mBtnCalculate?. mBtnCalculate is namelijk de Button in je class die je had gekoppeld aan je knop in main.xml. Met een if block kan je in Android een vraag stellen. Je gebruikt daarvoor het woord if en daarna moet je een vraag tussen haakjes erachter zetten. Daarna begin je het block dat moet worden uitgevoerd als de vraag met ja wordt beantwoord. Dit is zo'n if block: [gist id=1056238] In bovenstaand voorbeeld wordt een nieuw getal gemaakt met de naam someNumber. Het getal wordt op 4 gezet. Daarna wordt tussen de haakjes na het woord if de vraag gesteld: is someNumber kleiner dan 9?. Omdat someNumber net op 4 is gezet is someNumber inderdaad kleiner dan 9. Als gevolg daarvan wordt het block dat erna komt uitgevoerd: dat is het tonen van een zwart balkje onderin je scherm met daarin de tekst "someNumber is smaller than 9". Als je trouwens in plaats van het getal 4 bijvoorbeeld het getal 20 had ingevoerd, dan werd het if block niet uitgevoerd, simpelweg omdat het getal 20 niet kleiner is dan het getal 9. Het enige wat je nu nog moet weten is hoe je precies de vraag schrijft waarmee je vraagt: de knop die net was ingedrukt, is dat de knop mBtnCalculate?. Het vergelijken van twee objecten, dat doe je met "==". Wanneer de method wordt aangeroepen, wordt de knop die net is ingedrukt in een View gestopt met de naam view. Dit kan je zien in de beschrijving van je method block: je ziet daar tussen haakjes staan: View view. Hoe dit verder werkt wordt in de volgende DevTutorial uitgelegd.

[gist id=1056260] Met het dubbele =-teken, ==, vraag je of het object links ervan hetzelfde is als het object rechts ervan. Het woord view bevat de Viewdie zojuist is aangeraakt. Dus met bovenstaande zin vraag je, in normaal Nederlands vertaald: De view die net is aangeraakt, is dat de knop mBtnCalulcate? Vervolgens begin je met het code block dat wordt uitgevoerd wanneer deze vraag met "ja" wordt beantwoord. De inhoud ervan wordt besproken onder het volgende kopje.

EditText: tekst uitlezen en omzetten naar een getal

Nu we gecontroleerd hebben of wel echt de juiste knop is ingedrukt, kunnen we de tekst opvragen die in het tekstveld mEtxtAmount staat.

[gist id=1056283] Deze helemaal uitleggen zou deze tweede DevTutorial te ingewikkeld maken. Maar wat al wel goed is om te weten, is dat we een getal aanmaken die we euros noemen. Een woord voor een getal met komma's in Android is float (een getal zonder komma's in Android is een int). Het getal euros vullen we met het getal dat we opvragen van het tekstveld (het opvragen van het getal staat immers rechts van het =-teken).

[gist id=1056285]

[gist id=1056289] Bovenstaande zin is ook te complex om meteen uit te leggen (deze DevTutorial focust zich op een selectie van algemene begrippen van Android). Wat al wel goed is om te begrijpen, is dat hetgene dat tussen de twee enige komma's staat, de tekst is die weergegeven wordt. In dit geval begint dat bij het euro-teken en eindigt het bij de verwijzing naar dollars. Wederom staat er een kringeltje in deze zin: in dit geval weet Android niet wat je bedoelt met "Toast". Voeg de volgende import toe ergens boven het begin van je class: [gist id=1056293] Je class moet er nu als volgt uitzien: [gist id=1056296]

Je eerste echte Androidapp is nu klaar! Je kan de app nu uitproberen door een getal in te vullen in het tekstveld en op de knop te drukken: (in de vorige DevTutorial was uitgelegd hoe je een app op kan starten).

Ik hoop dat je het weer leuk vond om te doen en zie je graag terug op het forum of in de volgende DevTutorial! De volgende DevTutorial gaat dieper in op layouts en Views, en laat je ook werken met het datumveld.

Lees meer over:
DevTutorial

Plaats reactie

666

0 reacties

Laad meer reacties Bekijk alle reacties

Meest gelezen

3 manieren om stiekem en ongemerkt WhatsApp-berichten te lezen

Berichten-apps komen met de handige bevestiging om te zien of de ander jouw berichtje heeft gelezen. Toch kan je in apps als...

Google Pixel 5a (5G) komt definitief niet naar Europa

Vrijdagavond deden geruchten de ronde over een afgestelde lancering van de Pixel 5a. Mede door de chiptekorten zou Google de...

Gegevens van 500 miljoen LinkedIn-gebruikers online te koop aangeboden

Na een immens datalek bij Facebook, lijkt het ditmaal mis te zijn gegaan bij LinkedIn. Via een bekend hackersforum wordt name...

Google bevestigt einde Shopping-app, gaat door als website

Googles Graveyard, gevuld met apps die na jaren in dienst te hebben gestaan van gebruikers wereldwijd worden afgedankt, wordt...

Fitbit wil bloeddrukmetingen mogelijk maken op zijn smartwatches

Bloeddrukmetingen zijn normaliter alleen weggelegd voor dure apparatuur die men gebruikt in ziekenhuizen of huisartsenposten....

Lees meer

Net binnen

Fitbit wil bloeddrukmetingen mogelijk maken op zijn smartwatches

Bloeddrukmetingen zijn normaliter alleen weggelegd voor dure apparatuur die men gebruikt in ziekenhuizen of huisartsenposten....

Gegevens van 500 miljoen LinkedIn-gebruikers online te koop aangeboden

Na een immens datalek bij Facebook, lijkt het ditmaal mis te zijn gegaan bij LinkedIn. Via een bekend hackersforum wordt name...

Google bevestigt einde Shopping-app, gaat door als website

Googles Graveyard, gevuld met apps die na jaren in dienst te hebben gestaan van gebruikers wereldwijd worden afgedankt, wordt...

3 manieren om stiekem en ongemerkt WhatsApp-berichten te lezen

Berichten-apps komen met de handige bevestiging om te zien of de ander jouw berichtje heeft gelezen. Toch kan je in apps als...

Google Pixel 5a (5G) komt definitief niet naar Europa

Vrijdagavond deden geruchten de ronde over een afgestelde lancering van de Pixel 5a. Mede door de chiptekorten zou Google de...

Lees meer