APPI Labo Leo Rutten 10/ 4/2017 Inhoudsopgave 1. Inleiding ................................................................................................................... 1 2. Eerste kennismaking met Linux ................................................................................... 1 3. Het eerste voorbeeld .................................................................................................. 2 3.1. Het voorbeeld bekijken .................................................................................... 2 3.2. Het voorbeeld uitbreiden .................................................................................. 9 3.2.1. build.gradle aanpassen ................................................................. 10 3.2.2. Aanpassing layout ............................................................................... 10 3.2.3. Aanpassing Java ................................................................................. 11 3.2.4. Nog een extra uitbreiding ..................................................................... 11 3.2.5. Logging ............................................................................................. 11 4. Een ListView voorbeeld met een eigen dataklasse ...................................................... 12 4.1. Voorbereiding ............................................................................................... 12 4.2. De Rechthoek klasse .................................................................................. 12 4.3. Een layout voor elke rechthoek ........................................................................ 13 4.4. De aangepaste ArrayAdapter klasse ............................................................. 14 4.5. Aangepaste MainActivity .......................................................................... 15 1. Inleiding Dit is de begeleidende tekst voor het labo van het vak APPI. In dit labo wordt een aantal concepten van het Android platform praktisch uitgewerkt. Meestal start je met een voorbeeld dat je op één of andere manier moet uitbreiden. Dit is de software die we in dit labo nodig hebben: • • • • • • • Linux Slackware64 14.2 De bash commandolijn Editors zoals pico, kate of jedit Versiebeheer met git De buildtool gradle De Android SDK Android Studio In de eerste faze wordt er enkel met de commandolijn gewerkt. Later wordt Android Studio ingezet. Ook als deze laatste in gebruik genomen is, blijft de commandolijn belangrijk. Het is bijvoorbeeld aanbevolen om git altijd via commandolijn te blijven gebruiken. 2. Eerste kennismaking met Linux De distributie in de labo's is Slackware64 14.2. Deze versie is van juli 2016 en wordt bij elke boot geupdate. Dit betekent dat het opstarten iets trager verloopt. Om het werk in het labo praktisch mogelijk te maken, heeft elke gebruiker een eigen login met daaraan gekoppeld een homedirectory. Deze login staat volledig los van alle andere logins op deze campus. De homedirectories bevinden zich op de 1 APPI Labo afss1 fileserver. De schijfruimte op deze server is beperkt tot 70 Gb. Daarom wordt er spaarzaam omgegaan met het toekennen van schijfruimte aan de gebruikers. De software om een persoonlijke login mogelijk te maken met de afss1 is: • OpenAFS voor de opslag van de bestanden • OpenLDAP voor het bijhouden van het gebruikersprofiel • Kerberos5 als authenticatieserver Het is verplicht om in te loggen met de toegekende loginnaam en het bijbehorende paswoord. De lijst van loginnamen met foto wordt getoond op het aanmeldscherm. Login met de juiste loginnaam en paswoord. Start konsole en test een aantal van deze commando's: ls, pwd, cd, mkdir, rmdir, cat, less, rm. Er is nog een tweede server die we nodig hebben in dit vak. Dat is de server met domeinnaam eaict.technologiecampusdiepenbeek.be. Het verschil met afss1 is dat deze buiten de UCLL firewall staat. Hierdoor is die van buitenaf bereikbaar. Dit geldt niet voor afss1. Deze staat binnen de firewall en is bijgevolg alleen maar bereikbaar vanuit de UCLL gebouwen. De eaict server hebben we nodig voor het versiebeheer met git. Hier zijn twee mogelijkheden: • Je maakt gebruik van de Git opslagruimte van eaict.technologiecampusdiepenbeek.be/gitblit/ • Je houdt de projecten bij in je homedirectory binnen eaict. Deze homedirectory kan je bereiken via ssh. Gitblit is een serverapplicatie die een webinterface voor Git opslagruimten aanbiedt (repositories). Het voordeel is dat je dan via de webinterface de projecten kan volgen. De taak voor APPI moet op deze wijze beheerd worden. 3. Het eerste voorbeeld 3.1. Het voorbeeld bekijken Het eerste voorbeeld wordt met android create gecreëerd en met gradle gecompileerd. Deze werkwijze is zo simpel maar is toch nuttig om éénmalig uit te proberen. In praktijk kan je als student beter met Android Studio werken. Het nut om toch éénmaal een Android project met gradle te compileren is dat je zo een goed inzicht krijgt in het proces van compileren en testen van een Android applicatie. Het is in het algemeen zo dat projecten via commandolijn bouwen bij de meeste technologieën aanwezig is om dit soort expertise te kunnen opbouwen. Omdat voor een Android project een heleboel bestanden in een vaste mappenstructuur nodig zijn, moet je ofwel een bestaand voorbeeld kopiëren of een nieuw project genereren. Wij kunnen de laatste optie kiezen die mogelijk is met het android create commando. Dit is het commando: android create project \ -g -v 2.2.3 \ --target android-25 \ --name MyFirstApp \ --path MyFirstApp \ --activity MainActivity \ --package com.example.myfirstapp 2 APPI Labo Dit commando maakt een nieuwe map met daarin alle bestanden voor een nieuw project. Je moet een aantal parameters meegeven. • -g -v 2.2.3 Gebruik een Gradle sjabloon (-g) voor de Gradle Android plugin versie 2.2.3 (2.2.3). • --target android-25 Deze parameter geeft aan voor welke versie van Android de applicatie wordt gecompileerd. android-25 is het API-nummer van Android 7.1.1. • --name MyFirstApp Dit is de naam van de applicatie. • --path MyFirstApp Dit is de map waarin het nieuwe project terecht komt. • --activity MainActivity Dit is de naam van de Java klasse die dienst doet als hoofdactiviteit. • --package com.example.myfirstapp Dit is de packagenaam die gebruikt zal worden voor alle Java klassen. In plaats van het android create commando is er nog dit alternatief: haal het voorbeeld af met git. Dit is het commando: git clone http://eaict.technologiecampusdiepenbeek.be/gitblit/r/android/vb01-myf Het volgende overzicht geeft weer hoe de bestandenstructuur van een minimale Android applicatie eruit ziet. Omdat in dit geval gradle wordt gebruikt om te compileren, zijn er een aantal bestanden specifiek voor gradle gegenereerd. Als je op een andere wijze gaat compileren, mogen die bestanden geschrapt worden en moet je andere configuratiebestanden gebruiken. Voor het compileren van Android apps is gradle echt wel belangrijk. Ook als je Android Studio gebruikt, wordt in de achtergrond Gradle gebruikt voor de compilatie; Google heeft immers voor Gradle gekozen als algemene buildtool. We overlopen de bestanden en mappen. AndroidManifest.xml is het belangrijkste configuratiebestand en wordt later uitgelegd. build.gradle legt vast hoe gradle de compilatie moet uitvoeren. De overige bestanden in de hoofdmap zijn niet zo belangrijk. De map res bevat een aantal submappen met daarin allerlei bronnen die in het project gebruikt worden. De figuren staan in een aantal drawable submappen volgens de resolutie. De map layout bevat main.xml. Dit is de layoutbeschrijving van de applicatie. De map values bevat o.a. alle teksten die in de applicatie gebruikt worden. . |-- build.gradle `-- src |- - androidTest | `-- java | `-- com | `-- example | `-- myfirstapp | `-- MainActivityTest.java `-- main |-- AndroidManifest.xml 3 APPI Labo |-- java | `-- com | `-- example | `-- myfirstapp | `-- MainActivity.java `-- res |-- drawable-hdpi | `-- ic_launcher.png |-- drawable-ldpi | `-- ic_launcher.png |-- drawable-mdpi | `-- ic_launcher.png |-- drawable-xhdpi | `-- ic_launcher.png |-- layout | `-- main.xml `-- values `-- strings.xml Het bestand AndroidManifest.xml bevat de belangrijkste configuratiegegevens van de applicatie. <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.myfirstapp" android:versionCode="1" android:versionName="1.0"> <application android:label="@string/app_name" android:icon="@drawable/ic_lau <activity android:name="MainActivity" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> Met package="com.example.myfirstapp" wordt de Java packagenaam vastgelegd. De applicatie krijgt een label met android:label="@string/app_name" en een ikoon met android:label="@string/app_name". Binnen de applicatie is er een activiteit met een klassenaam android:name="MainActivity" en een label. Binnen de activiteit wordt een intent-filter vastgelegd. Hiermee wordt bepaald dat deze activiteit als hoofdactviteit van deze applicatie kan gestart worden. In andere woorden, als je dit niet vastlegt, kan de applicatie niet gestart worden. Bij de waarden van de attributen worden de notaties @string en @drawable. Hiermee wordt verwezen naar de bronnen die zich in de map res bevinden. Het bestand strings.xml bevat alle teksten die in de applicatie voorkomen. Door de teksten uit de Java broncode weg te houden is het veel gemakkelijker om automatisch van taal te wisselen. Voor elke tekst is er een name attribuut dat als sleutel wordt gebruikt. <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">MainActivity</string> </resources> 4 APPI Labo Het bestand main.xml beschrijft de layout van de view die in de activiteit weergegeven wordt. Opmerkelijk is dat afmetingen in pixel of andere eenheden volledig ontbreken. Hierdoor kan de layout gemakkelijk aangepast worden aan verschillende schermgroottes. <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello World, MainActivity" /> </LinearLayout> De layoutbeschrijving is een boomstructuur van views die vastleggen wat er in een activity wordt weergegeven. Voor deze beschrijving wordt XML gebruikt omdat je hiermee gemakkelijk een hiërarchie kan vastleggen. In het voorbeeld wordt een verticale lineaire layout toegepast met daarin een tekstview. Dit laatste is een veld met daarin een tekst. Beide views nemen de volledige breedte in beslag; de hoogte van de tekstview is afhankelijk van de tekst. Zowel LinearLayout als TextView zijn views. LinearLayout en TextView zijn hier elementen in het XML bestand maar daarnaast zijn het ook klassen die met de Android API meegeleverd worden. Het bestand MainActivity.java bevat de Java broncode van de hoofdactiviteit van de applicatie. package com.example.myfirstapp; import android.app.Activity; import android.os.Bundle; public class MainActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } } De klasse MainActivity bevindt zich in de package com.example.myfirstapp en de klasse is afgeleid van de klasse Activity. Door deze erfenis krijgen we een klasse die dienst doet als activiteit. In deze applicatie is er maar één activiteit; in andere applicaties kan je meerdere activiteiten hebben. Bij een activiteit hoort een view. Een view is verantwoordelijk voor het zichtbare deel van de activiteit. In deze applicatie wordt de view met de oproep setContentView(R.layout.main) ingesteld. De parameter is een verwijzing naar het bestand main.xml in de res map. De parameter is in een klasseformaat geschreven. Het vastleggen van de view gebeurt in de onCreate() methode. Deze methode maakt deel uit van de afhandeling van gebeurtenissen die met de levenscyclus van de activiteit te maken hebben. Een activiteit kan tot leven komen en kan daarna verdwijnen. Bij elke toestandsovergang hoort een methode. De methode onCreate() wordt gestart wanneer de view van de activiteit zichtbaar wordt. 5 APPI Labo Dit is in grote lijnen de uitleg over de bestanden die voor dit project gegenereerd zijn. De aspecten van Android zijn bij deze beschrijving slechts oppervlakkig uitgelegd. In de latere hoofdstukken zullen een aantal van deze aspecten beter uitgelegd worden. Nu is het tijd voor de compilatie. Dat doe je zo: gradle assembleDebug Met dit commando wordt een debugversie van de applicatie gebouwd. Je vindt het bestand terug als build/outputs/apk/MyFirstApp-debug.apk. Je kan alle bestanden die erbij gekomen zijn door de compilatie opruimen met het volgende commando: gradle clean Je kan een Android applicatie op twee verschillende manieren testen: ofwel gebruik je een GSM of tablet met een USB kabel verbonden met de pc ofwel gebruik je emulatie. Het voordeel van de laatste optie is dat je geen fysiek apparaat nodig hebt maar het nadeel is wel dat emulatie trager is en niet alle periferie (GPS, ...) aan boord heeft. In de volgende stappen gebruiken we emulatie. Hiervoor moet je een zogenaamde AVD aanmaken. Dit is een virtueel apparaat waarvan op voorhand de specificaties zijn vastgelegd. Je kan AVD's aanmaken met het commando android. Start het programma en ga naar Tools/Manage AVDs. In dit scherm kan je nieuwe AVD's aanmaken. In figure_title zie je dat er al twee AVD's zijn gemaakt: avd-nexus-s en avd19. Beide AVD's ondersteunen de zelfde Android versie (4.4.2) maar de eerste heeft geen Google Maps en de tweede heeft dat wel. Afbeelding 1. Overzicht Android devices 6 APPI Labo De AVD naar keuze zou nu kunnen gestart worden met het volgende commando: emulator -avd avd19 Door de specifieke installatie van de Android SDK in het labo is het niet mogelijk om zelf avd's te maken. Daarom wordt er één enkele AVD ter beschikking gesteld die zo gestart kan worden: emulator-nexus4-api25 Op iets oudere PC's schijnt het bovenstaande commando niet te werken. Voor die PC's is er het volgende commando: emulator-nexuss-api19 Als je langere commando's moet intypen, moet je zeker de TAB-toets gebruiken. Type enkele letters van het commando en dan TAB. Hierdoor wordt het commando automatisch uitgebreid. Bij conflicten met je een extra TAB typen; de mogelijke volgende letters worden dan getoond. Je kan met het volgende commando een lijst opvragen van alle Android apparaten die ter beschikking staan. Je ziet nu dat er één AVD in emulatie draait. $ adb devices List of devices attached emulator-5554 device Op deze AVD gaan we de applicatie installeren. Dat gebeurt zo: gradle installDebug Als je de applicatie na een verbetering opnieuw wil installeren, kan je die eventueel eerst verwijderen. gradle uninstallDebug Nu kan je de applicatie starten zoals je ziet in figure_title. 7 APPI Labo Afbeelding 2. De eerste app draait Het kan nodig zijn om de applicatie te verwijderen omdat de AVD onthoudt welke applicaties er geïnstalleerd zijn, ook nadat de emulatie gestopt en herstart is. 8 APPI Labo Tot slot is er nog een commando dat weergeeft welke targets er ter beschikking staan voor ontwikkeling. android list targets Available Android targets: ---------id: 1 or "android-19" Name: Android 4.4.2 Type: Platform API level: 19 Revision: 4 Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, W Tag/ABIs : default/x86, google_apis/x86 ---------id: 2 or "android-25" Name: Android 7.1.1 Type: Platform API level: 25 Revision: 3 Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, W Tag/ABIs : android-tv/x86, android-wear/armeabi-v7a, android-wear/x86, google_a ---------id: 3 or "Google Inc.:Google APIs:19" Name: Google APIs Type: Add-On Vendor: Google Inc. Revision: 20 Description: Android + Google APIs Based on Android 4.4.2 (API level 19) Libraries: * com.android.future.usb.accessory (usb.jar) API for USB Accessories * com.google.android.media.effects (effects.jar) Collection of video effects * com.google.android.maps (maps.jar) API for Google Maps Skins: HVGA, QVGA, WQVGA400, WQVGA432, WSVGA, WVGA800 (default), WVGA854, W Tag/ABIs : no ABIs. In deze listing is de eerste target een basistarget met API android-22 en de derde is een target die gebaseerd is op de eerste met Google Maps als uitbreiding. Als je een app ontwerpt waarin de kaarten van Google Maps worden getoond, dan heb je de derde target nodig. 3.2. Het voorbeeld uitbreiden Het bovenstaande voorbeeld hebben we kant en klaar gekregen. Nu is het tijd voor een kleine oefening. Maak gebruik van een extra bibliotheek om de lokale tijd te tonen. Op de volgende pagina wordt een gelijkaardig voorbeeld uitgelegd. Op het einde van deze pagina wordt uitgelegd hoe je de uitbreiding kan realiseren. • http://spring.io/guides/gs/gradle-android/ De gebruikte bibliotheek is Joda-Time [http://www.joda.org/joda-time/]. De klassen in deze bibliotheek zijn een verbeterde versie van de standaard Java klassen voor tijd en kalender. 9 APPI Labo Om de klassen te kunnen gebruiken hoef je de bibliotheek niet af te halen; het volstaat om de afhankelijkheid te vermelden in het Gradle configuratie bestand build.gradle. Gradle zal dan zelf een download doen om de afhankelijkheid op te lossen. Dit zijn de stappen. Eerst wordt de build.gradle in orde gemaakt. 3.2.1. build.gradle aanpassen Het moet er zo uitzien: buildscript { repositories { jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.3.0' } } apply plugin: 'com.android.application' apply plugin: 'idea' android { compileSdkVersion 'android-25' buildToolsVersion '25.0.2' buildTypes { release { } } } repositories { jcenter() } dependencies { compile 'joda-time:joda-time:2.9.7' } De laatste twee rubrieken zijn nieuw; met repositories wordt aangegeven waar op het Internet afhankelijkheden kunnen afgehaald worden. En in de rubriek dependencies wordt met de regel compile 'joda-time:joda-time:2.9.7' aangegeven dat we jodatime willen gebruiken. Bij een afhankelijkheid moet je de groepsnaam, artifactnaam en het versienummer vermelden. 3.2.2. Aanpassing layout Ook in de layout, beschreven door main.xml, moet je een kleine wijziging aanbrengen. <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView 10 APPI Labo android:id="@+id/text_view" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Hello World, MainActivity" /> </LinearLayout> De TextView heeft nu een id gekregen. Dit is nodig om vanuit Java ernaar te kunnen verwijzen. 3.2.3. Aanpassing Java Tot slot wordt de Java-code ook aangepast. package com.example.myfirstapp; import android.app.Activity; import android.os.Bundle; import android.widget.TextView; import org.joda.time.LocalTime; public class MainActivity extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); } @Override public void onStart() { super.onStart(); LocalTime currentTime = new LocalTime(); TextView textView = (TextView) findViewById(R.id.text_view); textView.setText("The current local time is: " + currentTime); } } Hier zijn extra import's nodig en komt er een extra methode onStart() die automatisch in een latere stap opgeroepen zal worden. In deze methode wordt de tekst van de tijd in de TextView ingesteld. Na al deze aanpassingen kan je compileren en installeren. 3.2.4. Nog een extra uitbreiding Probeer als extra uitbreiding het bijvoegen van een extra TextView element in de layout. Dit element krijgt dan wel een andere id. Met deze tweede TextView kan je ook in de onCreate() methode een tijd tonen. 3.2.5. Logging Probeer ook logging bij te voegen met de volgende oproep: 11 APPI Labo static final public String TAG = "Voorbeeld1"; Log.d(TAG, "een debug melding"); Plaats de TAG constante op klasseniveau. Denk er ook aan om de juiste import te schrijven. Je kan ook een zogenaamde toast tonen. import android.widget.Toast; int aantal = 7; Toast.makeText(getBaseContext(), "aantal " + aantal, Toast.LENGTH_LONG).show(); Meer uitleg staat hier [http://developer.android.com/guide/topics/ui/notifiers/toasts.html]. 4. Een ListView voorbeeld met een eigen dataklasse In deze oefening maken we een aanpassing aan het tekstlijstvoorbeeld zodat er objecten van een eigen klasse in een lijst kunnen weergegeven worden. We willen de informatie over rechthoeken bijhouden. Daarom moet je de klasse Rechthoek maken. 4.1. Voorbereiding Haal het voorbeeld tekstlijst opnieuw af met git clone. Indien het voorbeeld al bestaat en lokaal aangepast is, kan je best de map ervan van naam veranderen. Anders is er een conflict met de mapnamen. $ $ $ $ $ cd gitwerk mv tekstlijst tekstlijst-orig git clone http://eaict.technologiecampusdiepenbeek.be/gitblit/r/android/tekstl mv tekstlijst tekstlijstad cd tekstlijstad 4.2. De Rechthoek klasse Maak het bestand Rechthoek.java in de map src/main/java/be/fiiw/android/ tekstlijst en neem deze inhoud over. package be.fiiw.android.tekstlijst; public class Rechthoek { private double breedte; private double hoogte; public Rechthoek(double b, double h) { breedte = b; hoogte = h; } public double getBreedte() 12 APPI Labo { return breedte; } public double getHoogte() { return hoogte; } public double getOppervlakte() { return breedte * hoogte; } } 4.3. Een layout voor elke rechthoek Voor elke rechthoek willen we de breedte, hoogte en oppervlakte weergeven. Deze layout neemt dat voor zijn rekening. <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="horizontal" android:padding = "10dp"> <TextView android:id="@+id/type" android:layout_width="wrap_content" android:layout_height="fill_parent" android:gravity="center_vertical" android:padding = "10dp"/> <LinearLayout android:layout_width="wrap_content" android:layout_height="fill_parent" android:orientation="vertical" > <TextView android:id="@+id/breedte" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="0.5" android:padding = "10dp"/> <TextView android:id="@+id/hoogte" android:layout_width="wrap_content" android:layout_height="0dp" android:layout_weight="0.5" android:padding = "10dp"/> </LinearLayout> <TextView android:id="@+id/oppervlakte" android:layout_width="wrap_content" android:layout_height="fill_parent" 13 APPI Labo android:gravity="center_vertical" android:padding = "10dp"/> </LinearLayout> 4.4. De aangepaste ArrayAdapter klasse We maken een afgeleide van de ArrayAdapter klasse. Dit is nodig omdat we meer dan een simpele tekst willen weergeven. De klasse RechthoekAdapter zorgt ervoor dat voor elke rechthoek een layoutbeschrijving wordt gegenereerd zodat de breedte, hoogte en oppervlakte elke in een eigen layoutonderdee kunnen weergegeven worden. Neem de volledige inhoud over. package be.fiiw.android.tekstlijst; import import import import import import import android.app.Activity; android.content.Context; android.widget.ArrayAdapter; android.view.LayoutInflater; android.widget.TextView; android.view.View; android.view.ViewGroup; public class { Context int Rechthoek RechthoekAdapter extends ArrayAdapter<Rechthoek> context; layoutResourceId; data[]; public RechthoekAdapter(Context context, int layoutResourceId, Rechthoek[] da { super(context, layoutResourceId, data); this.layoutResourceId = layoutResourceId; this.context = context; this.data = data; } @Override public View getView(int position, View convertView, ViewGroup parent) { View row = convertView; if (row == null) { LayoutInflater inflater = ((Activity)context).getLayoutInflater(); row = inflater.inflate(layoutResourceId, parent, false); TextView TextView TextView TextView tvType tvBreedte tvHoogte tvOppervlakte = = = = (TextView)row.findViewById(R.id.type); (TextView)row.findViewById(R.id.breedte); (TextView)row.findViewById(R.id.hoogte); (TextView)row.findViewById(R.id.oppervlakte); Rechthoek rh = data[position]; tvType.setText("Rechthoek"); tvBreedte.setText("b " + rh.getBreedte()); tvHoogte.setText("h " + rh.getHoogte()); tvOppervlakte.setText("o " + rh.getOppervlakte()); 14 APPI Labo } return row; } } 4.5. Aangepaste MainActivity Pas de huidige MainActivity aan. package be.fiiw.android.tekstlijst; import import import import import import import import import android.app.Activity; android.content.Intent; android.os.Bundle; android.view.View; android.widget.ListView; android.widget.Toast; android.widget.ArrayAdapter; android.widget.AdapterView; android.widget.AdapterView.OnItemClickListener; public class MainActivity extends Activity { static final public String TAG = "tekstlijstad"; static { new new new new new }; final Rechthoek[] rechthoeken = Rechthoek(1, Rechthoek(2, Rechthoek(5, Rechthoek(6, Rechthoek(7, 2), 3), 5), 4), 1) @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); Toast.makeText(getBaseContext(), "#rechthoeken " + rechthoeken.length, Toast.LENGTH_LONG).show(); ArrayAdapter adapter = new RechthoekAdapter(this, R.layout.rechthoekitem, rechthoeken); ListView listview = (ListView) findViewById(R.id.text_list); listview.setAdapter(adapter); listview.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Rechthoek rh = rechthoeken[(int)id]; 15 APPI Labo double b = rh.getBreedte(); double h = rh.getHoogte(); Toast.makeText(getBaseContext(), "rechthoek", Toast.LENGTH_LONG).sho } }); } } 16