Ben Fondu Jeroen Pelsmaekers Nele Schoonheere Mathias Ver Elst
2
Dankwoord Allereerst willen wij Google Inc. bedanken om het voor ons mogelijk te maken applicaties te ontwerpen voor hun besturingssysteem Android. Wij zijn erg dankbaar voor hun handige website voor developers1 waar we gemakkelijk informatie terugvonden. Google’s zoekmachine was uiteraard ook zeer nuttig tijdens onze zoektocht naar informatie telkens we op een probleem stuitten. Een persoon die we zeker willen bedanken is meneer Luc Janssens, onze projectbegeleider. Zijn enthousiasme werkte bijzonder aanstekelijk voor ons en de conversaties met hem via Skype zorgden voor dat extra beetje aanmoediging om er compleet voor te gaan. Graag willen wij ook de medewerkers en leden van de website Stack Overflow2 bedanken. Hier vonden wij bijna altijd de oplossing op de problemen die we tegenkwamen. De goede community en overzichtelijke lay-out op deze site betekenden een echte hulp tijdens de momenten waarop we de wanhoop nabij waren. Een andere website die we willen opnemen in dit dankwoord is Reddit3. Deze website bevat talloze nuttige artikels in de Android-sectie. Deze hebben ons doorheen het jaar erg veel verder geholpen en waren een goede plaats voor geavanceerde topics in verband met Android. We mogen uiteraard ook elkaar, de teamleden, niet vergeten te bedanken. Tijdens deze vier intense weken van samenwerking zijn er warme vriendschappen gegroeid. We hebben met zijn vieren gedurende deze periode 5 dagen per week van 9 uur tot 17 uur samen zitten werken en dit ging bijzonder goed en was bovendien aangenaam werken. We willen ook enkele organisaties bedanken die het voor ons mogelijk maakten om op deze manier te werken. Allereerst de Katholieke Hogeschool Leuven zelf voor het ter beschikking stellen van haar faciliteiten zoals het studielandschap waar we ons elke dag bevonden, daarnaast even aandacht voor De Lijn die ervoor zorgde dat de helft van ons groepje ter plaatse geraakt met minimale vertragingen en de tankstations in de regio Leuven die de rest van het team weer verder hielp. Ook een dankwoordje voor de mensen achter Skype4 die dit handige programma gratis ter beschikking stellen en ervoor zorgden dat we konden communiceren met onze projectbegeleider. Ook het studentenrestaurant Alma en de cafetaria in het departement G&T van de KHLeuven zijn we erg dankbaar. De cafetaria was de plaats waar we elke middag gezamenlijk lunchten en in de Alma verzamelden we elke woensdagavond voor de legendarische spaghetti. Om af te sluiten willen we nog enkele personen bedanken. Naast onze vrienden en families willen we ook Els Bleys bedanken die ons eens gezelschap kwam houden.
INVENTIUM TEAMLEDEN BEN FONDU Contactgegevens JEROEN PELSMAEKERS Contactgegevens NELE SCHOONHEERE Contactgegevens MATHIAS VER ELST Contactgegevens TEAM BUILDING
15 16 16 16 16 16 17 17 17 17 17
FUNCTIONALITEITEN
19
UURROOSTEROVERZICHT AUTO-STILL EN AUTO-VIBRATE MEMO PER VAK WEKKER KHL-STIJL CONFIGURATIE REEKSEN GENEREREN UURROOSTERS
19 20 21 21 22 23 23
FUNDAMENTEN VAN ANDROID
24
WAT IS ANDROID? MANIFEST OPEN HANDSET ALLIANCE ANDROID VERSIES ANDROID MARKET ORACLE VERSUS GOOGLE
24 24 28 28 28 29
5
VOORBEREIDING
30
GROTE ‘MEETING’ WEEK 1 WEEK 2 WEEK 3
30 30 30 31
LAY-OUT
36
DESIGN LOGO ICONEN VOOR HET MENU Icon Design Guidelines ANDERE AFBEELDINGEN Punaise en memoblaadje VERSCHILLENDE SCHERMGROOTTES TABLETS
36 36 37 37 38 38 39 40
DATA GATHERING & SYNC
41
SYNCHRONISATIE TUSSEN ONLINE LESROOSTERS EN DE LOKALE DATABANK BASISWERKING Initiële selectie Synchronisatie LESMANAGEMENT DATABASE
41 41 41 41 42 42
PERMISSIES
43
INTERNET ACCES_NETWORK_STATE MODIFY_AUDIO_SETTINGS CAMERA VIBRATE WRITE_EXTERNAL_STORAGE ACCES_WIFI_STATE UPDATE_DEVICE_STATS CHANGE_WIFI_STATE
43 43 43 43 43 44 44 44 44
NOTIFICATIONS
45
TIJDSINDELING
46
6
VOORUITGANG
47
PROBLEMEN
48
DATA UURROOSTER (1) DATA UURROOSTER (2) SVN REPO (1) SVN REPO (2) UNKNOWN ERROR (17/02) PROBLEMEN MET REGEX VOOR HASH OP TE HALEN PROBLEEM MET HET STARTEN VAN EEN SERVICE (1) PENDINGINTENTS EN BROADCASTRECEIVERS DEBUGGEN VAN BROADCASTRECEIVER PROBLEEM MET ICAL PARSER WEEKVIEW IS TE COMPLEX VOOR ANDROID 1.6 STARTEN ACTIVITY VANUIT SERVICE ONCLICKLISTENER BIJ SPINNER ALARMEN ZETTEN INLEZEN VAN FILENAAM DOOR MIDDEL VAN URI TOEVOEGEN VAN EEN WAARDE AAN DE PROPERTIES ROTATED IMAGES LELIJKE RANDEN OPVRAGEN VAN REEKSEN GEEFT FOUTEN ONVERKLAARBARE FOUTEN (ECLIPSE) DEBUGGEN VAN EEN WIDGET APART GEDRAG JAVA NUMBERPICKER NIET IN SDK ZIEKTE PRIVATE AFBEELDINGEN SKYPE TRAGE OPSTART VAN EMULATOR RUN WIDGET VERSUS DEBUG WIDGET RUN WIDGET VERSUS DEBUG WIDGET (2) APPWIDGET BEVAT GEEN FINDVIEWBYID() REFRESH RATE WIDGET INT EN LONG TIMEDIFFERENCE GREGORIANCALENDAR IS ZERO-BASED PROBLEEM MET TIJDSZONES WIDGETPROBLEEM CHARACTER ENCODING MENSELIJKE FOUTEN
B DISCLAIMERTEKST C VOORBEREIDINGSMAILS MATHIAS – 23 JANUARI 2011 BEN – 24 JANUARI 2011 MATHIAS – 25 JANUARI 2011 NELE – 31 JANUARI 2011 BEN – 31 JANUARI 2011 BEN – 2 FEBRUARI 2011 D ANDROID PROJECT AGENDA E VOORUITGANGSOVERZICHT F KLASSENDIAGRAM PACKAGES KLASSENOVERZICHT KLASSEHIËRARCHIE INTERFACE HIERARCHY G SCREENSHOTS WEEKVIEW DAGVIEW WEEKVIEW MET MENU ALARMMENU ALARMOPTIES SYNC SETTINGS LESSON MANAGEMENT LESSON SOUND PROFILE SETTINGS DISCLAIMER H USE CASE DIAGRAMMEN ANDROID SCREEN KHLROOSTER LESDETAILS ALARM SETTINGS GELUIDSPROFIEL LES GALLERY SCREEN LESSENMANAGER I TICKETS J ANDROIDMANIFEST.XML K CODEVOORBEELDEN ALARM IMPLEMENTATIE SET EN GET PROPERTY PREFERENCES GESTURES IN COMPONENTS LAYOUT STRETCHING OVER VERSCHILLENDE RIJEN TRY FOR SELECTING MUSIC NOTIFICATIONS GEBRUIKEN FORCEER ENCODING L PROPERTIES
M CODE SYNCSERVICE.JAVA ALARMSERVICE.JAVA LESSONEDITORASYNCHELPER.JAVA DAY_VIEW.XML MENU_DAY_VIEW.XML N DATABASESCHEMA
146 146 151 154 158 160 162
11
12
Inleiding Hoe het allemaal begon … Jeroen Pelsmaekers en Mathias Ver Elst kwamen als eersten op het idee om een uurroosterapplicatie te maken voor Android. Dit mede doordat ze allebei over een mobiele telefoon beschikken dat Android als besturingssysteem gebruikt en omdat ze al jaren vonden dat het huidige gebruik van het uurroostersysteem via de portaalsite van de KHLeuven5 een heel stuk eenvoudiger zou kunnen verlopen. Er bestond immers geen ondersteuning voor mensen die zich in een combinatietraject bevinden. Zij moesten de uurroosters van alle reeksen waarin ze lessen volgen opvragen en dit kon een tijdrovende en verwarrende bezigheid zijn voor velen. Mathias en Jeroen besloten dus om deze applicatie te ontwikkelen als eindproject en zochten nog een extra lid om hun team te vervolledigen. Ze spraken enkele andere vrienden aan en vrijwel meteen vonden ze in Ben Fondu en Nele Schoonheere twee zeer geïnteresseerde potentiële teamgenoten. Nadat deze twee nieuwe leden zich bij het team voegden, werd het aanvankelijke idee nog wat verder uitgewerkt en bedachten de teamleden nog wat extra nuttige functionaliteiten zoals bijvoorbeeld het toevoegen van een wekker die automatisch geactiveerd wordt voor de eerste les van de dag begint.
Waarom Android? De laatste jaren zijn smartphones niet meer uit het dagelijkse leven weg te denken. Een heleboel studenten hebben momenteel zo een toestel in hun bezit. Sinds de release van het nieuwe besturingssysteem van Google in 2007 won Android steeds meer en meer aan populariteit. De verkoop van Android telefoons zit nog steeds in de lift en dan vooral bij mensen in de IT-sector. De maanden voor de aanvang van ons projecten hielden we onze medestudenten nauwlettend in de ogen en merkten we op dat een heleboel van hen net zoals ons interesse hadden in Android telefoons en deze dan ook massaal aankochten. Natuurlijk was het onze bedoeling om zoveel mogelijk mensen te bereiken met onze applicatie en daarom leek het ons een goed idee om voor Android te ontwikkelen. Dit in combinatie met het feit dat applicaties voor Android in een zeer erg op Java gelijkende programmeertaal geschreven kunnen worden, zorgde ervoor dat we bijzonder veel interesse hadden om hiervoor een applicatie te ontwerpen. Een ander aspect van Android dat we wel fijn vonden, was het feit dat het een OpenSource project is. Aangezien wij alle vier voorstanders zijn van de OpenSource beweging, sprak dit ons uiteraard ook erg aan.
5
https://portaal.khleuven.be/
13
14
Het team Ons team kende zijn oorsprong bij Mathias Ver Elst en Jeroen Pelsmaekers. Mathias wou dolgraag een Android-applicatie ontwerpen voor het eindproject en Jeroen kwam met het idee op de proppen om de uurroosteropvraging voor mensen met een combinatietraject te vergemakkelijken. Toen Jeroen en Mathias hun ideeën met elkaar bespraken, merkten ze op dat deze eigenlijk zeer goed te combineren zouden zijn. Uurroosters worden immers vaak opgevraagd via smartphones door mensen die op weg zijn naar de les. Jeroen was zo enthousiast over het maken van deze applicatie dat hij zijn ex-klasgenoten Ben Fondu en Nele Schoonheere hierover vertelde. Ook zij toonden interesse voor dit project en al snel werden ze aanvaard als nieuwe teamleden.
Inventium Op de allereerste dag van ons project kwamen we samen in de cafetaria van G&T en vonden we dat we een teamnaam nodig hadden. Het was Mathias die op de proppen kwam met een naam die hij vroeger al eens had gebruikt en deze werd dan lichtelijk aangepast door Ben waardoor ‘Inventium’ ontstond. Hierna ging Mathias meteen aan de slag met het ontwerpen van een logo voor ons team. (Hierover meer informatie in het hoofdstuk ‘Design’.) Het logo representeert de vier leden van ons team met vier i’s (de i van Inventium) of – met wat fantasie – vier op mensen gelijkende figuurtjes. Elk teamlid heeft zijn of haar eigen kleur en dus zijn of haar eigen figuurtje. Zo is Jeroen blauw, Ben groen, Mathias geel en Nele paars. De grootte van de figuren werd bepaald door de werkelijke grootte van de persoon in kwestie.
15
Teamleden Ben Fondu Ben Fondu is het oudste lid van ons team. Hij is de enige die niet over een Android telefoon beschikt, maar was desondanks zeer gemotiveerd om aan dit project mee te werken. Hij nam de taak op zich om een iCal parser te schrijven om aan de data op de portaalsite te geraken vanuit onze applicatie. Ben had nog geen ervaring met Android, maar wel met het erop gelijkende Java. Eén van zijn vele talenten is het maken van hackarounds. Velen kennen Ben omwille van zijn ietwat eigenwijze karakter. Dit is vaak een groot voordeel tijdens het programmeren omdat Ben zijn eigen kijk heeft op de code. Contactgegevens E-mailadres: [email protected] Skype: elbekko Jeroen Pelsmaekers Jeroen Pelsmaekers is een grote Android fanaat. Hij was één van de eersten om een Android-apparaat aan te kopen van zodra dit beschikbaar was in België. Zijn Android-toestel bij voorkeur is een Sony Ericsson XPERIA X106. Jeroen had al een beetje ervaring met het schrijven van Androidapplicaties. Hij had al enkele testapplicaties gemaakt om de SDK van Android te leren kennen. Hij heeft zich onder andere gericht op het maken van services voor de applicaties en ook de widget nam hij voor zijn rekening. Jeroen is gespecialiseerd in het oplossen van mysterieuze problemen en houdt de sfeer in de groep door zijn gevoel voor humor. Contactgegevens E-mailadres: [email protected] Skype: dejerre90
Nele Schoonheere Nele Schoonheere bezit ook een Android mobiele telefoon. Zij koos voor een toestel van Samsung, namelijk de Apollo (GT-I5800)7. Nele had nog geen ervaring met het programmeren voor Android, maar was net als de rest gemotiveerd om zoveel mogelijk bij te leren. Naarmate het project vorderde, kwam Nele in te staan voor het verloop van de communicatie. Zo verliep het wekelijkse contact met de afstudeerproject begeleider grotendeels via haar en werkte ze aan het schrijven van dit verslag. Contactgegevens E-mailadres: [email protected] Skype: neleschoonheere Mathias Ver Elst Mathias Ver Elst heeft zeer erg veel interesse in Android en zowat alles dat ermee te maken heeft. Hij bezig ook een Sony Ericsson XPERIA toestel, maar koos voor de kleinere variant, de X10 Mini Pro8. Mathias had als enige al behoorlijk wat ervaring met programmeren voor Android. Hij had al allerlei zaken uitgeprobeerd en had daardoor al heel wat kennis opgeschaard voor we aan het project begonnen. Mathias is een hardwerkend persoon en door al deze inzet nam hij al gauw het initiatief. Hij werd zo’n beetje als projectleider beschouwd in ons team en was het aanspreekpunt bij problemen met de lay-out. Hij nam ook de meeste designproblemen voor zijn rekening en ontwierp in de beginfase van ons project allerlei schetsen om de lay-out van de applicatie te verduidelijken. Contactgegevens E-mailadres: [email protected] Skype: fyorden Team Building We vonden het als team erg belangrijk om ook eens na de ‘werkuren’ af te spreken. We zorgden er dus voor dat we elke woensdagavond samen gingen gaan eten en daarna nog iets te gaan drinken. Op deze manier konden we eens over iets anders praten dan programmeren en informatica, wat ertoe leidde dat de contacten binnen ons team nog aangenamer verliepen.
Bij wijze van team building en in een poging het onvermijdelijke leed te verzachten gingen we ook in team onze outfits voor de presentatie van dit project uitzoeken, er op deze manier voor zorgend dat we er allemaal op ons paasbest uit zouden zien.
18
Functionaliteiten De dag waarop ons project van start ging, besloten we dat het een goed idee was om de te implementeren functionaliteiten neer te schrijven. Achteraf gezien hebben we ze allemaal kunnen verwezenlijken. Hieronder een overzicht:
Uurroosteroverzicht De allerbelangrijkste functionaliteit van onze applicatie is natuurlijk het geven van een uurroosteroverzicht. Het was voor ons belangrijk dat dit op een gemakkelijke manier vanuit een simpele applicatie kon gebeuren zonder dat de gebruiker naar allerlei verschillende sites moet surfen. We wilden absoluut ondersteuning bieden voor mensen met een combinatietraject die dus lessen volgen in verschillende reeksen. Dit vonden wij redelijk belangrijk aangezien het huidige door de school ter beschikking gesteld systeem hier niet in voorziet. Onze opzet was dat elke student zijn of haar reeksen en lessen kan aanvinken en dat de bijhorende schema’s dan automatisch in de applicatie geplaatst gingen worden. Een ander onderdeel van ons uurroosteroverzicht is de overschakeling tussen dag- en weekview. Op deze manier is het overzichtelijker en gemakkelijker te gebruiken voor de mensen die de applicatie raadplegen. We wilden ook nog een derde manier ter beschikking stellen om de uurroosters te bekijken via onze applicatie, namelijk via een widget dat de gebruiker op zijn of haar home screen kan plaatsen. Dit zorgt ervoor dat de gebruiker niet telkens de applicatie moet openen, maar gewoon de volgende paar uur les kan aflezen vanuit het home screen van de telefoon.
19
Dag- en weekview Nog een onderdeeltje van deze functionaliteit zijn de ingebouwde gestures. Hierdoor kan er naar een volgende dag of week genavigeerd worden door met een vinger over het scherm te sliden.
Auto-still en Auto-vibrate Een extra functionaliteit die we bedacht hebben, ging uit van een probleem dat elke student wel kent: in de les zitten en dan plots opgebeld worden waardoor je ringtone doorheen heel de aula weerklinkt. Om dit op te lossen schreven we code die ervoor moet zorgen dat de mobiele telefoon automatisch op stil of vibrate gezet wordt (naargelang de keuze van de gebruiker) wanneer zijn of haar les aan de gang is. Nadien moeten de instellingen van de telefoon terug naar de normale modus gezet worden.
20
Memo per vak Het leek ons een fijne functionaliteit om memo’s toe te voegen per vak. Vaak wordt er op het einde van de les nog snel iets gezegd en heeft de student geen tijd (of zin) meer om dit neer te schrijven. Dit is waar onze applicatie van pas komt. Door op de toepasselijke les te duwen, kan er een memo toegevoegd worden. Dit werd later uitgebreid met de mogelijkheid om een foto toe te voegen als memo. Misschien op het eerste zicht niet erg nuttig, maar tegenwoordig nemen veel studenten snel een foto van het bord in plaats van de opgave voor een taak over te pennen. Met deze applicatie is het daarna eens zo gemakkelijk om deze foto’s terug te vinden.
Wekker Om het leven van de studenten wat gemakkelijker te maken en hen de moeite te besparen van elke avond hun wekker manueel te moeten instellen, hebben we ervoor gezorgd dat de student enkel moet ingeven hoeveel uren of minuten voor de les begint hij of zij gewekt wil worden en onze applicatie doet de rest. Als extraatjes hebben we ervoor gezorgd dat de student in kwestie zelf kan kiezen met welk geluid hij of zij gewekt wordt. De mogelijkheden zijn het gebruik van het standaard notificatiegeluid van de telefoon, een simpele vibrate, het selecteren van een eigen mediabestand, het selecteren van een stream of het ingeven van een eigen stream.
Hier kan de gebruiker de instellingen voor de wekker instellen.
21
Het instellen van het aantal uren en/of minuten voor de eerste kan hier gebeuren door gebruik te maken van een TimePickerDialog.
In deze spinner staan de opties om te kiezen op welke manier de gebruiker gewekt wilt worden. In het tweede scherm heeft de gebruiker gekozen om een stream te selecteren en moet de gebruiker nu ingeven dewelke hij of zij wilt.
KHL-stijl Iets dat we belangrijk vonden voor onze applicatie was het toepassen van een zogenaamde KHL-stijl. We vonden het een goed idee om een duidelijke associatie te maken met de Katholieke Hogeschool Leuven en onze applicatie zodat de gebruikers meteen een gevoel van vertrouwen krijgen in onze applicatie. We verkregen dit door het logo van de KHLeuven te verwerken in ons programma en door het herkenbare ‘KHLeuven-rood’ te gebruiken als achtergrond met witte tekst erop.
22
Toch wilden we ook ons eigen karakter verwerken in de applicatie dus staken we ook ons logo erin.
Het logo van de Katholieke Hogeschool Leuven in combinatie met ons Inventium-logo.
Configuratie reeksen Een belangrijke functie van onze applicatie is dat een gebruiker gemakkelijk zijn of haar lessenrooster kan samenstellen. Dit gebeurt via het lesson management in onze settings.
Het settings menu.
Genereren uurroosters Een extra functionaliteit die we nog wilden verwezenlijken indien we tijd teveel zouden hebben was het genereren van uurroosters zonder overlappingen voor mensen in combinatietrajecten. Momenteel moeten deze trajecten nog manueel in elkaar gepuzzeld worden door de studenten zelf of de studietrajectbegeleiders. Dit is echter een tijdrovende bezigheid waarvan wij dachten dat het handig zou zijn als dit automatisch zou kunnen verlopen. Spijtig genoeg zijn we hier niet aan toe gekomen en is deze functionaliteit dus niet uitgewerkt.
23
Fundamenten van Android Wat is Android? Android is een OpenSource besturingssysteem voor mobiele apparaten. Android werd in 2005 gekocht door Google Inc. als een niet OpenSource applicatie en is gebaseerd op een aangepaste versie van de Linux-kernel. In 2007 heeft Google Android gereleased als OpenSource framework, gelicensieerd onder de Apache 2.0 licentie. Android is grotendeels gebaseerd op de Java programmeertaal met enkele belangrijke verschillen:
Er wordt niet gecompiled naar .class bestanden, maar naar .dex bestanden. Er wordt niet gewerkt met een Java virtual machine, maar met een Dalvik virtual machine. Android bevat Just In Time Compilation (vanaf versie 2.2).
Voor het opslaan van data wordt gewerkt met het OpenSource databasebeheersysteem SQLite. Voor het opvragen van deze gegevens, kan er gewerkt worden met een beperktere versie van SQL. Android applicaties bestaan uit twee grote delen, namelijk de XML opbouw van de schermen (layout) en de op Java gebaseerde Androidtaal die zorgt voor de achterliggende logica. Hierdoor verkrijgen we een duidelijke scheiding tussen de business logica en de lay-out (Model-View). Doordat we op een mobiel platform werken, moeten er bepaalde taken uitgevoerd worden in de achtergrond. Hiervoor wordt in Android gebruik gemaakt van Services. Deze kunnen uitgevoerd worden zonder de UI thread te blokkeren. Android zorgt voor een goede sandboxing van de applicatie doordat elke applicatie vooraf moet specifiëren welke Permissions de applicatie nodig heeft voor de uitvoer van het programma. Bij de installatie van een applicatie worden deze permissies getoond aan de gebruiker zodat deze kan beslissen of hij of zij deze applicatie wilt installeren op zijn of haar mobiel toestel. Tevens weet hij of zij wat deze applicatie kan aanpassen aan zijn of haar toestel.
Manifest De manifest bevindt zich in de root directory van de applicatie en bevat essentiële informatie over de applicatie op het Androidsysteem. Zonder dit bestand kan de applicatie niet op het systeem uitgevoerd worden. Hier een overzicht van wat de manifest allemaal doet:
Het benoemt de Java package voor de applicatie. De packagenaam dient als een unieke soort van identificatie voor de applicatie. Het beschrijft de componenten van de applicatie, de activities, services, broadcast receivers en content providers waaruit de applicatie bestaat. Het omschrijft de mogelijkheden in componenten per klasse voor de applicatie. Het bepaalt welke processen de applicatie componenten gaan hosten. Het bepaalt welke permissies de applicatie moet hebben zodat er toegang is tot de API en interactie met andere applicaties. Het beschrijft de permissies die andere applicaties nodig hebben om te communiceren met de componenten van de applicatie. Het beschrijft de minimum versie van de Android API die vereist is om de applicatie uit te voeren.
24
Het maakt een lijst van de libraries waarmee de applicatie gekoppeld moet zijn.
Dit is eigenlijk de centrale vertegenwoordiger van de applicatie in Android. Deze declareert alle verschillende permissies, lay-outstijlen, de vereiste versies van Android en de componenten van de applicatie. Deze componenten bestaan dan uit de services, de activities en broadcastreceivers.
Open Handset Alliance In 2007 ontstond de Open Handset Alliance. Dit is een verzameling van een tachtig bedrijven waaronder onder andere Google, Texas Instruments, LG, Samsung Electronics en HTC9. Het doel van deze organisatie is om open standaarden te maken voor alle mobiele apparaten. Op deze manier gaan ze lijnrecht in tegen bedrijven zoals Apple die hun eigen standaarden gebruiken voor eigen apparaten zoals bijvoorbeeld de iPhone.
Android versies Doorheen de tijd zijn er steeds nieuwe versies van Android uitgebracht10. Momenteel is de nieuwste versie 3.0 (Honeycomb) en deze is speciaal uitgebracht voor tablets. Voor mobiele telefoons is versie 2.3.3 (Gingerbread) de laatste versie. Bij elke nieuwe versie van het Android besturingssysteem zijn er uitbreidingen toegevoegd aan het besturingssysteem. Vanaf versie 1.6 (Donut) is het Android besturingssysteem volwassen genoeg bevonden voor het gebruik op mobiele telefoons. Bij de latere versies van het besturingssysteem, zijn er ook door de community gevraagde extra’s aan het besturingssysteem toegevoegd zoals bijvoorbeeld tethering.
Android Market Voor het distribueren van app’s voor het Android besturingssysteem wordt gebruik gemaakt van de door Google beheerde Market. Hierop kan de eindgebruiker betalende of gratis applicaties vinden die hij of zij kan downloaden en installeren op zijn of haar mobiele toestel. Het is tevens mogelijk om te zoeken in verschillende onderverdelingen waaronder:
Games o o o o o o
Arcade & Action Brain Casual Cards & Casino Racing …
9
Voor een volledige lijst van de leden van OHA: http://en.wikipedia.org/wiki/Open_Handset_Alliance#Members 10 Overzicht van de verschillende versies van Android: http://en.wikipedia.org/wiki/Android_version_history
28
Applicaties o Boeken o Business o Communicatie o Media o Nieuws & magazines o Sociaal o …
Naast de Market bestaat er ook de mogelijkheid om applicaties te installeren buiten de Market om, maar hier kan de legaliteit van de app’s niet gegarandeerd worden. App’s voor de Market worden geverifieerd door Google, applicaties geïnstalleerd op andere manieren, zijn mogelijk niet geverifieerd en kunnen mogelijk schadelijke code bevatten.
Oracle versus Google In augustus 2010 heeft Oracle, eigenaar van Java, Google aangeklaagd over een mogelijke patentinbreuk. Volgens Oracle zouden er teveel overeenkomsten zijn tussen het Android besturingssysteem en Oracle’s Javataal. Google’s antwoord op deze aanklacht is: “Android is gebaseerd op Apache Harmony, een clean room implementatie van de Java class libraries en een onafhankelijk ontwikkelde virtuele machine genaamd Dalvik.”
29
Voorbereiding Nog voor ons project van start ging, werden er al enkele e-mails11 heen en weer gestuurd tussen de leden van onze groep om toch een optimale voorbereiding te hebben. Hierin werden allerlei afspraken gemaakt in verband met werkuren, projectmanagement en de algemene aanpak van zaken voor ons project. Al snel werd er een planning opgesteld voor het verloop van ons project. Dit zag er als volgt uit:
Grote ‘meeting’
Met zijn allen rond de tafel gaan zitten om exact vast te leggen welke functionaliteiten ons eindproduct moet bevatten. Dit product opdelen in functionaliteiten (stories). Stories een punt geven qua belangrijkheid. Stories een punt geven qua complexiteit.
Week 1
Educatie. Beginnen met enkele basisfunctionaliteiten, eventueel gebruik makend van pair programming om sneller ingewerkt te geraken met Android.
Dag 1:
Week 2
Dag 2:
herhaling dag 2. …
Dag 5:
11
stand-up meeting aan begin van de dag, wie heeft wat gedaan, problemen bespreken, hulp nodig? als er iemand vast zit met een story => pairen met iemand die denkt dit te kunnen oplossen totdat probleem opgelost is herhaling dag 1.
Dag 3:
kleine meeting aan het begin van de dag, iedereen kiest een story om mee te beginnen (opletten dat er niet teveel overlapping is tussen de gekozen stories!) story beginnen te ontwikkelen eventueel nieuwe story beginnen enz.
herhaling vorige dagen. terugblik op sprint. Welke stories zijn afgewerkt? Waar zit er nog een probleem? Wat moet er nog allemaal gebeuren?
De mails zijn bijgevoegd in bijlage C Voorbereidingsmails.
30
Week 3 Ongeveer hetzelfde als week 2. Naar het eindproduct toewerken en volop aan het verslag beginnen.
Week 4 Naar aflevering toewerken, laatste puntjes afwerken.
Deze planning hebben we vrij goed kunnen naleven. We hebben echter niet gebruik gemaakt van stories en dergelijke, maar zijn gewoon vertrokken van de functionaliteiten. Bij een project als het onze wees dit zichzelf een beetje uit. Wat we wel hebben toegepast is pair programming. We deden dit niet constant, maar samenwerken per twee bleek wel degelijk zijn voordeel te hebben gedurende de start van het project om zo snel mogelijk ingewerkt te geraken en bij het optreden van fouten. Ter voorbereiding hebben we ook tijdens de rustweek enkele tutorials van Android zelf proberen uit te werken. Op deze manier hadden we toch een idee waar we aan begonnen voordat het project zelf begon. Voor we konden beginnen programmeren voor Android, moesten we alles installeren dat nodig is om voor Android te programmeren. Wij gebruikten Eclipse om onze applicatie te ontwikkelen. Hiervoor hadden we Eclipse zelf nodig en moesten we nog een plug-in installeren voor Android. Hierna moesten we nog de SDK downloaden12. Zoals beschreven in de aanvankelijke planning zijn we in het begin met zijn allen rond tafel gaan zitten om exact de functionaliteiten te bespreken. Dit was nodig om ons ervan te verzekeren dat we allemaal hetzelfde idee hadden voor de applicatie. We maakten ook afbeeldingen en schetsen alvorens te beginnen programmeren. Dit om een duidelijk beeld te krijgen van wat we wilden bereiken.
12
Stap-voor-stap tutorial over het voorbereiden van de computer om voor Android te programmeren: http://developer.android.com/sdk/installing.html
Een aanvankelijke schematische voorstelling van hoe de data van de portaalsite naar de applicatie geïmporteerd moeten worden.
33
Schematische voorstelling van hoe alles moet verlopen in verband met het synchroniseren en de netwerken.
Een snelle tekening van hoe het menu eruit moest gaan zien.
34
Een overzicht van wat er in het alarm submenu terecht moest komen.
Overzicht van de nodige opties in de settings.
35
Lay-out Een belangrijk onderwerp van de applicatie is de lay-out. Deze moet helpen om alles overzichtelijk te houden en moet er mede voor zorgen dat onze applicatie professioneel en betrouwbaar oogt.
Design Logo Het logo werd ontworpen door Mathias. Het idee erachter is dat elke ‘i’ een lid van ons team representeert. Deze ‘i’ is niet toevallig ook de ‘i’ van Inventium. Er werd trouwens ook een geanimeerde versie van het logo ontworpen. Het doel was om ons iets meer in het project te kunnen inleven. Daarom is het logo ook rechtstreeks aan onszelf gelinkt. Het logo bestaat uit 4 delen en ons team bestaat uit 4 groepsleden. Ze zijn geordend volgens onze respectievelijke grootte. Het logo gelijkt ook wat op het bekende symbool voor internetbereik. Hiermee wensen we de communicatie tussen ons team en de rest van de wereld weer te geven.
Om dit logo te ontwerpen gebruikte Mathias de OpenSource programma’s Blender13 en MyPaint14. Blender wordt gebruikt om 3D creaties te maken en is beschikbaar voor alle veelgebruikte besturingssystemen. De pilaren zijn van groot naar klein geplaatst volgens een logaritmische curve om een onevenheid te creëren maar toch een herkenbaar patroon te gebruiken. Om de kleuren te kiezen hebben we elk een kleur gekozen die sterk bij ons aanleunde. Dit komt zeer goed overeen met de uiterste kleuren in een kleurenpallet.
Om meer leven aan het logo te geven hebben we een geanimeerde versie gemaakt met het oog om op te vallen maar niet storend te zijn. Natuurlijk kunnen we deze animatie niet op papier zetten en zal dus enkel op de presentatie zichtbaar zijn.
Dit was de eerste schets van het logo. Iconen voor het menu Om de icoontjes voor in het menu te ontwerpen, wilden we het liefst trouw blijven aan de gekende stijl die Android gebruikt in de standaardapplicaties. We konden gebruik maken van vele standaard iconen die ingebouwd zitten in Android, maar bij bepaalde iconen was dit echter niet mogelijk omdat ze privaat en niet publiekelijk gedeeld werden. Hierdoor moesten we bijvoorbeeld voor het klokicoontje in het overzichtsmenu een eigen icon ontwerpen. Op het internet zijn een heel aantal tutorials te vinden die uitleggen hoe je het best een icon creëert voor menu’s. Er zijn ook een heleboel tutorials die zich specifiek richten op het ontwerpen van icons voor Android. Wij volgden enkele stap-voor-stap tutorials uit deze laatste categorie. Hieronder een overzicht van de meest handige guides die we vonden: Icon Design Guidelines15 Deze tutorial op de developer website van Android zelf was bijzonder nuttig. Er wordt een onderscheid gemaakt tussen de verschillende soorten iconen en hierover wordt dan telkens een heleboel informatie gegeven. Dit gaat van standaardgroottes tot tips in verband met de benaming. Wij waren op zoek naar een manier om de menu-iconen gelijkend op die van Android te maken en ook dit vonden we terug op deze website16. Een redelijk groot minpuntje was dat de uitleg in verband met het maken van de iconen niet altijd even gemakkelijk te begrijpen was voor mensen met een niet al te uitgebreide kennis van het gebruik van allerlei design tools.
Do’s and don’ts according to Google. Tutorial for creating an icon for an Android button17 Uiteindelijk gebruikte Mathias de volgende tutorial om zijn icoontjes voor onze applicatie te ontwerpen. Hij koos deze tutorial omwille van de stapsgewijze en gemakkelijk te begrijpen uitleg die erin staat. In combinatie met de duidelijke voorbeelden, zorgde dit ervoor dat het ontwerpen van nieuwe icons vlot verliep. Door deze uitleg na te leven, ontwierp hij de volgende afbeeldingen:
Andere afbeeldingen Punaise en memoblaadje In onze applicatie is een duimspijker terug te vinden wanneer de gebruiker op een les duwt. Ook deze is vakkundig ontworpen door Mathias Ver Elst. De duimspijker werd in 3D ontworpen in het programma Blender.
17
http://www.connorgarvey.com/blog/?p=41
38
Deze punaise werd later aan een memoblaadje toegevoegd waarop de gebruiker tekst kan plaatsen. Hieronder is een afbeelding zichtbaar van het memoblaadje met de duimspijker erop.
Deze afbeeldingen geïntegreerd in de applicatie.
Verschillende schermgroottes We probeerden zoveel mogelijk rekening te houden met het feit dat we aan het programmeren waren voor mobiele toestellen die per definitie vrij compact zijn, maar toch erg verschillend in
39
grootte kunnen zijn. Daarom testten we onze applicatie uit op onze drie eigen Android toestellen die allen een verschillende schermgrootte hebben en zorgden we ervoor dat we de applicatie ook eens runden op de emulator, maar dan met de resolutie van een nieuwe Android tablet. Tablets Na navolging van de iPad verschijnen er tegenwoordig ook steeds meet tablets die Android draaien. We vonden het dus wel eens nuttig om te kijken of onze applicatie ook op zo’n tablet runde. Op de tablet in onze emulator zag onze applicatie er minder goed uit dan op onze smartphones, maar het was nog steeds leesbaar, overzichtelijk en de lay-out bleef goed. Het spijtige was dat er niet optimaal gebruik werd gemaakt van de extra schermruimte die zo’n tablet biedt. Omdat tablets nog niet ingeburgerd zijn in het studentenleven, vonden we het echter niet de moeite waard van hier een heel nieuwe lay-out voor op te bouwen aangezien het huidige resultaat nog redelijk goed is.
KHLRooster op een tablet.
40
Data gathering & sync Dit gedeelte van de applicatie werd vrijwel volledig uitgewerkt door Ben Fondu. Hij schreef zelf een iCal parser die de gegevens uit de op de portaalsite ter beschikking gestelde iCal-files haalde en deze in onze applicatie injecteerde.
Synchronisatie tussen online lesroosters en de lokale databank Basiswerking De sync bestaat uit twee onderdelen: het initiële selecteren en ophalen van lessen, en het periodiek synchroniseren van de uurroosters. Initiële selectie De initiële selectie wordt automatisch opgeroepen de eerste keer dat de applicatie start en kan ook opgeroepen worden vanuit het lesmanagement scherm om extra vakken toe te voegen. Eerst haalt de applicatie een lijst van departementen op van het portaal. Deze lijst wordt aan de gebruiker gepresenteerd in een scrollbare lijst van RadioButtons. Als de gebruiker al één of meerdere vakken in een departement volgt, wordt dit aangeduid door de naam van het departement groen aan te duiden. Om fouten op te vangen waarbij de applicatie gestopt is tijdens het synchroniseren, hebben we de mogelijkheid toegevoegd om de synchronisatie te forceren. Als een van deze departementen wordt geselecteerd, haalt de applicatie een lijst van reeksen in dit departement op. Ook deze worden in een scrollbare lijst van RadioButtons getoond en worden met groene tekst aangeduid als de gebruiker al één of meerdere vakken volgt in een reeks. Bij het selecteren van een reeks wordt eerst de unieke hash opgehaald van het portaal die nodig is voor het ophalen van de iCal file. Deze hash moet opnieuw worden opgevraagd elke keer dat een ander lesrooster wordt opgevraagd. Na het ophalen van deze hash wordt de iCal file opgevraagd. Deze file wordt dan door de iCal parser gehaald, die een lijst van events teruggeeft. Hieruit wordt een lijst van unieke vakken gehaald, die dan aan de gebruiker getoond worden in een scrollbare lijst van CheckBoxes. Deze worden automatisch aangevinkt als de gebruiker het betreffende vak al volgt. Er is een knop om alle vakken aan te duiden, en een knop om de selectie te bewaren. Als er op de knop wordt gedrukt om de selectie te bewaren dan gaat de applicatie de lesuren van de geselecteerde vakken uit de lijst met events halen en geeft deze aan de database door om te inserten. Synchronisatie De synchronisatie kan op 3 manieren worden opgeroepen: bij het opstarten van de GSM, periodiek en langs een menu item. Dit laatste heeft vooral een psychologisch doel, op deze manier is de gebruiker er altijd zeker van dat hij of zij over de laatste versie beschikt. Zolang de synchronisatie bezig is, krijgt het menu item een oranje icoon. Als de synchronisatie faalt, krijgt het menu item een rood icoon. Bij een succesvolle synchronisatie krijgt het menu item het standaard grijze icoon.
41
Eerst wordt een lijst van alle departementen en reeksen opgehaald uit de database, daarna wordt de iCal file voor elk van deze reeksen opgehaald. Op basis van de lessen in de database worden de correcte lessen uit de iCal file gehaald. Alle lesuren in de toekomst worden uit de database verwijderd, en de lesuren uit de iCal file worden ingevoegd.
Lesmanagement Dit is een scherm waar alle gevolgde lessen in getoond worden. Van hieruit is het mogelijk om deze lessen te verwijderen, of nieuwe lessen toe te voegen. Dit scherm bestaat simpelweg uit enkele knoppen om nieuwe lessen toe te voegen en/of te verwijderen. We hielden dit met opzet zo simpel mogelijk om de gebruikers niet te verwarren.
Database De database zorgt voor alle interacties tussen de SQLite database en de applicatie. Vanuit de applicatie worden er nergens directe queries uitgevoerd. Dit maakt het mogelijk om zonder problemen de achterliggende database aan te passen. We hebben in het begin de beslissing genomen om alles in lijsten in het geheugen bij te houden, en tussen deze lijsten en de database te synchroniseren als er iets wordt aangepast.
42
Permissies Androidapplicaties hebben permissies nodig om bepaalde zaken op het toestel te kunnen toevoegen. Bij het installeren van een applicatie via de Android Market, krijgt de gebruiker te zien welke permissies de applicatie in kwestie nodig heeft. Zo kan de gebruiker beslissen of hij/zij deze applicatie wilt draaien op zijn/haar toestel en kritisch nadenken of de applicatie realistisch gezien deze permissies wel nodig heeft en dus al dan niet te vertrouwen is. Hier overlopen we de permissies die we toestonden voor onze KHLRooster applicatie waarbij we ook even kort uitleggen waarom we deze nodig hadden.
INTERNET We hebben deze permissie nodig om de portaalsite te raadplegen en de lesgegevens af te halen en om ervoor te zorgen dat audiostreams afgespeeld kunnen worden als wekker. <uses-permission android:name="android.permission.INTERNET" />
ACCES_NETWORK_STATE De permissie ACCES_NETWORK_STATE zorgt ervoor dat de applicatie gegevens kan opvragen over de netwerken die het toestel gebruikt. We hebben dit nodig voor de sync om te kijken of er een internetverbinding is en of we eventueel de Wi-Fi zelf nog moeten opzetten. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
MODIFY_AUDIO_SETTINGS Deze permissie is nodig om de globale audio-opties aan te passen. Wij gebruiken die in onze applicatie om de modus van de telefoon te veranderen tijdens lessen naar silent of vibrate en nadien weer terug naar de originele setting. <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
CAMERA Wij staan onze gebruikers toe foto’s te maken en deze bij te houden per les. Hiervoor hadden we toegang nodig tot de camera van het toestel. Deze permissie laat dit toe. <uses-permission android:name="android.permission.CAMERA" />
VIBRATE Deze permissie laat ons toe de vibratemodus van het toestel te activeren. Wij gebruiken dit bijvoorbeeld tijdens lessen om ervoor te zorgen dat de lessen niet onderbroken worden door storende beltonen. <uses-permission android:name="android.permission.VIBRATE" />
43
WRITE_EXTERNAL_STORAGE Deze permissie laat toe te schrijven naar externe geheugenruimte. In onze applicatie gebeurt dit bij het opslaan van foto’s bij lessen. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
ACCES_WIFI_STATE De ACCES_WIFI_STATE permissie laat toe dat de Wi-Fi status wordt veranderd. Op deze manier kunnen wij de Wi-Fi opzetten tijdens een sync (indien de gebruiker dit toelaat). <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" >
UPDATE_DEVICE_STATS Hiermee kunnen we de Wi-Fi aan- of uitzetten. Dit is nodig om tijdens onze sync de Wi-Fi op te zetten indien de gebruiker dit toelaat om hierdoor deze sync te versnellen en de gebruiker niet op onnodige kosten te jagen. <uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" >
CHANGE_WIFI_STATE Hiermee kunnen applicaties de Wi-Fi status aanpassen. Dit is nodig om de Wi-Fi status aan te passen tijdens de sync. <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" >
44
Notifications
Notifications worden steeds bijgehouden bij de laatst voltooide les of de les die bezig is. Om te weten wanneer de effectieve notificatie plaatsvindt houden we een timeDifference bij. Dit werd gedaan om de synchronisatie zonder problemen te laten verlopen. Wanneer er nu een sync gebeurt mogen toekomstige lessen zomaar verwijderd worden, deze kunnen toch geen herinneringen hebben staan. Notifications worden in het blauw weergeven wanneer de herinnering gedaan moet worden tegen het weergegeven lesuur. Een notification is een klein systeembericht dat weergeven wordt in de menubalk. Of er zich een bepaald geluid afspeelt is afhankelijk van de gebruikersinstellingen op de gsm zelf.
45
Tijdsindeling We wisten op voorhand dat we met een beperkte werktijd te maken gingen krijgen. Vier weken voor het ontwikkelen van een Android applicatie is niet verschrikkelijk veel, maar we waren er rotsvast van overtuigd dat dit moest lukken indien we een goede planning volgden. We spraken op voorhand af van zoveel mogelijk binnen afgesproken ‘werkuren’ te werken. Dit hield in dat we van maandag tot vrijdag rond half tien afspraken om tegen vijf uur in de namiddag naar huis te gaan. Ons team koos voor deze aanpak in plaats van de eerste weken een beetje te slabakken en dan bij het naderen van de deadline volop in gang te schieten omdat we geloofden dat regelmatige werkuren goed zijn voor het gemoed en het teamwerk zouden vergemakkelijken. Ook leek het ons verstandig om onszelf elke dag wat tijd te gunnen om afstand te nemen van het werk zodat we de volgende dag weer verder konden werken met een nieuwe, frisse blik op de applicatie. Deze tactiek bleek goed te werken voor ons team en dankzij dit schema, gingen we elke ochtend met plezier aan de slag en waren we zelfs een beetje triest toen het einde van het afstudeerproject naderde. Qua inhoudelijke indeling van het afstudeerproject maakten we een kort schema om later min of meer na te volgen. Het begon met een dag intensief vergaderen, dan een weekje educatie en het begin aan basisfunctionaliteiten. De volgende twee weken waren gericht op het volop ontwikkelen van de applicatie terwijl we de laatste week overlieten om alle kleine details bij te schaven en aan het verslag te werken.
46
Vooruitgang Tijdens ons project hielden we bij wat we wanneer maakten. Hierdoor kunnen we gemakkelijk zien waar we hoelang aan bezig zijn geweest. Deze lijst is terug te vinden in bijlage E (vooruitgang). Doordat we gebruik maakten van SVN konden we ook een logs bijhouden van alles wat we updaten doorheen de loop van het project. Dit zorgde ervoor dat we gemakkelijk konden zien wat er veranderd was per versie zodat eventuele nieuwe fouten snel opgespoord konden worden. Ook was het handig om te zien wie met wat bezig was om gemakkelijk hulp te kunnen vragen aan de persoon die een bepaald onderdeel van de code geschreven had. In bijlage A (Timeline) bevindt zich een overzicht van deze updates per dag met een korte beschrijving van de update18. De bijhorende uren zijn niet correct voor onze tijdszone, maar we geven ze toch mee om de tijdsintervallen tussen updates weer te geven. Vaak terugkerende termen in dit overzicht zijn ‘Wikistart’19 en ‘ticket’. We gebruikten deze tickets om weer te geven wat er nog moest gebeuren aan de applicatie.
18
Een uitgebreidere versie van dit overzicht kan gevonden worden op onderstaande website: http://inventium.stringsandints.com/trac/timeline 19 De Wiki van Inventium die we gebruikten voor de meer technische zaken: http://inventium.stringsandints.com/trac/wiki
47
Problemen Doorheen de vier weken dat we aan ons project werkten, hebben we consequent een probleemlog bijgehouden op de wiki van ons project20. Hieronder een overzicht van de hardnekkigste problemen:
Data uurrooster (1) Er is geen eenvoudige webservice die we kunnen aan spreken om aan de uurroosters te raken. Ook toestemming om zelf een service aan te spreken zal niet lukken op korte tijd. We zijn dus aangewezen op de iCal-file die gegenereerd wordt op het portaal. De iCal-file is echter niet rechtstreeks beschikbaar want er is een extra parameter nodig met een hash die volgens ons vrijwel zeker afhankelijk is van het IP en waarschijnlijk ook de datum. Doordat we niet precies weten waaruit deze hash opgesteld is, kunnen we deze momenteel enkel bekomen door eerst de uurroosterpagina te bezoeken en de hash uit te link te halen. Data uurrooster (2) We waren tijdelijk ongerust omdat het leek alsof de iCal-file niet correct gegenereerd werd, wat een groot probleem zou kunnen betekenen, maar later bleek dat automatisch al de weken van het semester gegenereerd worden wat ons even in de war bracht. SVN REPO (1) Na de eerste commits leken er problemen te zijn wanneer de repo geüpdatet werd, dit werd opgelost door de gen/ folder over te slaan. Deze files worden immers automatisch gegenereerd wat voor problemen zorgde. SVN REPO (2) Na een update moet het project vaak ook gecleared worden. We zijn er nog niet achter waarom dit nodig is. Unknown Error (17/02) Op donderdag 17/02 dook er opeens een unknown error op die we niet meteen opgelost kregen. In de onCreate() sloten we namelijk aanvankelijk de connectie, iets dat we blijkbaar niet mochten doen. Na dit aangepast te hebben, verliep alles zoals het moest. Problemen met regex voor hash op te halen De syntax van reguliere expressies in Java is verschillend van die we eerder in onze opleiding geleerd hadden. Dit zorgde voor een heleboel verwarring. Ook waren er problemen met de matcher niet over meerdere lijnen werkt. Er moet dus tijdens het inlezen gekeken worden of we op een lijn zitten waar we weten dat het kan voorkomen (bijvoorbeeld: input.contains("unique")). Het voordeel hieraan is dat dit eigenlijk efficiënter is. 20
De wiki van ons project: https://wikis.khleuven.be/gt_misc/index.php/Jeroen_Pelsmaekers_Nele_Schoonheere_Ben_Fondu_Mathias_V er_Elst#Problemen
48
Probleem met het starten van een service (1) Het op stil zetten van een Android telefoon gebeurt door gebruik te maken van een PendingIntent. Deze wordt opgebouwd door middel van een Intent. Als er gegevens van de Intent veranderen nadat de PendingIntent gemaakt werd, zal de PendingIntent deze aangepaste gegevens niet doorgestuurd krijgen. We hadden dit eerst niet door en hebben grondig moeten debuggen om dit te achterhalen. PendingIntents en BroadcastReceivers Een PendingIntent wordt verzonden naar een BroadcastReceiver in plaats van naar een Service, er moet dus gewerkt worden met een omweg om deze broadcast op te vangen. Hiervoor ontwikkelden we een tussenklasse. Debuggen van BroadcastReceiver Het is zo goed als onmogelijk om een BroadcastReceiver te debuggen met de Android debugger omdat het AndroidOS niet weet wanneer deze Receiver opgeroepen zal worden. Dit maakt het zeer moeilijk voor ons om fouten op te sporen. Probleem met iCal parser De iCal parser die bij het begin van het project gekozen werd, ical4j, blijkt zeer traag te zijn. We vermoeden dat dit is omdat deze intern een zeer uitgebreide datastructuur opbouwt, wat veel geheugen inneemt. Dit is duidelijk in de debugger te zien doordat de garbage collector constant zit te werken. Een mogelijke oplossing voor dit probleem is om zelf een parser te schrijven die minder geheugenintensief is. Dit is de optie die wij gekozen hebben. WeekView is te complex voor Android 1.6 Bij het testen op Android 1.6 ontstaat er een error waaruit ik kan afleiden dat de layoutstructuur te complex is geworden om te kunnen renderen. Het ligt niet aan de schermgrootte of density aangezien hetzelfde toestel met versie 2.1 deze fout niet krijgt. Het probleem is dat oudere versies van Android nog niet overweg konden met een layoutmanager die geen subcomponenten bevat. Deze zijn nu gewoon veranderd naar lege TextViews. Starten Activity vanuit Service Bij het starten van een Activity vanuit een Service, krijgt men de ERROR/AndroidRuntime(2431): Caused by: android.util.AndroidRuntimeException: Calling startActivity() from outside of an Activity context requires the FLAG_ACTIVITY_NEW_TASK flag.
error. Bij de Intent die de Activity opstart, moet de FLAG_ACTIVITY_NEW_TASK flag gezet worden om dit op te lossen.
49
onClickListener bij Spinner Het is niet mogelijk een onClickListener te implementeren bij een Spinner. Er moet gewerkt worden met een onItemSelectedListener21, maar deze mag niet geïmplementeerd worden door gebruik te maken van een anonieme listener. Er moet gewerkt geworden met een dedicated listener. Alarmen zetten Alarmen die ingesteld zijn door de uurroosters, moeten kunnen veranderen als de gebruiker een aanpassing doet aan de settings of als de data die ingelezen wordt van het portaal verandert. Hierdoor moet er gewerkt worden met twee properties en de twee oude waarden hiervan moeten meegegeven worden aan de Intent. Inlezen van filenaam door middel van Uri We wilden een eigen mediabestand als alarm instellen. Het lukte ons om de locatie van het bestand te selecteren maar omwille van gebruiksvriendelijkheid leek het ons wenselijk om ook de bestandsnaam weer te geven aan de gebruiker. Dit bleek echter niet zo makkelijk als we aanvankelijk hadden gedacht. We krijgen slechts de Uri mee bij het selecteren van het bestand. Hiermee moeten we via een query aan het OS vragen wat de filenaam van de file is. Toevoegen van een waarde aan de properties Bij het toevoegen van een waarde aan de properties, moet er een commit uitgevoerd worden. Anders wordt deze nieuwe waarde niet opgeslagen. Hoewel we dit wisten, vergaten we dit erg vaak. Een mogelijke oplossing zou zijn om een methode te schrijven die voor ons de properties wegschrijft. Rotated Images lelijke randen Wanneer een rotationAnimation op een image wordt toegepast kan er geen anti-aliasing uitgevoerd worden om lelijke randen te voorkomen. Een eventuele oplossing is een custom imageView maken die de onDraw overschrijft22, maar dit probleem is niet dringend.
Opvragen van reeksen geeft fouten Bij het opvragen van de reeksen in een departement waar een spatie in voorkomt, werd er een exception geworpen. Eerst dachten we dat dit kwam doordat de spatie in de URL niet correct geëncodeerd werd ('+' ipv '%20'). Na lang zoeken hebben we eindelijk de Uri.encode() functie gevonden in de Android libraries, die dit wel correct deed, maar dat loste het probleem nog niet op.
Na verder debuggen kwamen we tot de vaststelling dat het portaal een redirect header terugstuurde omdat de week moet worden meegegeven. In deze redirect header stond er echter een fout, namelijk dat de spaties niet geëncodeerd worden. De Java HttpClient klasse heeft hier problemen mee, en gaf een exception. Dit probleem hebben we uiteindelijk opgelost door meteen de week mee te geven, om de redirect te vermijden, want we kunnen niet controleren wat de server ons terugstuurt. Onverklaarbare fouten (Eclipse) Af en toe doet Eclipse raar en geeft hij fouten op anders altijd werkende code. Meestal kan hij plots een bepaalde layout-component niet meer terugvinden. Uit ondervinding leerden we dat het beste is om Eclipse gewoon eens te herstarten, het project te cleanen en dan te refreshen. Normaal werkt alles dan weer normaal. Als het dan nog niet lukt, raden we aan om de volgende zaken eens te proberen:
Bij gebruik emulator: de emulator herstarten met de optie om de user-data te wissen. Bij rechtstreeks gebruik op het mobiele toestel: via console met de adb.exe tool in de android-sdk platform-tools het volgende commando proberen: o adb uninstall <projectpackage>
Voorbeeld van een adb uninstall voor ons project. Debuggen van een widget Aangezien een widget op het hoofdscherm draait, krijgt het de rechten van het hoofdscherm23. Indien een toepassing een korte tijd niet meer reageert, wordt deze afgesloten en de debugger gedisconnecteerd. Hierdoor is het dus zeer moeilijk om een widget te debuggen. Dit probleem losten we op door de applicatie op de emulator te laten runnen. De emulator disconnect de debugger niet. Apart gedrag Java Bij het gebruik van een inline if-statement kwam en we een raar gedrag tegen.
tv2.setText(lh.getLesson().getName() + " (" + lh.getLocation()!=null?lh.getLocation().split(" ")[0]:"" + ")"); Deze lijn toont enkel de locatie ipv naam (locatie).
23
Meer uitleg over dit probleem op: http://stackoverflow.com/questions/4626103/debugging-widget-causesanr
51
tv2.setText(lh.getLesson().getName() + " (" + (lh.getLocation()!=null?lh.getLocation().split(" ")[0]:"") + ")"); Bovenstaande lijn heeft extra haakjes rond de if-statement en blijkt wel correct te werken. Op de website Stack Overflow24 hebben we de uitleg ondertussen teruggevonden voor JavaScript. Dit zal waarschijnlijk hetzelfde zijn in Java. NumberPicker niet in SDK Een NumberPicker, een basiscomponent van Android, zit niet standaard in de android SDK. Het probleem is dat de ontwerptools deze widget wel aanbieden als bruikbaar. De applicatie zal dus zonder problemen builden, maar tijdens het gebruik van de component in de applicatie zal dit een crash van de applicatie veroorzaken wat we uiteraard ten zeerste willen vermijden. Een optie was een OpenSource alternatief online te gaan zoeken, maar er is toch gekozen voor de optie om een custom component te maken en dan extra listeners toe te voegen.
Een voorbeeld van de NumberPicker component van Android die we dus niet konden gebruiken in onze applicatie en waarvoor we zelf een component moesten ontwerpen. Ziekte Bij aanvang van onze derde werkweek kregen we te maken met ziekte in ons team. Ben werd ziek en kon dus niet het risico nemen ons allemaal aan te steken en blijf dan maar thuis om daar zoveel mogelijk verder te kunnen werken, ondanks het feit dat hij ziek was. Dit zorgde natuurlijk wel voor een verminderde communicatie en een vermindering in mankracht in ons team. We probeerden dit goed te maken door communicatie te behouden via Skype.
Doorheen de week bleek de ziekte ernstiger te zijn dan we dachten. Ben kreeg de diagnose dat hij Mexicaanse griep had in combinatie met een bacteriële infectie. Hierdoor kon hij een volledige week niet veel werken. Private afbeeldingen Android heeft een heleboel standaard iconen en afbeeldingen ingebouwd die de programmeur rechtstreeks in zijn of haar applicatie kan gebruiken, maar er zijn er ook een aantal die private zijn. Dit zorgt ervoor dat er fouten optreden als de programmeur deze wel probeert te gebruiken. Omwille van deze reden moesten we zelf enkele icoontjes ontwerpen voor onze applicatie. Later in dit verslag bespreken we tutorials en manieren waarop dit gemakkelijk gedaan kan worden. Skype Aanvankelijk ondervonden we enkele communicatieproblemen tussen ons en onze begeleider. Dit had te maken met niet functionerende microfonen en/of webcams. We werkten op onze eigen laptops en sommige daarvan leken het gekozen programma, Skype, helaas niet helemaal goed te ondersteunen. Na deze eerste probleempjes merkten we dat Skype wel goed werkte op de laptop van Nele en dus spraken we af dat hiermee alle Skype-gesprekken gevoerd zouden worden. Dit hield mede in dat Nele ervoor moest zorgen dat ze vrijwel altijd een werkende versie van het project moest hebben staan om dit indien nodig te tonen aan de begeleider. Trage opstart van emulator In het begin van ons project werkten we allemaal op emulators die we draaiden op onze PC’s. Dit had als voordeel dat het gemakkelijk te debuggen was, maar een groot nadeel was het feit dat het opstarten van deze emulator bij velen zeer traag verliep. Vrij snel schakelden de eigenaars van een Android telefoon dus over naar hun eigen gsm om dit proces te versnellen. De snelheid hiervan woog op tegen de bijkomende nadelen zoals bijvoorbeeld het feit dat dit het debuggen een beetje vermoeilijkte. Run widget versus debug widget Een vreemd probleem dat we kregen, had te maken met ons widget. Wanneer we het gewoon runden, wilde het niet van view veranderen. Plaatsten we breakpoints en debugden we echter, dan werkte dit wel. Dit probleem sleepte even aan en we posten zelfs een vraag hierover op de website Stack Overflow25. We losten dit echter op nog voordat we een antwoord ontvingen hierop. De oplossing bestond uiteindelijk uit het oproepen van de setListeners() functie op een extra plaats. We weten tot op heden niet precies waarom dit nodig is bij het gewoon runnen van een applicatie en niet tijdens het debuggen, maar aanvaardden het als ‘één van de vele mysteries van het leven’. Run widget versus debug widget (2) Later tijdens het ontwikkelen van de widget kregen we opnieuw een gelijkaardige fout. We losten dit uiteindelijk op door Thread.sleep() te gebruiken om de widget de tijd te geven up te daten.
AppWidget bevat geen findViewById() Om een knop zichtbaar of onzichtbaar te maken op ons widget, hadden we nood aan het gebruik van de methode findViewById() zoals we die kennen uit Activity-klassen. Bij een AppWidget bestaat deze echter niet. Bij een AppWidget moet er dus gewerkt worden met RemoteViews en de methode setViewVisibility() in plaats van findViewById(). Refresh rate widget Vanaf Android 2.x is de refresh rate van een widget gelimiteerd tot één keer per half uur. Dit vonden wij persoonlijk niet genoeg en dus was het noodzakelijk de AlarmManager in te schakelen om de update om de vijf minuten te laten gebeuren. Int en Long timedifference Voor de notifications werd aanvankelijk een tijdverschil bijgehouden met een int, niemand heeft echter rekening gehouden met een tijdverschil van enkele maanden dus zal dit naar een long veranderd moeten worden. GregorianCalendar is zero-based We waren vergeten dat de GregorianCalendar zero-based was en dus snapten we eerst niet waarom deze klasse ervan uit ging dat er 31 dagen in de maand februari waren. Natuurlijk beseften we even later dat de tweede maand eigenlijk maart is wanneer je werkt met een systeem dat begint op 0, waardoor februari de eerste maand en januari de maand 0 is. Probleem met tijdszones We merkten opeens op dat alle lesuren een uur te vroeg leken te beginnen op ons lessenrooster. Dit kwam doordat ze in de iCal-file in een andere tijdszone. We dachten dat dit automatisch aangepast ging worden, maar dit bleek spijtig genoeg niet het geval te zijn. Widgetprobleem Een probleem met de widget treedt op wanneer het toestel van portrait naar landscape view wordt veranderd door het scherm te kantelen. Bij veel toestellen kan de home screen van het toestel niet in landscape view gezet worden, maar bij enkele toestellen (en bij onze emulator) is deze feature wel mogelijk. Het probleem dat bij deze toestellen dan optreedt, is dat de data van de databank niet in de widget geplaatst wordt na het overschakelen naar landscape orientation. Dit kan wel opgelost worden door op de refresh knop te duwen. We kozen ervoor dit probleem niet op te lossen omdat geen fataal probleem is. De oplossing zou namelijk eruit bestaan om een Service te schrijven die elke keer dat het scherm van orientation verandert, opgeroepen wordt. Dit zou erg batterij-intensief zijn en aangezien we met mobiele toestellen werken, leek dit is een slecht idee te zijn. Character encoding De KHLeuven stuurt alle webpagina’s door met character encoding ISO-8859-1, terwijl Android standaard UTF-8 gebruikt. Dit moesten we dus omzetten bij het inlezen van de lessen wanneer we ze ophalen van de portaalsite.
54
Menselijke fouten Een overgrote meerderheid van de fouten waarmee we af te rekenen kregen, waren van de menselijke aard. Dit waren foutjes zoals simpelweg het vergeten oproepen van de commit()-functie, of zelfs het vergeten schrijven van stukken code. Met het gebruik van SVN kwamen er nog fouten bij zoals het vergeten uploaden van bepaalde files waardoor de rest opeens een heleboel fouten kregen na de update van het project. Menselijke fouten zijn natuurlijk niet te vermijden wanneer men samenwerkt in een team studenten. De manier om ze zo snel mogelijk op te lossen is goede communicatie, gestructureerde code en duidelijke afspraken. We merkten ook op dat twee paar ogen meer zien dan één en vaak is het dus nuttig van iemand anders eens naar de code te laten kijken want deze nieuwe persoon heeft vaak een frissere blik en zal fouten dus sneller opmerken.
55
Gebruikte technieken Model-View Om een applicatie voor Android te ontwikkelen wordt gebruik gemaakt van een combinatie van een taal die zeer erg op Java lijkt en een XML-taal om de lay-out te creëren. Doordat dit in Android ingebakken zit, is een propere scheiding van de business logica (model) en het visuele aspect (view) vrijwel onvermijdelijk. Dankzij dit positieve aspect van Android, konden we een applicatie ontwikkelen die we er volledig anders kunnen laten uitzien door enkel en alleen aan de XML-bestanden van het project dingen te veranderen zonder ons zorgen te moeten maken dat er iets misloopt bij de modelkant van de applicatie. Omgekeerd geldt hetzelfde en daarbovenop hebben we propere code doordat deze twee zaken niet door elkaar gemengd en verspreid over de regels code staan. Dit zorgt voor leesbaardere code die gemakkelijker te onderhouden zal zijn.
Strings file Een andere feature van Android is het bestand waarin alle gebruikte String in geplaatst kunnen worden. Dit is gemakkelijk om achteraf aan te passen en zorgt ervoor dat de applicatie eenvoudig in meerdere talen om te zetten is zonder in de code alles te moeten gaan herschrijven. We maakten hier dan ook optimaal gebruik van.
Design Patterns Template Bij de gestions hebben we gebruik gemaakt van een template design pattern. Deze template liet ons toe om verschillende gestions te beschrijven zonder de basisfuncties steeds te moeten herschrijven die normaal vast zijn. De AbstractGestionListener is de basis voor zowel de UpFlingGestion, DownFlingGestion, RightFlingGestion als de LeftFlingGestion.
Strategy In de AbstractGestionListener is er ook meteen gebruik gemaakt van een strategy-pattern. Op deze manier kan bij de implementatie een naamloze klasse geschreven worden om de actie te omschrijven die uitgevoerd moet worden wanneer de gestion gedetecteerd wordt. De actie wordt dan meegegeven in de overschreven performAction-methode in de naamloze GestionAction die meegegeven wordt in de constructor. Het is dan ook mogelijk om met de setAction-methode van de AbstractGestionListener een andere actie te definiëren om het gedrag at runtime te wijzigen. In het klassendiagram op de volgende pagina is de structuur van deze klassen duidelijk weergegeven.
56
57
Observable Een ietwat complexere implementatie is er ook gebeurd voor het Observable patroon. In onze custom NumberPicker wordt gezorgd dat OnNumberListeners kunnen luisteren naar wijzigingen van de waarde van de NumberPicker. Doordat we ook nog eens een custom-trigger gedrag implementeren in de OnNumberListener kunnen we veel flexibeler controleren in welke situaties we gewaarschuwd worden. Dit kon ook met het originele Observable-patroon maar nu wordt deze check gescheiden van de uit te voeren actie. Hieronder wordt een implementatie getoond van zowel een standaard trigger als een custom trigger. //default trigger month.addOnNumberListener(new OnNumberListener(13) { @Override public void OnNumber() { month.setNumber(1); } }); //custom trigger // This listener will restore the values if an invalid value was detected with checkState() OnNumberListener restore = new OnNumberListener() { @Override public boolean triggerAction(int number) { return !checkState() && !restoring; }; @Override public void OnNumber() { restoreState(); } }; month.addOnNumberListener(restore);
58
Hierboven heeft het android-framework een ingebouwd mechanisme om te kunnen luisteren naar events die zich plaatsvinden buiten de applicatie. Dit zijn broadcastReceivers en worden gedeclareerd in de manifest-file. Bij elke broadcastReceiver moet dan vermeld worden waar hij naar luisterd. Deze wordt dan geactiveerd als het systeem-event plaatsvind zoals bijvoorbeeld een binnenkomende sms. Notify system event
Android system
Broadcast receiver
Register for system event
Singleton Dit is een cruciale pattern voor een eenvoudige werking van Androidapplicaties. Met singleton is het mogelijk om data uit te wisselen tussen verschillende Activities. Er zijn hier natuurlijk meerdere manieren voor maar voor sommige onderdelen zoals de databank en applicatieproperties is dit de meest optimale oplossing. Er is wel blijkbaar een andere oplossing die eventueel had gekund zoals uitgelegd staat op StackOverflow26. Het verschil met het singleton is dat elke Activity/Service zijn context-variabele moet aanspreken om de gedeelde variabelen te gebruiken. Er wordt wel als opmerking gezegd dat dit geen oplossing is om de state bij te houden. Dit is omdat als al de Activities/Services gesloten zijn er geen context meer is en worden de variabelen van de application verwijderd. Dit is eventueel wel mogelijk met onze PropertyManager die met het singleton was geïmplementeerd.
Distributie Er zijn een aantal mogelijkheden om onze applicatie te distribueren zodat het tot bij de studenten van de KHLeuven kan geraken. Tot op heden hebben we nog niet volledig kunnen beslissen wat we precies gaan doen, maar hier toch even een overzicht van onze opties.
Android Market27 De meest voor de hand liggende optie is het ter beschikking stellen van de applicatie via de officiële Market van Android zelf. In deze Market kunnen ontwikkelaars hun applicaties aanbieden aan de Android gebruikers. Hiervoor moet de developer wel akkoord gaan met de terms of use van de Market. Een tweede vereiste is dat de ontwikkelaar zich registreert en hiervoor moet 25 USD betaald worden aan Google. Deze laatste vereiste zit ons een beetje dwars, maar uiteindelijk willen we dit bedrag nog wel financieren als dit betekent dat we de applicatie waar we zo lang aan gewerkt hebben ook degelijk gebruikt gaat worden. Het grote voordeel van de applicatie zo aan de man te brengen, is dat iedereen de applicatie zo gemakkelijk kan downloaden en dat het wat extra betrouwbaar oogt. Google zelf zorgt er bij betalende applicaties voor dat het geld bij de developer terecht komt.
Portaalsite KHLeuven28 Eventueel kunnen we onze applicatie laten verspreiden via de portaalsite van de Katholieke Hogeschool Leuven, de plek waar studenten momenteel hun lessenroosters checken. Dit kan een wat moeilijkere optie zijn omdat we de toestemming en medewerking van de beheerders van deze site hiervoor nodig hebben. Ook zal het waarschijnlijk niet voor alle studenten even duidelijk zijn hoe ze deze applicatie op hun mobiele apparaat kunnen zetten. Wat dan weer wel een voordeel is van deze methode, is dat er geen bijkomende kosten aan verbonden zijn en dat iedereen de applicatie kan vinden.
Zelf verspreiden We kunnen de applicatie ook zelf verspreiden. Er bestaan immers websites waarop men eigen applicaties aan het publiek kan aanbieden. Een groot voordeel is dat we dan zelf de controle behouden over de verspreiding van ons programma en dat dit waarschijnlijk gratis zal zijn. Nadelen zijn dat dit ervoor zorgt dat de applicatie minder gemakkelijk te vinden zal zijn en dat niet iedereen zomaar applicaties vertrouwt die hij of zij op het wereldwijde web vindt.
License Naar het einde van ons project toe, begonnen we verder te denken aan de studenten die eventueel volgend jaar zouden willen verder werken aan onze applicatie om deze dan up-to-date te brengen of te verbeteren indien ze dit zouden zien zitten. We hielden ook rekening met het feit dat onze collega-studenten misschien ook interesse hebben in het hele Android gegeven en het voor hen handig zou zijn om onze code te kunnen inkijken en/of bewerken. Om ervoor te zorgen dat anderen in de toekomst gebruik kunnen maken van onze code, releasten we onze applicatie onder een Creative Commons29 license, namelijk de Creative Commons Attribution-NonCommerical-ShareAlike 3.0 Unported License30. De Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License houdt in dat iedereen vrij is om de applicatie met derden te delen en deze aan te passen, maar dat er wel rekening gehouden moet worden met enkele regels. Zo mag de bestaande code niet gebruikt worden voor commerciële doeleinden en het eindresultaat moet onder eenzelfde licentie vallen als de onze. Deze regels gelden tenzij wij, de makers van de applicatie, specifiek de toestemming geven om hier tegenin te gaan. Om de gebruikers van onze applicatie op de hoogte te brengen van deze door ons gekozen license, hebben wij dit vermeldt in de disclaimer van het programma.
De afbeelding die bij deze license hoort en die terug te vinden is in onze disclaimer.
Documentatie Er werd ons gevraagd om ons project zo goed mogelijk te documenteren doorheen de loop ervan. Dit om toekomstige geïnteresseerde studenten die ook een Android project willen ontwikkelen, of zouden willen voortgaan op het onze, verder te helpen. We hebben dan ook gezorgd voor verschillende manieren van documentatie. Hier verder een overzicht van de manieren waarop we ons project gedocumenteerd hebben.
Verslag Dit verslag is in principe een belangrijke vorm van documentatie. Hierin trachten we de loop van ons project, de structuur en problemen zo duidelijk mogelijk weer te geven, in de hoop dat anderen hieruit kunnen leren. Ter documentatie hebben we bijvoorbeeld ook alle gebruikte links en tutorials bijgevoegd want deze hielpen onszelf heel erg veel verder.
Wiki’s Gelijklopend met het verslag, hielden we ook twee wiki’s bij. Eentje is die dat we van de KHLeuven ter beschikking31 gesteld kregen en de tweede is de wiki van ons project zelf32. Op deze eerste hielden we zo goed als alle informatie bij die in het verslag moest komen.
JavaDoc We hebben onze klassen en methoden zoveel mogelijk gedocumenteerd met JavaDoc. Op deze manier moet het duidelijker worden wat ze doen, welke parameters ze nodig hebben en wanneer ze opgeroepen worden. Dit gebruiken we samen met zo duidelijk mogelijke naamgeving. Nadien hebben we de JavaDoc gegenereerd en het HTML-bestand online ter beschikking gesteld33. Deze JavaDoc zal hier nog een hele tijd blijven staan zodat deze later nog geraadpleegd kan worden door geïnteresseerden in onze applicatie.
Een screenshot van onze gegenereerde JavaDoc pagina.
Een voorbeeld van de JavaDoc van de Utils klasse. Hier zien we de commentaar die we bij de methodes opgaven weergegeven.
63
Detailweergave van een methode uit de Utils klasse. Hierin staat de uitleg over de methode, de parameters en wordt er weergegeven wat voor waarde er terug wordt gegeven.
Inline commentaar Waar de JavaDoc volgens ons niet voor genoeg verduidelijking zorgde, hebben we inline documentatie toegevoegd. Bijvoorbeeld bij complexe methodes vonden we dit soms wel nodig. Dit was niet enkel met het oog op buitenstaanders die onze code zouden willen begrijpen, maar ook voor onze eigen teamgenoten aangezien we vaak met andermans code bezig moesten zijn en dit af en toe vrij moeilijk te begrijpen kon zijn.
64
Testen Het testen van onze applicatie was niet altijd even vanzelfsprekend omwille van een aantal redenen. On te beginnen zaten we natuurlijk met mobiele toestellen die allemaal een klein beetje verschillend werken, over andere specificaties beschikken en alles net een klein beetje anders tonen op het scherm. Soms bleken problemen afhankelijk te zijn per toestel. Een ander probleem dat we hadden bij het testen was dat dingen zoals alarmen en de synchronisatie met de portaalsite heel moeilijk te testen zijn.
Geen JUnit testen We kozen ervoor om geen JUnit testen te schrijven. Hoewel we wel degelijk het nut inzien van het testen van programma’s en beseffen dat dit een ontzettend belangrijk aspect van het programmeren is, vonden we persoonlijk niet dat JUnit tests een grote meerwaarde zouden zijn voor onze KHLRooster applicatie. Zo konden we bijvoorbeeld wel aparte methodes testen op hun correctheid, maar uiteindelijk was de echte functionaliteit, zoals het opvragen van lessen via de portaalsite of het activeren van het alarm, zeer moeilijk testbaar via JUnits. We besloten dus van de tijd die we anders in JUnits zouden steken, te besteden aan het uittesten van de applicatie op de emulators of eigen toestellen. Dit was soms een tijdrovende bezigheid, maar we hebben dit zo goed mogelijk proberen uit te voeren.
65
Disclaimer Aangezien de hoofdfunctionaliteit van onze applicatie het doorgeven van lesuren voor studenten is en dit toch wel een belangrijke zaak is, vonden wij het onze plicht van hen op de hoogte te stellen van het feit dat er altijd iets kan fout gaan met deze data. Dit zou eventueel iets te maken kunnen hebben met een eventuele programmeerfout van ons (hoewel we natuurlijk hopen dat dit niet gebeurd) of met iets dat helemaal buiten onze macht ligt, een herstructurering van het portaal bijvoorbeeld, of iets compleet anders. We zagen ook in dat een misverstand in het gebruik van de wekfunctie gemakkelijk te maken is of dat de gebruiker misschien verward zou kunnen zijn waarom de applicatie uit zichzelf de Wi-Fi connectie van zijn of haar toestel moet kunnen activeren. Om al deze redenen besloten we een disclaimer te schrijven die terug te vinden is in het Settingsmenu onder de optie ‘Disclaimer’. Bijlage B bevat de letterlijke tekst van onze applicatie. Hierin raden we onze gebruikers aan om de gevonden informatie kritisch te bekijken en altijd na te kijken of deze wel correct is. We geven ook uitleg over waarom we de Wi-Fi forceren indien zij deze optie niet uitvinken. We schreven deze tekst in het Engels, rekeninghoudend met eventuele buitenlandse studenten die onze applicatie zouden willen gebruiken. Ook plaatsen we de tekst in een WebView waardoor vanuit de applicatie gesurft kan worden naar de bijhorende links. We hopen dat deze disclaimer het gemakkelijker maakt voor gebruikers om onze applicatie te gebruiken en dat hiermee misverstanden uit de weg gegaan kunnen worden.
Alternatieve methodes Om ons project zo goed mogelijk te testen, was het nodig om zelf zoveel mogelijk met applicatie bezig te zijn. We schreven ons in op allerlei lessen, zetten onze alarmen, wachtten om te kijken of de silentfunctie geactiveerd werd, enzovoorts. Op vlak van de sync-functie testten we ook of de lessen van andere studierichtingen en departementen ook in onze applicatie ingeladen konden worden. Wanneer dit niet lukte, was het tijd om aanpassingen te doen en losten we dit zo snel mogelijk op. Een andere manier die we toepasten, was het uitlenen van onze smartphones aan klasgenoten en familieleden en hen uitdagen om de applicatie kapot te krijgen. We zijn ook een hele tijd bezig geweest met het actief veroorzaken van fouten. Door onze kennis van de applicatie, konden we zelf proberen race-condities te creëeren en checken of dit onze applicatie deed crashen of niet.
66
De toekomst Zoals beschreven in het bovenstaande hoofdstuk, hebben wij al even nagedacht over de toekomst van onze applicatie. Wij zien een aantal mogelijke opties in verband met het onderhoud van de applicatie.
Eigen applicatie KHLeuven Er werd ons bij aanvang van ons project verteld dat de KHLeuven zelf ook ooit een project had opgestart die de opvraging van de lessenroosters moest vergemakkelijken. Dit project werd echter vroegtijdig gepauzeerd. Indien dit project terug hervat zou worden, zal dit mogelijk onze applicatie deels vervangen, hoewel deze de alarmfuncties en dergelijke niet zal ondersteunen.
Zelf het onderhoud van de applicatie doen We kunnen eventueel ook zelf de applicatie een tijdje blijven onderhouden indien dit nodig zou blijken. Dit zal waarschijnlijk echter niet altijd onze hoogste prioriteit krijgen aangezien we binnenkort (hopelijk) afstuderen en dus zelf geen gebruik meer gaan maken van KHLRooster.
De volgende generatie Als er de ontwikkeling van het project van de KHLeuven zelf niet al te snel hervat wordt, kan een groepje geïnteresseerd studenten ons indien gewenst opvolgen. Gedurende de ontwikkeling van onze applicatie probeerden we er rekening mee te houden dat andere informatici onze code misschien achteraf zouden willen uitbreiden of aanpassen. We deden dit specifiek door zoveel mogelijk verduidelijkende commentaar toe te voegen, duidelijke naamgeving toe te passen en onze problemen en dergelijke nauwgezet bij te houden in onder andere dit verslag. Moest iemand deze applicatie willen aanpassen dan is dit ook toegestaan dankzij de licentie die we gekozen hebben om ons programma onder vrij te geven. Meer informatie hierover is terug te vinden in het voorgaand hoofdstuk, genaamd ‘License’ in dit verslag.
67
Persoonlijke reflectie Ben Fondu Ondanks het feit dat ik zelf geen Android toestel heb, was ik zeer geïnteresseerd in dit project. Er lijkt veel toekomst te zitten in mobile development, dus ervaring opdoen in dit veld is zeker en vast nuttig. Het project is zeer vlot verlopen. Dagelijks samenkomen zorgde ervoor dat we elkaar constant konden helpen en vragen stellen, maar ook elkaar beter leerden kennen. Ook buiten de ‘werkuren’ gingen we samen op café of gingen we poolen, wat de teamgeest versterkte. Tijdens het ontwikkelen kwamen we regelmatig problemen tegen, sommige werden gemakkelijk opgelost, anderen waren wat moeilijker. Het grootste obstakel voor mij persoonlijk tijdens het ontwikkelen was dat ik mij nooit kon concentreren op het deel van het project dat ik voor mij had gekozen - het maken van de iCal parser en het synchroniseren van lessen - omdat er regelmatig eerst een layout gemaakt moest worden. Al bij al vond ik het een zeer interessante en toffe ervaring, en ik zal in de toekomst waarschijnlijk nog wel andere applicaties voor Android schrijven.
Jeroen Pelsmaekers Aangezien ik mijn stage in een bedrijf ga doen dat Android applicaties ontwikkelt, vind ik het handig dat ik alreeds wat ervaring heb kunnen vergaren op het gebied van programmatie voor Android. Daarnaast ben ik ook een grote liefhebber van Android toestellen. Ik vond ons team zeer aangenaam om mee samen te werken. Ben, Mathias en Nele waren zeer fijne groepsgenoten. We werkten zeer gezellig samen en ook na het harde werk, gingen we soms eens samen weg om iets te drinken en eten. Dit zorgde voor een fijne teamsfeer. Tijdens het werken werden er ook regelmatig grapjes gemaakt om de sfeer erin te houden. Ik vond het zeer bevredigend om hardnekkige problemen op te lossen die we vaak tegenkwamen. Ik ben van nature een koppig persoon en dit werkte in mijn voordeel doordat ik zo helemaal tot de wortels van het probleem geraakte en het kon oplossen. Ik heb dan ook heel erg veel bijgeleerd tijdens dit project, niet enkel op het vlak van pure kennis van programmeren, maar ook op het vlak van samenwerking.
Nele Schoonheere Bij het begin van dit project verwachtte ik dat dit project in dezelfde lijn zou verlopen als de gemiddelde projecten die ik tijdens mijn opleiding Toegepaste Informatica al eerder deed onder het jaar, maar dan zonder de extra stress van andere vakken, naderende examens en dergelijke meer. Ik merkte echter dat dit al snel anders verliep. Zo pakten we het vanaf het begin goed aan en begon we met het opstellen van plannen en schema’s in plaats van gewoon in het wilde weg aan iets te beginnen. Op deze manier wisten we goed waarmee we bezig waren en vermeden we last minute rampen bij het naderen van de deadline. Door deze goede voorbereiding, konden we gemakkelijk zelfstandig aan iets werken om dit dan later via SVN te delen met de rest van de groep. Na wat initiële probleempjes, bleek dit erg goed te
68
werken. Ondanks het feit dat dit zeer goed ging, kozen we er toch voor om elke dag het Belgisch weer en verkeer te trotseren om samen te komen op het departement Gezondheidszorg en Technologie. Vanaf dag één bakenden we hier ons eigen plekje af, ergens achterin het studielandschap waar we op ons gemak konden zitten zonder al teveel gestoord te worden, maar zonder te moeten inboeten op frisse lucht of licht. Een ander voordeel van elke dag samen te komen met de rest van het team was dat we elkaar konden verder helpen (soms door aan pair programming te doen). Dit soort samenwerking kan natuurlijk twee kanten uit: dit kan zorgen voor goede vriendschappen of het maken van nieuwe vijanden. In het geval van ons team was dit absoluut de eerste optie. Doorheen het project leerden we elkaar allemaal veel beter kennen en dit was zeker een positieve ervaring. We kwamen zelfs zo goed overeen dat we ook na het ‘werk’ tijdens de conventionele werkuren af en toe nog eens iets gingen drinken of eten met het team. Poolen werd dan weer tot onze officiële teamsport uitgeroepen. Een ander sociaal aspect van dit projectwerk was de (vriendschappelijke) rivaliteit met de andere teams. We gingen soms eens op ‘visite’ bij andere groepjes om te kijken hoe ver zij al stonden. Het geven van demonstraties van de applicatie werd ook een soort dagelijkse traditie. We vonden het ook handig om te zien hoeveel vordering de rest al had gemaakt zodat we onszelf indien mogelijk konden bijsturen. Het programmeren op zich verliep ook zeer aangenaam. Hoewel ik aanvankelijk geen ervaring had met het programmeren voor Android of eender welk ander mobiel toestel, leerde ik al snel heel veel bij en maakte ik redelijk wat vorderingen. De functionaliteiten op zich had ik wel wat onderschat. Op het eerste zicht lijkt onze applicatie niet zo heel erg uitgebreid, maar hoe verder we geraakten, hoe meer bugs we tegenkwamen en hoe meer er aangepast moest worden. Het was verbazingwekkend hoeveel werk er in zo een vrij basic applicatie gestoken moet worden om het een beetje deftig te maken. Om te besluiten, dit afstudeerproject verliep buitengewoon aangenaam en er was een mooie balans tussen werk en plezier en het eindproduct mocht er zeker ook zijn!
Mathias Ver Elst Door de loop van de jaren hebben we reeds enkele projectjes uitgewerkt. Steeds opgejaagd door de meerderen deadlines en lessen was het altijd nog tot laat werken om een degelijk werk te tonen. Deze keer hadden voor het eerst de kans om een project gebalanceerd uit te kunnen werken zonder al teveel stress van andere vakken of projecten. Daarom keek ik al heel lang uit naar dit project. In de maanden voor de examens van het 5de semester was ik al hoofdzakelijk bezig met het uitwerken van mijn eigen idee. Android stond hierin centraal en ook al was er weinig vrije tijd, ik stond 100% achter mijn projectidee. Het plan was om een Japanse dictionary te creëren samen met enkele efficiënte drill-programma’s. Er bestaan reeds meerdere gelijkaardige applicaties maar geen enkele heeft een perfecte combinatie van een snelle flow en uitgebreide mogelijkheden. Hier wilde ik verandering in brengen.
69
Het was dan ook ergens spijtig dat ik beter kon overschakelen op een ander project op Android. Dit hield me echter niet tegen om ook hier volop voor te gaan. De ervaring die ik in dit project opdeed kan ik altijd overdragen later als ik mijn eerste idee wil uitwerken. Het nieuwe project was dus een idee van Jeroen die graag de uurrooster van de Katholieke Hogeschool Leuven op zijn gsm had. Hieraan zou dan een automatische wekker gelinkt zijn en de mogelijkheid om met combinatietrajecten te werken. Dit is een idee waar ik in het verleden ook al aan gedacht had en dus vond ik het zeker niet erg hieraan mee te werken. Op het eerste zicht lijkt dit een eenvoudige applicatie. Wat data inlezen en tonen op het scherm met hier rond een alarm. Maar schijn bedriegt, layout voor gsm’s is een stuk geavanceerder en het framework van Android is in geen geval gelijk aan dat van Spring. En als er iets is dat ik reeds snel geleerd heb is dat gebruiksvriendelijkheid alles is bij een gsm-applicatie. Een gebruiker wilt snel een programma installeren en zo snel mogelijk zien waar het toe in staat is. Geen eindeloze menu’s en settings om alles persoonlijk te maken maar een intelligentie applicatie die weet wat de gebruiker wil. Voordat het project begonnen was, had ik eigenlijk maar één doel voor ogen. Dit was om werkuren van de vrije tijd te scheiden om zo altijd fris te kunnen verder werken. Mijn idee van een goede informaticus is door de loop van de tijd licht veranderd. Het is niet iemand die tot uren in de nacht zoekt om al de bugs eruit te halen, maar iemand die gecontroleerd kan plannen en zich kan houden aan tijdslimieten. Over de loop van het hele project is dit ook zeer goed tot punt gekomen. Iedereen was steeds aan het werk tussen 9 en 5 maar hierbuiten konden we steeds rustig naar huis. Het enige spijtige was dat ik thuis geen motivatie meer had om zelf aan eigen projecten of dergelijke te werken maar dit zal hopelijk wel weer terug veranderen. De groepssfeer was ook altijd goed, samen eten, uitgaan en winkelen. Om dit aan de start van het project wat te verbeteren had ik het idee snel een logo en teamnaam te gebruiken wat altijd een gevoel van samenhorigheid geeft. Het samen uitgaan na het werk is een techniek die ook toegepast wordt in Japan waar men niet enkel werkt voor het bedrijf maar werkelijk een deel is van het bedrijf. Elke dag na het werk moet men dan mee samen ergens drinken en eten samen met de baas. In tegenstelling tot deze ietwat geforceerde methode deden wij dit eerder met heel veel plezier. Wat ook opvalt is dat niet enkel de kennis van informatica cruciaal is maar algemene kennis met allerlei programma’s als Blender,Ttrac, SVN, Gimp en Photoshop hebben een grote meerwaarde. Het geeft een goed gevoel dat al die uren van spelen met deze programma’s wel vruchten afwerpen. In de toekomst zal ik later zeker gebruik kunnen maken van de ervaring die ik door de loop van de weken nog heb opgelopen. Android is heden en toekomst en ook al zal dit niet voor eeuwig blijven, momenteel is de vraag naar mobiele ontwikkelaars sterk aan het stijgen. Er wordt wel eens gezegd dat mobiele applicaties de nieuwe dot-com bubble is. Ik kijk dan ook ooit een toekomst waarbij iedereen zijn computer altijd bijheeft als gsm en eenvoudig op monitors aansluit zonder dat overal nog vaste computers zullen geïnstalleerd staan.
70
Zoals gewoonlijk begin ik weer van het onderwerp af te wijken. Als ik nog even nadenk over het project kan ik me nog herinneren dat ik in het begin van het project (net zoals bij al mijn projecten) ik zeer ambitieuze functies wilde implementeren. Zo had ik graag de mogelijkheid om automatisch optimale lessenroosters laten samenstellen wanneer meerdere vakken gevolgd moesten worden. Dit is er natuurlijk nooit van gekomen omdat de meesten dit niet zo zagen zitten. Toch vermelde ik deze functionaliteit keer op keer. Dit zorgt ervoor dat andere functies meestal sneller vordering maken. Naar het einde toe lieten we deze functie dan vallen en viel er een grote druk weg. Dit lijkt natuurlijk op het watervalsysteem maar in tegenstelling tot het watervalsysteem wist ik op voorhand dat deze functionaliteit niet geïmplementeerd zou worden maar enkel als druksysteem gebruikt kon worden. Dit was ook de eerste keer voor mij dat ik actief samen moest programmeren met anderen. Tijdens vorige projecten was dit eerder passief en af en toe code mergen via mail en dergelijke wat dan ook meestal hard tegenviel. Ben had reeds ervaring met Trac en SVN dus konden we dit snel opzetten en gezamenlijk aan dezelfde code werken. Door een SVN te gebruiken, is er iets meer druk om geen code door te sturen die nog errors bevat. Als er fouten in zaten werd het al vrij snel duidelijk wie ervoor verantwoordelijk was. Tot slot wil ik nog even kwijt dat de grootste reden voor het succes van ons project te wijten is aan de controle over de eigen opdracht. Er waren geen wispelturige klanten die alles van vandaag op morgen omdraaien en op zijn kop zetten. Bovendien hadden we ook als één van de weinigen een meisje in het team dat mee bijdraagt tot de veelzijdigheid van het team en een extra balans brengt.
71
Conclusie Na vier weken bloed, zweet en tranen in de ontwikkeling van dit project gestoken te hebben, zijn er een heel aantal conclusies die we hebben kunnen trekken.
Voorbereiding is belangrijk Wij zijn van start gegaan nadat we eerst alle functionaliteiten uitvoerig bespraken en ervoor zorgden dat we met zijn vieren op dezelfde lijn zaten. We zijn van de overtuiging dat ons project een stuk minder vlot gegaan zou hebben als we hier niet eerst tijd voor hadden genomen. We maakten ook schetsen en schema’s om de lay-out zo uniform mogelijk op te stellen. We maakten ook afspraken in verband met naamgeving. Deze twee zaken waren ook een hele hulp naarmate de weken vorderden. De goede voorbereiding van ons project bleek achteraf gezien ook een nuttige vorm van documentatie. Zo kunnen de use case diagrammen en de gemaakte schetsen gebruikt worden om zaken over onze applicatie uit te leggen aan derden.
Communicatie Een aspect van het programmeren dat we als studenten toegepaste informatica weleens over het hoofd durven te zien is communicatie. We merkten echter al snel dat een toename van communicatie binnen ons groepje vrijwel altijd leidde tot een beter eindresultaat. Zo zorgden we ervoor dat we – indien mogelijk – met zijn allen ergens rustig samen konden zitten tijdens het programmeren. Hierdoor konden we elkaar verder helpen bij problemen en eventuele vragen met elkaar bespreken. Ook communicatie naar buitenaf bleek belangrijk te zijn. Zonder websites zoals bijvoorbeeld Stack Overflow34 waar gebruikers elkaars vragen beantwoorden, zou ons project vast en zeker veel moeizamer verlopen zijn.
Groepssfeer Eén van de ergste dingen die je kan tegenkomen als student in een afstudeerproject, is in een groepje terecht komen met medestudenten die lui en/of asociaal zijn. Zowat iedereen heeft al eens moeten samenwerken met mensen die niet gemotiveerd waren of waarmee het niet klikte en kan dus uit eigen ervaring vertellen dat dit niet aangenaam werken is. Uiteindelijk lijdt dan ook het eindproduct hieronder. Bij ons was dit echter absoluut niet het geval. Vanaf de allereerste dag voelden we dat de sfeer in ons team goed zat. Het klikte tussen al de groepsgenoten onderling en ook het samenwerken verliep hierdoor zeer vlot. Om de groepssfeer optimaal te houden gingen we geregeld eens met het team weg na de werkuren zodat we ook eens plezier konden maken en over niet-IT-gerelateerde onderwerpen praten.
34
http://www.stackoverflow.com
72
Mobiele toestellen Het was voor ons allemaal een eerste grondige kennismaking met het programmeren voor Android. Op dit vlak leerden we dus een heleboel bij. Dit betekent niet dat we enkel en alleen specifiek leerden hoe we voor Android konden programmeren, maar ook voor mobiele toestellen in het algemeen. Dit is immers niet helemaal hetzelfde als het maken van normale, voor de PC bestemde programma’s. We moesten leren rekening houden met het feit dat de meeste mobiele toestellen over kleinere schermen beschikken en dat bijvoorbeeld menu’s compacter weergegeven moeten worden om de applicatie gebruiksvriendelijk te houden.
Werkritme Iets belangrijks dat we leerden, was dat het nuttig is om een goed werkritme op te bouwen. De eerste paar dagen hadden enkelen van ons wat moeite met dit ritme te vinden omdat de verleiding groot is om afgeleid te geraken wanneer je Android informatie opzoekt op internet. Het is zeer gemakkelijk om snel even op een lichtelijk relevante link te klikken om dan uiteindelijk ergens compleet anders uit te komen. Gelukkig lukte het ons al snel om geconcentreerd verder te werken tijdens de werkuren en onze tijd nuttig te besteden aan ons project. Dit was waarschijnlijk mede door de lichte tijdsdruk en met de groepsdruk, wetende dat we allemaal afhankelijk waren van elkaars werk en inzet. Een andere zaak die hiermee te maken heeft, is dan weer ongeveer het omgekeerde hiervan. We leerden van andere groepen immers dat het ook niet goed is om te lang door te werken. Zo hoorden we namelijk van een groepje dat ze op het einde van de dag per ongeluk een verkeerd commando intypten omdat ze er niet helemaal meer bij waren door toenemende vermoeidheid waardoor ze heel hun project onbruikbaar maakten en opnieuw moesten beginnen. We merkten dus op dat het nodig is om een gulden middenweg te vinden die de perfect balans tussen werken en ontspanning weergeeft. Wij denken persoonlijk hier redelijk goed in geslaagd te zijn.
Kort samengevat, we hadden een heel fijne tijd tijdens dit afstudeerproject. We hadden veel plezier, maar werkten ook serieus aan deze nuttige applicatie. Moesten we terug kunnen gaan in de tijd dan zouden we allemaal, absoluut terug dezelfde keuzes maken.
De Officiële Android website: http://www.android.com Android Open Source: http://source.android.com Android Market: https://market.android.com Android artikel op Wikipedia (Engelstalig): http://en.wikipedia.org/wiki/Android_%28operating_system%29 Officiële website voor Android Developers: http://developer.android.com Nieuws en forum over Android: http://www.talkandroid.com Android development talk: http://www.androiddevelopmenttalk.com Android Developers Blog: http://android-developers.blogspot.com Android Application Development: http://kronox.org/documentacion/Professional_Android_Application_Development.pdf Android Central: http://www.androidcentral.com Android World (NL): http://www.androidworld.nl Your Android (BE): http://www.yourandroid.be Programmeren voor Android (inleiding): http://www.mobile-internet-device.nl/mid-nieuws/programmeren-voor-google-androidinleiding
Inventium
Onze repo: http://inventium.stringsandints.com/repo Onze trac: http://inventium.stringsandints.com/trac De KHLeuven wiki van ons project: https://wikis.khleuven.be/gt_misc/index.php/Jeroen_Pelsmaekers_Nele_Schoonheere_Ben_ Fondu_Mathias_Ver_Elst#Problemen Tijdsbestedingsvoorstel: https://docs.google.com/document/d/1sdPVlMBkVKGM-CuSni2U3HvdbO819WdylRWCtHiAfE/edit?hl=nl# JavaDoc van ons project: http://inventium.stringsandints.com/javadoc/
74
Hulpbronnen
Stack Overflow: http://stackoverflow.com Ons probleem op Stack Overflow: http://stackoverflow.com/questions/5165841/android-appwidget-does-not-start-servicewhen-ran Common tasks and how to do them in Android: http://developer.android.com/guide/appendix/faq/commontasks.html Start a Service At Boot: http://www.androidcompetencycenter.com/2009/06/start-service-at-boot Informatie over gebruik emulator: http://developer.android.com/guide/developing/tools/emulator.html 10 Tips for Developing Android Apps: http://danroundhill.com/2010/04/02/10-tips-for-developing-android-apps Alle vragen op Stack Overflow met als tag ‘Android’: http://stackoverflow.com/questions/tagged/android Android Developers Mailing List: http://groups.google.com/group/android-developers Android Discuss Mailing List: http://groups.google.com/group/android-discuss Android Security Discussions: http://groups.google.com/group/android-discuss Android Market Help Forum: http://www.google.com/support/forum/p/Android+Market Understanding Google Android Programming Terminology: http://www.brighthub.com/mobile/google-android/articles/26463.aspx Manifest.permission overzicht: http://developer.android.com/reference/android/Manifest.permission.html Hello Android (tutorials): http://www.helloandroid.com/tutorials Software Passion (tutorial): www.softwarepassion.com/android-series-custom-listview-items-and-adapters Google Code Android Bugtracker https://code.google.com/p/android/issues/detail?id=1188 EnvyAndroid http://envyandroid.com/archives/66/slow-android-autocomplete-eclipse-helios-36 Android (de Android community van België): http://www.androids.be
Eclipse (ontwikkelomgeving): http://www.eclipse.org Blender (ontwerp logo): http://www.blender.org Skype (communicatie): http://www.skype.com MyPaint (voorontwerp lay-out): http://mypaint.nl.softonic.com Microsoft Word (tekstverwerking): http://office.microsoft.com/nl-be/word
Design
Menu icon design volgens Android: http://developer.android.com/guide/practices/ui_guidelines/icon_design_menu.html Tutorial for creating an icon for an Android button: http://www.connorgarvey.com/blog/?p=41 Android layout tricks: http://android-developers.blogspot.com/2009/02/android-layout-tricks-1.html Declaring layout: http://www.linuxtopia.org/online_books/android/devguide/guide/topics/ui/declaringlayout.html
Varia
KHLeuven Portaal: https://portaal.khleuven.be KHLeuven: http://www.khleuven.be Rechtstreekse links naar livestreams: http://internetradio.vrt.be/dab/hoeluisteren/pc/help/Links_streams.html Android Dev op Twitter: http://twitter.com/#!/AndroidDev Android Central op Twitter: http://twitter.com/#!/androidcentral 20 Must Have Android Apps for Developers and Designers: http://www.1stwebdesigner.com/freebies/android-apps-developers-designers Open Handset Alliance op Wikipedia: http://en.wikipedia.org/wiki/Open_Handset_Alliance Why Google Chose the Apache Software License Over GPLv2 for Android: http://arstechnica.com/old/content/2007/11/why-google-chose-the-apache-softwarelicense-over-gplv2.ars Unofficial Android Apps: http://android-market.co Android Mod Links: http://www.androidmodlinks.info Google: http://www.google.be
76
iOS 4 versus Android: http://www.portablegear.nl/nieuws/10960/iOS_4_versus_Android_2.2.htm Regendetector Android: http://www.androids.be/android-regendetector-widget Kinepolis applicatie: http://www.androids.be/kinepolis-android-applicatie How to generate JavaDoc with Eclipse: www.mtholyoke.edu/~makazand/generate_javadoc.doc Creating JavaDoc: http://onjava.com/onjava/excerpt/eclipse_chapter2/index1.html
Hardware
Sony Ericsson (mobiele telefoons): http://www.sonyericsson.com/cws/home?cc=nl&lc=nl Samsung Mobile (mobiele telefoon): http://www.samsungmobile.com Dell (laptops): http://www.dell.be Samsung (laptop): http://www.samsung.com HP (laptop): http://www.dell.be Wacom (tekentablet voor schetsen): http://www.wacom.com Logitech (muis): http://www.logitech.com
77
Bijlagen A Timeline Dit is een overzicht van alle onze updates aan onze applicatie. Dit gaat terug vanaf het begin van de ontwikkeling tot helemaal aan het einde. Dit is ook op de volgende link terug te vinden: http://inventium.stringsandints.com/trac/timeline. 03/09/11
03:16 (Jeroen) Inline comment, verwijderen unused imports 02:44 (Nele) Aanpassingen AlarmSettings.java Verslag bijgewerkt. AndroidManifest.xml 02:35 (Ben) Javadoc 02:34 (Ben) Character encoding fixes. 02:24 (Jeroen) Static variabelen op final gezet, mogelijke misrie-fix 02:09 (Jeroen) Javadoc and inline comment for services 01:51 (Mathias) A few smal fixes and some comments 01:05 (Jeroen) Bugfix AlarmService.java en AlarmButtonActivity.java 01:04 WikiStart edited by Mathias 03/08/11 08:21 (Nele) Verslag 08:07 Ticket #17 (Uniforme naamgeving) closed by Ben 08:06 Ticket #16 (Klassenschema) closed by Ben 08:06 Ticket #28 (Genereren uurroosters) closed by Ben: wontfix 08:06 Ticket #11 (Documentatie) closed by Ben 08:06 Ticket #30 (iCal: dubbele lokalen) closed by Ben: invalid 08:02 Ticket #40 (Klasseschema herschalen zodat past op 1 pagina) closed by Ben: fixed 08:01 (Ben) Ticket #40 07:58 (Ben) Changed the colour of that. 07:44 (Ben) Mark lessons in lesson management when not found in last sync. 07:44 (Nele) Verslag 07:39 (Ben) Make it possible for the sync to be forced on in case it's interrupted.
78
07:28 Ticket #40 (Klasseschema herschalen zodat past op 1 pagina) created by Jeroen 07:24 (Ben) More log stuff + a small change in toast strings. 07:22 (Ben) Newly generated Javadoc 07:16 (Ben) Bugfix + cleaning up log messages. 07:07 (Ben) Class selection bugfix. 06:59 (Ben) Error catching. 06:53 Ticket #39 (Refresh screen after sync) closed by Ben: fixed 06:52 (Ben) SyncService now calls back to KHLRooster to refresh. 06:41 (Jeroen) alarmclock_activity.xml Achtergrond ook op rood gezet services worden ... 06:03 (Mathias) Extra methode voor relevante notifications te krijgen getNotifications() 05:58 (Nele) Verslag: heleboel veranderingen waaronder toevoeging persoonlijke ... 05:54 (Jeroen) Notifications worden nu ook gezet tegen de juiste les door middel van de ... 05:50 Ticket #25 (Widget maken voor homescreen) closed by Jeroen: fixed 05:50 Ticket #35 (Services uittesten wanneer uitgevoerd door sync + gegevens uit properties ...) closed by Jeroen: fixed 05:50 Ticket #38 (Notifications moeten nog werkelijk gemaakt worden) closed by Jeroen: fixed 05:32 Ticket #39 (Refresh screen after sync) created by Mathias: Na de sync gewoon eens een intent naar de KhlroosterActivity doen. Volgens … 05:07 (Mathias) Notifications half werkend, moet nu nog een planning-mechanisme in zoals ... 04:57 (Ben) Meer Javadoc + gegenereerde Javadoc 02:42 (Jeroen) Notifications begonnen 02:17 WikiStart edited by Mathias 02:16 (Jeroen) LessonEditor.java: na edit van lessen, ook alarmen ... 01:28 (Ben) Hopefully fixing a timezone issue. 00:31 (Ben) Klassediagram 03/07/11 07:26 (Nele) Verslagaanpassingen voor vandaag. 07:21 (Nele) Verslag bijgevuld + nog wat dingen aangepast aan settings.
79
07:19 Ticket #38 (Notifications moeten nog werkelijk gemaakt worden) created by Mathias: Na elke wijziging van notifications aan de databank moet de … 07:18 (Jeroen) Commentaar geschreven in en bij methodes van Widget.java 07:12 (Mathias) Wat commentaar, fixes in the notifications (again), imports gecleaned. 07:07 Ticket #36 (Dagview automatisch scrollen) closed by Ben: wontfix 07:06 Ticket #37 (Wifi uitzetten na sync) closed by Ben: fixed 07:05 (Ben) Javadoc + code cleanup 06:38 (Jeroen) Utils.java: nieuwe methode om versie OS na te gaan Services: Indien versie ... 06:13 (Ben) Bug fixed 05:54 (Ben) Try enabling wifi before doing initial sync. 05:47 (Jeroen) Database.java bugfix (nullpointer) SyncService.java sync om 12 uur en 23 ... 04:21 (Ben) Sync scheduler fix 04:19 (Jeroen) Widget knop gaat weg bij geen huidige les (bugfix) Util methode om wifi ... 01:25 (Jeroen) Wifi uitschakelen na sync als wifi uitgeschakeld was bij start 01:07 (Ben) Sync fixes 03/06/11 13:49 (Nele) Verslag. 03/05/11 08:54 Ticket #26 (Notification list) closed by Mathias: fixed 03/04/11 06:49 (Ben) More sync stuff 06:49 Ticket #34 (Syncservice detail) closed by Ben: fixed: Should be in [143] 06:18 Ticket #8 (Vakmanagement) closed by Ben: fixed 06:18 Ticket #32 (Date locale lookup) closed by Ben: invalid: Emulator bug 06:17 (Mathias) Fix om widget-activity koppelingen goed te laten verlopen 06:16 Ticket #37 (Wifi uitzetten na sync) created by Jeroen: als de wifi uit stond voor de sync, de wifi terug afzetten voor batterij … 06:15 (Jeroen) Emulator fix (geen wifi) 06:07 (Nele) Lay-out van sound profile settings aangepast. 06:03 (Ben) Sync fully working (hopefully).
80
05:39 (Mathias) Vergeten om add notification action te implementeren voor lessonDetails 05:37 (Jeroen) Services uitgetest met data uit DB. WIdget knop op scherm 2 gezet naar ... 05:17 (Mathias) 04:49 Ticket #36 (Dagview automatisch scrollen) created by Ben: Het dagview automatisch laten scrollen naar de positie van de huidige tijd … 01:50 (Nele) alarmModes => public (Sorry, Jeroen.) 01:41 (Nele) alarmModes aangepast zoals requested door Jeroen. + NullPointerprobleempje? ... 01:04 WikiStart edited by Jeroen 00:19 ( Mathias) Enkele files vergeten te comitten gisteren 03/03/11 07:48 (Ben) Should probably do the sync. Will test it tomorrow, along with some UI ... 07:20 (Mathias) Meeste is nu vertaald Notificaties kloppen nu normaal ... 07:07 (Jeroen) Widget schakelt terug naar scherm 1 indien er geen huidige les meer is ... 07:07 (Nele) Android's fundamenten bijgevuld in verslag (+ andere dingen ... 06:27 Ticket #35 (Services uittesten wanneer uitgevoerd door sync + gegevens uit properties ...) created by Jeroen 06:26 Ticket #7 (Vakselectie) closed by Jeroen: fixed 06:26 Ticket #15 (lijst met opties en preferences) closed by Jeroen: fixed 06:25 Ticket #5 (Menuopties) closed by Jeroen: fixed 06:23 Ticket #34 (Syncservice detail) created by Jeroen: Bij het starten van de AlarmService? moeten er 2 velden meegegeven worden … 06:21 Ticket #21 (Sync laten uitvoeren bij starten android) closed by Jeroen: fixed 06:13 (Jeroen) Aangepast zodat de SyncService? nu ook automatisch start als het OS ... 05:39 (Jeroen) Widget werkt. Update elke 5 minuten. Als er een huidige les is, kan de ... 05:36 (Ben) (De)select all button added to lesson editor. 04:50 (Nele) JavaDoc? toegevoegd + verslag nog wat bijgevuld. 03:26 WikiStart edited by Ben 03:26 WikiStart edited by Ben 03:24 (Ben) Start of SyncService?, already checks for network connection with ...
81
03:12 (Jeroen) Betere versie van de checkInternetConnection methode, geeft int terug met ... 03:08 Ticket #27 (Notification screen) closed by Mathias: fixed 03:08 Ticket #31 (Notification edit screen) closed by Mathias: fixed 03:07 Ticket #10 (Memo) closed by Mathias: fixed: Replying to Ben: > Tekst (64k), mogelijkheid om images in te … 03:06 Ticket #33 (Refactor OnNumberListener) closed by Mathias: fixed 03:05 Ticket #18 (Bijhouden weergeven datum bij draaien) closed by Mathias: fixed 03:04 Ticket #13 (vloeiende overgang dagoverzicht bij wisselen dag + lessen aanpassen voor ...) closed by Mathias: fixed 03:04 Ticket #12 (nadat parsing goed werkt de weer te geven lessen gewoon uit databanke ...) closed by Mathias: fixed 03:02 WikiStart edited by Mathias 02:50 (Jeroen) checkInternetConnection methode aangepast zodat rekening houdt met alle ... 02:32 (Mathias) 03/02/11 07:19 (Ben) Widget gefixed. Suggesties: een manier om aan te geven dat de getoonde ... 07:01 (Nele) Verslag bijgewerkt. Nu: inhoudsopgave, probleem opgelost, license, ... 06:15 (Ben) Lots of small changes, error handling, ... 06:03 WikiStart edited by Mathias 05:32 (Jeroen) Probleem met widget opgelost. Klein nieuwe probleem: toont bij instellen ... 05:17 (Ben) A bit of grammar nazi-ing. 05:07 (Nele) Begin van de disclaimer gemaakt. Gekoppeld aan het settingsmenu. 03:53 (Ben) Month is apparently 0-based in gregoriancalendar... 03:21 (Ben) Correctly saves the lessons now. Also played with the date stuff a bit, ... 02:01 (Ben) Lessen zouden nu correct moeten worden ingelezen bij lesson management. 03/01/11 13:26 (Nele) Verslag aangevuld: extra problemen toegevoegd & extra afbeeldingen ivm ... 07:24 (Nele) Verslag: distributie. 07:05 (Jeroen) Stubs gemaakt voor refactoring NumberPicker. 06:59 ( Nele) Verslag: probleem toegevoegd.
82
06:55 (Mathias) 06:34 Ticket #33 (Refactor OnNumberListener) created by Mathias: Momenteel is er een eenvoudige OnNumberListener. Dit kan eventueel later … 06:32 (Nele) Settings aangepast. Verslag gecommit + afbeeldingen. 06:24 (Jeroen) Cleanup van services. Commentaar geschreven bij nieuw toegevoegde ... 05:59 (Mathias) Fix getCurrentAndNextLessonHour Implementing NumberListenerr? into Custom ... 05:30 (Jeroen)Widget werkt nu ook met data uit database. Methode bij database toegevoegd ... 04:08 (Mathias) Edit, save, cancel memo begin met de notificationlist 03:42 WikiStart edited by Nele 03:39 (Nele) Wrap rond kolom naam in lesson_management.xml 03:24 (Jeroen) Widget kan wisselen tussen 2 schermen. Start activities bij klik op ... 02:23 (Nele) Vervolg settings. 01:14 WikiStart edited by Nele 02/28/11 13:23 (Jeroen) File voor widgets vergeten toe te voegen. 07:50 (Jeroen) Dingen aangepast aan widget. Error bij verwisselen van scherm 2 naar ... 07:31 (Mathias) Enkele kleine fixes. 07:16 (Mathias) Heel wat documentatie en widget kan via detailsActivity de camera nu ... 06:42 (Ben) Should be the biggest part of the initial sync. Needs some more work, like ... 05:09 (Jeroen) Static variabelen toegekend aan actions voor widget. 05:00 Ticket #32 (Date locale lookup) created by Ben: Investigate possible fixes for the immensely slow lookup of locales. 04:25 (Mathias) Should be the final fix for camera. 04:07 (Mathias) Fix 2 camera 03:49 (Mathias) Possible camera fix, need to test on other device. 03:04 (Jeroen) Widgetscreens aangepast. Icoontjes toegevoegd. 01:47 (Mathias) 01:41 Ticket #31 (Notification edit screen) created by Nele: Notificaties (achteraf) aan kunnen passen.
83
01:39 Ticket #30 (iCal: dubbele lokalen) created by Nele: Nakijken of er problemen zijn als er twee lokalen toegewezen zijn. 01:35 Ticket #9 (Lesson, Day, Week and notes class) closed by Nele: fixed 01:34 Ticket #1 (iCal parser en inlezen van lesroosters) closed by Nele: fixed 01:31 Ticket #29 (Verslag schrijven) created by Nele 01:31 Ticket #28 (Genereren uurroosters) created by Mathias 01:30 Ticket #27 (Notification screen) created by Mathias 01:28 Ticket #26 (Notification list) created by Mathias 01:04 (Jeroen) widget.xml verwijderd, niet meer nodig. 02/27/11 15:10 (Mathias) Klokje voor widget 14:33 (Mathias) Verbetering image-gallery. Enkele reële lessen in de databank gezet om te ... 02/25/11 06:28 (Nele) Verder gewerkt aan sound profile menu. 06:27 (Jeroen) Widget aangepast. Knop om te veranderen tussen screens gezet. Autoresize ... 06:24 (Ben) More lesson management, almost at the saving it to the DB bit. 06:13 WikiStart edited by Nele 06:03 (Jeroen) widget toegevoegd. Begonnen aan tweede scherm van widgets. Widget ook ... 06:02 (Jeroen) Images voor switchen tussen schermen widget toegevoegd. 02:29 WikiStart edited by Ben 02:27 Ticket #25 (Widget maken voor homescreen) created by Jeroen: Widget dat bestaat uit 2 onderdelen: - Huidige les - volgende les + … 02:24 Ticket #20 (Check Properties on startup launch activity) closed by Jeroen: fixed 01:50 (Jeroen) Bugfix aan AlarmSettings?.java Case 2: default waarde uit properties moet ... 01:46 WikiStart edited by Nele 01:27 (Nele) Settings menu. 01:05 Ticket #3 (Auto vibrate) closed by Jeroen: fixed 01:05 Ticket #22 (Custom media selecteren) closed by Jeroen: fixed 00:54 (Mathias)
84
02/24/11 07:29 (Ben) Further work on the LessonEditor?. Added utils for URL encoding and ... 07:26 (Jeroen) Services geschreven: vibrate voor Lesson Service voor inschakelen ... 06:16 WikiStart edited by Jeroen 05:37 (Mathias) Kleine fix om de photoLinks naar de database te schrijven en ze uit te ... 05:19 (Ben) Better date for example 05:11 (Mathias) Kleine fix voor database 05:01 (Mathias) Mogelijkheid om foto's toe te voegen aan notities voor een lesuur. Deze ... 03:05 Ticket #24 (Meerdere woonplaatsen) closed by Nele: invalid 03:02 Ticket #24 (Meerdere woonplaatsen) created by Nele: Alarm moet ondersteuning bieden voor meerdere woonplaatsen (verschillende … 02:08 (Nele) AlarmSettings.java: probleem opgelost met select ... 01:55 Ticket #23 (Status van Ringer van OS uitlezen en in prop zetten) closed by Jeroen: fixed 01:37 WikiStart edited by Jeroen 02/23/11 11:38 (Jeroen) Aanpassingen aan services. Gestandardiseerde naamgeving voor properties. 07:24 Ticket #4 (Detailweergave les) closed by Ben: fixed 07:23 Ticket #6 (Dagweergave) closed by Ben: fixed 07:20 Ticket #23 (Status van Ringer van OS uitlezen en in prop zetten) created by Jeroen: Bij het switchen naar een andere RingerMode? moet de huidige status … 07:18 (Ben) Added class selection screen to lesson editor. 07:12 WikiStart edited by Jeroen 06:55 WikiStart edited by Jeroen 06:54 WikiStart edited by Jeroen 06:39 (Nele) Alarm settings verder aangepast. 06:08 (Ben) Die in a fire SVN 06:05 (Ben) Lesson Management. Also includes the removal of a few @Override ... 04:56 (Nele) Verder menu-aanpassingen: - enter custom stream - pick existing stream - ... 02:31 (Nele) Verdere aanpassingen aan AlarmSettings?.java: - Select stream: ...
85
02:11 (Ben) Database fixes + starting lesson management. 01:50 (Mathias) Extra ArrayList?<String> in lessenhour om links naar foto's bij te houden ... 00:57 (Mathias) Verwijderd van camera.xml, kunnen beter build-in camera programma's ... 00:54 (Mathias) Animaties bij overgang Fix voor uurselector bij dagoverview start van ... 02/22/11 13:21 (Ben) Hopefully ignoring /bin/ again. 11:26 (Jeroen) Paar aanpassingen aan services. Wekker van telefoon kan ook op vibrate ... 07:41 WikiStart edited by Mathias 07:33 Ticket #22 (Custom media selecteren) created by Nele: Bij de alarm settings de custom media laten selecteren. 04:05 (Jeroen) Javadoc geschreven voor Services. 04:04 (Nele) Menu. 02:17 (Jeroen) AlarmClockService?.java zorgt er nu ook voor dat de alarmen die al gezet ... 01:04 Ticket #21 (Sync laten uitvoeren bij starten android) created by Jeroen: Bij het herstarten van het OS worden alle alarmen die gezet zijn, … 00:49 (Mathias) Verwijderen verkeerde event_week_view.png 02/21/11 07:29 (Jeroen) Alarm uitschakelen via knop en via accelerometer. Clock toegevoegd aan ... 07:28 (Nele) Menu + AlarmSettings? 07:26 (Ben) Cleanup. 07:20 (Mathias) Weekcalendar is geupdate en kan nu lessen tonen en een selector om het uur ... 05:19 (Jeroen) AlarmService?.java geimplementeerd. Alarm zal gezet worden ... uur voor ... 02:26 (Mathias) Sync animation + week_current_hour_selector (nog wel ffjes aanpassen voor ... 02:17 Ticket #20 (Check Properties on startup launch activity) created by Mathias: default waarden zetten indien nog niet geset. 01:50 Ticket #19 (Code cleanup) created by Ben: Debug messages weghalen, testdata uit de onCreate van de database halen, … 01:48 (Ben) Testdata bij onCreate van DB: niet vergeten verwijderen. 01:40 DatabaseSchema edited by Ben 01:40 Ticket #14 (Locatie is verkeerd bijgehouden) closed by Ben: fixed
86
01:39 (Ben) Fixed ticket #14 00:19 (Mathias) Vergeten de files mee te uploaden dom dom... 02/20/11 12:11 (Mathias) Grote update: Implementatie van weekview met gestures en gegenereerde ... 08:47 WikiStart edited by Mathias 06:02 Ticket #18 (Bijhouden weergeven datum bij draaien) created by Mathias: Als de applicatie afsluit moet hierna wel de huidige week weergeven worden … 03:13 Ticket #17 (Uniforme naamgeving) created by Mathias: Door de tijd heen heb ik af en toe verkeerde formaten gebruikt voor … 02/19/11 18:22 (Ben) Wrote my own parser and made it about 37 times faster than iCal4j. Also ... 00:39 (Nele) Begin van menu gemaakt. 02/18/11 13:25 Ticket #16 (Klassenschema) created by Mathias 13:19 Ticket #15 (lijst met opties en preferences) created by Mathias: Dit wordt vanuit het menu opgeroepen en is een overzicht van al de … 13:17 Ticket #14 (Locatie is verkeerd bijgehouden) created by Mathias: De locatie is blijkbaar bijgehouden bij de les in de plaats van het … 13:15 Ticket #13 (vloeiende overgang dagoverzicht bij wisselen dag + lessen aanpassen voor ...) created by Mathias: Een plotse overgang geeft een slecht gevoel bij de gebruiker. 13:12 Ticket #12 (nadat parsing goed werkt de weer te geven lessen gewoon uit databank ...) created by Mathias: Dit is enkele lijnen code uit commentaar zetten maar tijdelijk voor … 13:09 WikiStart edited by Mathias 12:38 WikiStart edited by Mathias 08:00 Milestone Week 1 completed 06:55 (Ben) Ticket #1: iCal parser 06:42 (Jeroen) Kleine bugfix op SilenceService?.java AlarmClockService?.java toegevoegd aan ... 04:44 (Mathias) Fix manifest. 04:41 (Mathias) Refactoring van de layout naar een custom control. Start van ... 03:09 Ticket #2 (Silencer Service) closed by Jeroen: fixed 02:03 (Jeroen) SilenceService?.java werkt volledig. Gebruiker krijgt toastMessage als ...
87
02/17/11 08:06 (Jeroen) Services werken gedeeltelijk. VIBRATE_ON werkt, niet doorgegeven via ... 07:47 (Mathias) Oplossen landscape + herschreven berekeningen schermweergave voor meerdere ... 07:44 (Mathias) 05:45 (Jeroen) Database parsing voor opslaan geupdated. 05:25 (Ben) Database date fix 05:20 (Nele) Wat JavaDoc toegevoegd. 02:56 (Ben) Database stuffses 02:44 (Mathias) 02:33 (Nele) Argh. 00:13 WikiStart edited by Mathias 02/16/11 08:00 (Ben) Database fixes 07:44 (Mathias) Automatische berekening van cursor met huidige uur aangepast op ... 07:12 (Mathias) Solve error: verkeerde verwijzing van resource-file + manifest de juiste ... 06:31 (Mathias) 06:30 (Ben) More DB stuff 06:29 (Mathias) Detailview wordt nu gegenereerd in KHLrooster (Activity) Er moet nog ... 06:19 (Ben) Further DB improvements 05:49 (Ben) Database sync method + model classes corrected 05:15 (Nele) LessonHour timeStamp verandert naar Gregoriancalendar 05:14 WikiStart edited by Mathias 05:13 WikiStart edited by Mathias 04:33 (Jeroen) AndroidManifest.xml aangepast zodat geen titel AndroidManifest.xml ... 04:22 WikiStart edited by Nele 04:19 (Nele) JavaDoc toegevoegd. 03:52 (Ben) Code cleanup 03:50 (Jeroen) Method stubs in database/Database.java gemaakt
88
03:49 Ticket #11 (Documentatie) created by Ben: Javadoc van alles 02:56 (Mathias) day_view.xml toegevoegd samen met enkele wijzigingen aan ... 02:53 (Ben) Database klasses - voorlopig alleen nog maar insert functies. 02:10 DatabaseSchema edited by Ben 00:55 (Mathias) 00:46 (Ben) iCal parser libraries added. 00:40 (Mathias) 00:13 DatabaseSchema created by Ben 00:12 WikiStart edited by Ben 02/15/11 07:12 (Mathias) Hopelijk dat de basis nu deftig werkt :-) 06:56 (Ben) 04:50 (Ben) 04:45 Ticket #10 (Memo) created by Ben: Tekst (64k), mogelijkheid om images in te voeren (image tags?). 04:44 (Mathias) 04:44 (Mathias) 04:30 (Mathias) Activity LessonDetail? toegevoegd in de manifest.xml 04:21 (Mathias) Eerste basis, detailscherm voor een les. 04:20 Ticket #9 (Lesson, Day, Week and notes class) created by Mathias: Klassen om tijdes het runnen van het programma de gegevens in geheugen … 04:16 Ticket #8 (Vakmanagement) created by Ben: Vakken verwijderen uit de lijst met te volgen vakken. 04:16 Ticket #7 (Vakselectie) created by Ben: Vakselectie op basis van ingelezen lijsten. Verticale lijst met … 04:15 Ticket #6 (Dagweergave) created by Mathias 04:14 Ticket #5 (Menuopties) created by Jeroen: Menu aanmaken voor opties aan te passen 04:12 Ticket #4 (Detailweergave les) created by Mathias 04:11 Ticket #3 (Auto vibrate) created by Jeroen: Vibrate ... min voor les
89
04:09 Ticket #2 (Silencer Service) created by Jeroen: Auto silence ... min voor les 01:03 Ticket #1 (iCal parser en inlezen van lesroosters) created by Ben: iCal parser en inlezen van lesroosters 01:02 WikiStart edited by Ben 02/14/11 11:44 WikiStart edited by Ben: Blijkbaar moet het sterreke van de lijst er een spatie voor hebben. 06:38 WikiStart edited by Ben 06:35 WikiStart edited by Ben 06:31 WikiStart edited by Ben 06:26 (Mathias)
90
B Disclaimertekst Hier volgt de letterlijke tekst zoals die terug te vinden is in onze applicatie. Disclaimer KHLRooster is an Android application made by Ben Fondu, Jeroen Pelsmaekers, Nele Schoonheere and Mathias Ver Elst; also known as 'The Inventium Team'. This app's purpose is to enable KHLeuven students to easily access their class schedules by using their mobile Android devices. By setting the alarm, this application automatically wakes you up before your first class of the day. You can also take notes and pictures and save them per lesson. By using this application you automatically agree to these terms of use. KHLRooster by Inventium is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. When synchronizing with the website KHLeuven Portaal we can enable your Wi-Fi for you if you turned it off. If you do not want this to happen automatically, you can change the corresponding setting under 'Settings' in the menu. Application malfunctions are possible, this may be due to a programming mistake, a bug, or something else entirely, so we ask you to always double check the information we give you through this app. By using this application you agree that the Inventium Team is not responsible or liable in case your alarm doesn't go off, for faulty information or damage caused to your device.
91
C Voorbereidingsmails Hierbij de mails die we naar elkaar stuurden ter voorbereiding van ons afstudeerproject.
Mathias – 23 januari 2011 Hey Aangezien de examens stilaan eindigen, is het misschien goed al eens na te denken over hoe we beste ons project kunnen aanpakken. Ik denk dat het best is dat iedereen de eerste dag (7 februari) voorstelt hoe hij/zij denkt dat een goede manier is. Een kleine PowerPoint of zoiets met ideeën en voorstellen lijkt me handig. Zo weten we wie wat verwacht en kunnen we vanaf de eerste dag duidelijk afspreken hoe alles geregeld zal worden. Ik heb reeds een PowerPoint gemaakt met enkel aandachtpunten, maar graag had ik jullie eigen visie gezien. Ik kijk er in elk geval naar uit.
Nog succes met de examens, Mathias P.S. Meneer Janssens kende iemand die dacht aan een project voor Android en had hiervoor op de voicemail een bericht achter gelaten voor meer informatie samen met mijn nummer. Het kan echter zijn dat door een communicatieprobleem ik zonet die kans verkeken heb. In elk geval moest ik hier nog iets van horen, zal ik laten weten over wat voor applicatie dit ging en dan moet er maar eens besproken worden of dit een goed idee is.
Ben – 24 januari 2011 Ik heb er juist is doorgelezen se. Je hebt er precies al serieus over nagedacht, dat is positief. Ik heb er wel enkele bedenkingen bij: 1) ManicTime ken ik zo direct niet, dus daar kan ik mij niet over uitspreken. Die Excel file daar ben ik wel tegen. Dat lijkt mij niet echt handig. Een task management systeem zoals TRAC of Redmine, dat makkelijk aan SVN of Git kan gekoppeld worden, lijkt mij hier beter. Hierdoor hebben we niet echt een ‘manager’ nodig, maar beslissen we gewoon wie wat gaat doen, zetten onszelf bij een ticket (dat vasthangt aan een milestone), en als het gedaan is, markeren we dat zo in de software. 2) Wekker uitzetten na verplaatsing GPS lijkt mij niet echt een goede manier om het te doen. Dan hang je af van ontvangst etc, en je gaat je wekker geen 2 meter verhuizen als je 'm wilt afzetten (tenzij je ermee gooit). Hier lijkt de accelerometer een betere optie: vanaf dat de wekker begint af te lopen kan je die beginnen pollen om te zien of er iets beweegt. 3) Qua tijdsverdeling: twee dagen samenkomen lijkt mij eigenlijk vrij weinig. Ik weet van mezelf dat als ik alles thuis in orde moet krijgen dat er veel meer tijd wordt doorgebracht op het internet dan met effectief werken... En vermits het voor ons allemaal toch vrij nieuw is, is het niet slecht van samen te zitten in het geval we vragen hebben. Dat moet natuurlijk niet elke dag zijn, zeker naarmate het project vordert, maar in het begin (week 1 en 2) zou ik toch 3 à 4 dagen/week samenkomen. Ik denk dat dat zowat mijn grootste gedachten waren over het project, maar een meeting houden op dag 1 is zeker een goed idee. Of we daarvoor allemaal een PowerPoint moeten maken is iets anders natuurlijk... Ben
93
Mathias – 25 januari 2011 Dit is het effect dat ik dus wou verkrijgen. 1) ManicTime is een applicatie dat constant bijhoudt welke applicatie draait en welke file/website hierin bekeken wordt. Hij probeert door gebruikeracties ook bij te houden of iemand actief aan het werken is of AFK is. Nu ergens misschien wat overkill als we toch wat vaste uren proberen te houden om eraan te werken. Maar het helpt wel als je alleen werkt en een beetje controle op jezelf wilt houden of je niet teveel afgeleid wordt. Voor management dacht ik wel dat Excel niet optimaal was maar ken nog geen specifieke applicaties. (Volgende week ze al eens bezien.) 2) Eigenlijk was het dus juist de bedoeling om met deze optie jezelf uit bed te forceren. Eventueel dan een combinatie met een accelerometer om hiermee een snooze op te zetten en het alarm pas effectief uitzetten als er een merkbare verplaatsing is. Ik ken mezelf en als de wekker naast me ligt zal ik die toch terug verzetten naar een uur later. 3) Dit is voor mij hetzelfde eigenlijk en je hebt een goed punt. Ik vind presentaties mezelf wat meer helpen om het gestructureerd over te laten komen. Dit is wat je zelf het beste lijkt. Mathias
94
Nele – 31 januari 2011 Hey iedereen! Ik heb even een klein tijdsbestedingsvoorstel opgesteld van hoe het mij verstandig lijkt om te werken. https://docs.google.com/document/d/1sdPVlMBkVKGMCuSni2U3HvdbO819Wdy-lRWCtHiAfE/edit?hl=nl# Een beetje volgens de principes van SCRUM zoals voorgesteld, maar rekening houdend met de korte tijd die we hebben. Dus, sprints van 1 week in plaats van 2/3 weken. Zoals Ben al schreef, denk ik dat het (zeker in het begin) nuttig zal zijn als we vaker samenkomen op school, kwestie van meteen een goede start te maken. Ik denk ook dat we beter niet tot dag 4 wachten om elkaar te beginnen helpen, maar elke dag even checken of er iemand op een probleem vastzit zodat we dit zo snel mogelijk kunnen oplossen en geen tijd verspillen. Ik zie hier ook voorstellen voor het gebruik van managementsprogramma's en zo. Ikzelf heb hier niet zoveel ervaring mee dus kan er niet veel over zeggen. Het lijkt me wel best om dit niet te complex te maken zodat we niet de helft van de tijd bezig zijn met die te leren gebruiken. Groetjes Nele
95
Ben – 31 januari 2011 Die tijdsverdeling is inderdaad ongeveer wat ik in gedachten had. Pair programming in the eerste week is ook een zeer goed idee. Qua managementprogramma's, die dat ik voorgesteld heb zijn niet echt ingewikkeld, en zijn puur een hulp om te zien wie wat doet, bij welke sprint die functionaliteit hoort ... Wat ik nog wel bedacht is dat het misschien moeilijk is om op school een lokaal vast te krijgen? We hebben allemaal wel een laptop (of zoiets, he Jeroen), dus het moet geen computerlokaal zijn, maar straks hebben we nog onze eigen applicatie nodig om te weten waar we moeten samenkomen om te ontwikkelen. Ben
96
Ben – 2 februari 2011 Volgens de mail van meneer Janssens beginnen we dus pas de 14e, niet de 7e. De extra vakantie is positief, maar dan hebben we dus wel een week minder.
97
D Android Project Agenda Deze tekst werd oorspronkelijk in PowerPoint-formaat naar ons gestuurd door Mathias. Hierin stelt hij voor hoe hij de verloop van het project ziet en wat hij wilt bereiken tijdens het afstudeerproject. Deze tekst in ook zichtbaar op de volgende link in zijn oorspronkelijke formaat35.
Vermijden stress en moeilijke deadline Houden tijdschema’s en administratie Communicatie centraal Plezier
Rolverdeling
Anti-manager maar pro-managing Beurtwisseling manager dagelijks Verdere rollen later ppt delegeren Unit-testing Communicatie Documentatie
Aanpak management
Tijdscontrole eventueel met ManicTime Dagelijks rapporteren bij manager Excel file (PID – project identification document) via dropbox. Enkel schrijfrechten voor teammanager Alternatieven?
35
De PowerPoint op Google Docs: https://docs.google.com/viewer?a=v&pid=explorer&chrome=true&srcid=0B0KSg_XSY1rgNTI4M2RmMzUtNjJjO C00MmE3LTg4YmUtNGI5MmFiN2M4ODkx&hl=nl
98
Teammanager
Registreert vorderingen Registreert werken Update wiki voor die dag
Delegeren
Taakverdeling zoals scrum (kennisgebied Nele) Rol afhankelijk van de dagelijkse taakverdeling
Scrum Forging
Week start zoals scrum dagelijks bespreking Selecteer taak en voer uit Vanaf dag 4 geen nieuwe taken starten maar: o Horen bij teamleden voor eventuele hulp o Schrijven Documentatie o Schrijven JUnits Voordelen: Betere documentatie, JUnits Stabielere features Beter voor kortere projecten Nadeel: Enkel focus kern-features (nadeel?)
Doel + functionaliteit Eenvoudig toch goed configureerbare schoolagenda met wekker Functies:
Services voor up-to-date agenda Agenda viewer Eenvoudig noties en herinneringen, taken aan vakken toewijzen Wekker berekent op basis locatie, vervoersmiddel, tijd om op te staan (extra marge in te stellen) o Radiowekker (Enkel standaard zenders? Eigen internetlinks?) o Gewone mp3-geluiden o Optie wekker uit na verplaatsing detecteren via GPS o (Diana events bij wekker)
Android educatie
Excel file o Onderwerp o Links met korte samenvatting
99
o o
Aanduiding wie wat leert, geleerd heeft Bij kiezen onderwerp, liefst iets apart, maar met kernfeatures in het hoofd
Planning
Lange termijn Eerste week Standaard dag Elke 1ste/5de dag in school, rest thuis
Lange termijn
1ste week o Educatie, experimenteren tools o Features uitgewerkt o Grafisch ontwerp o Communicatie voor databank o Wennen samenwerking 2de week o Starten eigelijk project o Kernfeatures reeds begonnen 3de week o Kernfeatures stabiel o Eventueel extra features 4de week o Voorbereiding presentatie o Kernfeatures stabiel + gedocumenteerd o JUnits enkel belang op complex en belangrijke punten Week 1 o Dag 1 Overleg projectaanpak Uitwerken features Vragen achter databankconnectie o Dag 2 Use cases uitwerken Grafische ontwerp uitwerken o Dag 3 – 5 Zelfstudie Uittesten git Samenwerken Standaard dag o 9:00 – 17:00 Vast ritme Glijdende uren Vermijden nawerken
100
Kwartiertje scrummeeting Thuiswerk Constant communicatiekanaal: MSN of Skype Einde dag, korte samenvatting dagwerk + uren ManicTime naar teammanager sturen
E Vooruitgangsoverzicht Hier een overzicht van wat we welke dag deden:
14/02/2011 o Eerste productomschrijvingen uitgewerkt en organisatorische maatregelen genomen. o Er werd ook een beeld geschept hoe de applicatie er ongeveer zal moeten uitzien. o De functionaliteiten werden opgesplitst om het werken gemakkelijker te doen verlopen. o Begin Android educatie. 15/02/2011 o De werking met SVN + Trac werd op punt gesteld en eerste tickets aangemaakt voor kerncomponenten. Deze tickets geven ook een gedetailleerde taakverdeling weer. o Een eerste basisweergave van de detailweergave is ondertussen ontworpen. Bekijk het als een Hello KHLRooster applicatie. 16/02/2011 o Gestart met data uit te werken + sqlLite database aanmaken en opvullen. o De detailweergave: Is nu ook grafisch voorzien van een memoblaadje voor notities. o Dagweergave: Is grafisch al half ontworpen. De uren met een uurcursor voor het huidige uur zijn al in orde. o Alarm- en SilenceService: Begonnen aan de klassen. 17/02/2011 o De dagweergave: Is een deel herschreven voor meerdere schermgroten en dpi. o De dagweergave kan nu ook enkele lessen grafisch weergeven. o De AlarmService: kan ondertussen al alarmen instellen om de SilencebroadcastReceiver te informeren. o De database: Wordt ondertussen succesvol aangemaakt, opgevuld en uitgelezen. o De parser: Heeft al succesvol de portaalsite kunnen contacteren en hiervan de vereiste unieke hash te strippen uit de HTML. 18/02/2011 o Refactoring: Van de dagweergave om gestures te kunnen aanvaarden en deze in een unieke herbruikbare component te steken o Gestions: Toegevoegd en kunnen nu eenvoudig geïmplementeerd worden met behulp van template-pattern en strategy-pattern tegelijk. o Belangrijkste menu's: Worden ondertussen ook al opgebouwd. 21/02/2011 o Menu: Verderwerken. o Overgang: Van dag- naar weekview gemaakt. 22/02/2011 o Menu:
102
Verder gewerkt. Widget: Research. o Vibrate-functie: Afgewerkt. o Weekview en dagview: Zijn af inclusief een overgangsanimatie voor visuele feedback. o Google heeft de nieuwe Android 3.0 (Honeycomb) SDK gereleased met betere emulator en layoutbuilder. 23/02/2011 o Alarm settings: Verder gewerkt. o Camera: Implementeren. o Lesmanagement: Verder gemaakt. 24/02/2011 o Algemene settings: Begin. o JavaDoc: Aanvullen. o Reeksconfiguratie: Vervolg. o Netwerken: Omgang met de netwerkconnecties vastgelegd. o Memo’s: Images gebruiken. 25/02/2011 o Settings: Vervolg. o Ophalen vakken: Begin. o Widget: Begin. o Camera. 28/02/2011 o Verslag: Begin. o Widget: Verderwerken. o JavaDoc: Documentatie bijgevuld. o Camera: Cameraproblemen opgelost. o Sync: Verwerken synchronisatie van vakken. 01/03/2011 o Settings: Afwerken menu. Lay-out. Properties opslaan. Properties lezen. o Widget: Vervolg. o Refactoring: Structuur verbeteren van de code. o Verslag: Vervolg. o
103
o
JavaDoc: JavaDoc toevoegen aan klasses. 02/03/2011 o Widget: Op punt stellen. o Verslag: Links toevoegen aan bibliografie. Hoofdstuk De Toekomst schrijven. o Disclaimer: Schrijven. o Memo’s: Aanmaken. Aanpassen. Verwijderen. 03/03/2011 o Widget: Afwerken. o Testen: Lesson management. o JavaDoc: JavaDoc toevoegen. 04/03/2011 o Sync: Afwerken. o JavaDoc: JavaDoc toevoegen. o Lay-out: Laatste details afwerken. o Verslag: Hoofdstuk Design Patterns. Conclusie beginnen. Data collection & gathering. 06/03/2011 o Verslag: Bibliografie aangevuld. Bijlagen toegevoegd. Inhoudstafel geregenereerd. 07/03/2011 o Verslag: Bibliografie aangevuld. Bijlagen toegevoegd. Inhoudstafel geregenereerd. Extra functionaliteit toegevoegd. Conclusie afwerken. o JavaDoc: JavaDoc toegevoegd. JavaDoc-bestanden gegenereerd en nagekeken. o Contact: Via Skype met meneer Janssens. o Sync: Probleem met lessen uit BAKO die niet werden weergegeven opgelost. o Lay-out: Lesson management probleem oplossen qua lay-out. 08/03/2011 o Verslag: Afwerken. Klassendiagram toevoegen.
104
Spelling en grammatica verbeteren. Klassendiagram. Klassenoverzicht. Voorblad. Conclusies. o Sync: Tijdszonesprobleem opgelost. Bugs opgelost. o Lay-out: Kleine details aangepast. 09/03/2011 o Verslag: Afgewerkt. Afgeprint. Ingebundeld. o Bugs fixen. o Testen. 10/03/2011 o Presentatie: Maken. Voorbereiden. Inoefenen. o Screencast. o Verslag indienen. 11/03/2011 o Presentatie!
105
F Klassendiagram Wij zullen ervoor zorgen dat het klassendiagram in een groter formaat beschikbaar zal zijn.
106
Gestiondiagram
107
NumberListeners
Packages Dit zijn de packages die we gebruikten in ons project:
java.lang.Object o com.stringsandints.inventium.khlrooster.icalparser.asynchandlers.LessonEditorA syncHelper o com.stringsandints.inventium.khlrooster.icalparser.asynchandlers.LessonSavingA syncHelper o com.stringsandints.inventium.khlrooster.layout.NotificationAdaptor com.stringsandints.inventium.khlrooster.gestionListeners.AbstractGestionListener o com.stringsandints.inventium.khlrooster.gestionListeners.DownFlingGestion o com.stringsandints.inventium.khlrooster.gestionListeners.LeftFlingGestion o com.stringsandints.inventium.khlrooster.gestionListeners.RightFlingGestion o com.stringsandints.inventium.khlrooster.gestionListeners.UpFlingGestion Activity o com.stringsandints.inventium.khlrooster.TestActivity Activity o com.stringsandints.inventium.khlrooster.NotificationList Activity o com.stringsandints.inventium.khlrooster.LessonSoundProfileSettings
Activity o com.stringsandints.inventium.khlrooster.AlarmButtonActivity AppWidgetProvider o com.stringsandints.inventium.khlrooster.widget.Widget BaseAdapter o com.stringsandints.inventium.khlrooster.ImgAdaptor BroadcastReceiver o com.stringsandints.inventium.khlrooster.services.StartServiceAtBootReceiver BroadcastReceiver o com.stringsandints.inventium.khlrooster.services.SilenceBroadcastReceiver com.stringsandints.inventium.khlrooster.database.Database com.stringsandints.inventium.khlrooster.icalparser.HTTPSHelper com.stringsandints.inventium.khlrooster.icalparser.ICalFetcher com.stringsandints.inventium.khlrooster.icalparser.InitialSync (implements com.stringsandints.inventium.khlrooster.icalparser.ISync) com.stringsandints.inventium.khlrooster.data.Lesson com.stringsandints.inventium.khlrooster.icalparser.asynchandlers.LessonEditorAsyncHel perCommunicator com.stringsandints.inventium.khlrooster.data.LessonHour com.stringsandints.inventium.khlrooster.icalparser.asynchandlers.LessonSavingAsyncHel perCommunicator LinearLayout o com.stringsandints.inventium.khlrooster.layout.WeekCalendar LinearLayout o com.stringsandints.inventium.khlrooster.layout.NumberPicker LinearLayout o com.stringsandints.inventium.khlrooster.layout.DayCalender com.stringsandints.inventium.khlrooster.layout.OnNumberListener com.stringsandints.inventium.khlrooster.data.PropertyManager com.stringsandints.inventium.khlrooster.R com.stringsandints.inventium.khlrooster.R.anim com.stringsandints.inventium.khlrooster.R.array com.stringsandints.inventium.khlrooster.R.attr com.stringsandints.inventium.khlrooster.R.color
111
com.stringsandints.inventium.khlrooster.R.dimen com.stringsandints.inventium.khlrooster.R.drawable com.stringsandints.inventium.khlrooster.R.id com.stringsandints.inventium.khlrooster.R.layout com.stringsandints.inventium.khlrooster.R.menu com.stringsandints.inventium.khlrooster.R.raw com.stringsandints.inventium.khlrooster.R.string com.stringsandints.inventium.khlrooster.R.styleable com.stringsandints.inventium.khlrooster.R.xml com.stringsandints.inventium.khlrooster.data.Reminder Service o com.stringsandints.inventium.khlrooster.services.VibrateBeforeLessonService Service o com.stringsandints.inventium.khlrooster.services.SyncService Service o com.stringsandints.inventium.khlrooster.services.SwitchWidgetScreenService Service o com.stringsandints.inventium.khlrooster.services.SilenceService Service o com.stringsandints.inventium.khlrooster.services.NetworkService Service o com.stringsandints.inventium.khlrooster.services.AlarmService Service o com.stringsandints.inventium.khlrooster.services.AlarmClockService SQLiteOpenHelper o com.stringsandints.inventium.khlrooster.database.DatabaseHelper TextView o com.stringsandints.inventium.khlrooster.layout.VerticalTextView TextView o com.stringsandints.inventium.khlrooster.layout.VerticalLabelView java.lang.Throwable (implements java.io.Serializable) o java.lang.Exception o com.stringsandints.inventium.khlrooster.database.UnknownIdException com.stringsandints.inventium.khlrooster.Utils com.stringsandints.inventium.khlrooster.Utils.ConnectionStatus com.stringsandints.inventium.khlrooster.Utils.SyncStatus com.stringsandints.inventium.khlrooster.icalparser.VEVENT
Enkele geselecteerde lessen Lesson sound profile settings
126
127
Disclaimer
128
H Use case diagrammen Android screen
129
KHLRooster
130
Lesdetails
131
Alarm settings
132
Geluidsprofiel les
133
Gallery screen
134
Lessenmanager
135
I Tickets Met de Trac hielden we tickets bij om de functionaliteiten op te delen en ervoor te zorgen dat alles gedaan werd. Deze tickets zijn online terug te vinden36 waar al de details met een simpele muisklik gevonden kunnen worden, maar voor het gemak sommen we ze hier ook nog eens op. Ticketnummer 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 36
Beschrijving iCal parser en inlezen van lesroosters SilenceService AutoVibrate Detailweergave les Menuopties Dagweergave Vakselectie Vakmanagement Lesson, Day, Week and notes class Memo Documentatie Nadat parsing goed werkt de weer te geven lessen gewoon uit de databanken lezen Vloeiende overgang dagoverzicht bij wisselen dag + lessen aanpassen voor nieuwe dag Locatie is verkeerd bijgehouden Lijst met opties en preferences Klassenschema Uniforme naamgeving Bijhouen weergegeven datum bij draaien Code clean-up Check properties on startup launch activity Sync laten uitvoeren bij starten Android Custom media selecteren Status van ringer van OS uitlezen en in property zetten Meerdere woonplaatsen Widget maken voor homescreen Notification list Notification screen Genereren uurroosters Verslag schrijven iCal: dubbele lokalen Notification edit screen Date locale lookup Refactor OnNumberListener SyncService detail Services uittesten wanneer uitgevoerd door sync + gegevens uit properties halen Dagview automatisch scrollen Wi-Fi uitzetten na sync
http://inventium.stringsandints.com/trac/report/6
136
38 39 40
Notifications moeten nog werkelijk gemaakt worden Refresh screen after sync Klasseschema herschalen zodat het past op 1 pagina
K Codevoorbeelden Om elkaar verder te helpen, maakten we een lijstje met veelvoorkomende stukjes code zodat we deze konden gebruiken als referentie om mee verder te werken. Hieronder volgen deze veelvoorkomende stukjes code. Alarm implementatie AlarmManager mgr=(AlarmManager)this.getSystemService(ALARM_SERVICE); Intent intent=new Intent(this, SilenceService.class); PendingIntent pi=PendingIntent.getBroadcast(this, 0, intent, 0); mgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, d.getTime(), pi);
Set en get property preferences // A context should always be provided (the service or activity) // Set property Editor e = PropertyManager.getInstance(this).getEditor(); e.putInt("savedBytes", dp.getCounter()); e.commit(); // Get property PropertyManager.getInstance(this).getSettings().getInt("savedCounter", 0)
Gestures in components // Implementing gestures in components has been made more flexible // Here is a small example GestureOverlayView gv = (GestureOverlayView) this.findViewById(R.id.gestionCatcher); gv.addOnGestureListener(new RightFlingGestion(new GestionAction() { @Override public void performAction() { dateShown.add(GregorianCalendar.DAY_OF_MONTH, 1); updateDateShown(); } })); // It is obvious that you should first implement a GestureOverlayView in your layout // This gestureOverlayView must encapsulate the place where you want to detect gestions.
Layout stretching over verschillende rijen
142
Try for selecting Music Intent i = new Intent(Intent.ACTION_GET_CONTENT); i.setType("audio/*"); Intent c = Intent.createChooser(i, "Select soundfile"); startActivityForResult(c,1);
Notifications gebruiken mManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE); notification = new Notification(R.drawable.icon, "Kanji dictionary update", System.currentTimeMillis()); contentView = new RemoteViews(this.getPackageName(), R.layout.progressbar); contentView.setTextViewText(R.id.procent, "0 %"); contentView.setProgressBar(R.id.progressBar, 100, 0, false); notification.contentView = contentView; // While updating go to updatingprogress screen Intent notificationIntent = new Intent(this, Menu.class); notificationIntent.putExtra("DictionaryUpdater", "Stop"); notificationIntent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0); notification.contentIntent = contentIntent; mManager.notify(PROGRESS_NOTIFICATION_ID, notification);
Forceer encoding URL url = new URL("http://ftp.monash.edu.au/pub/nihongo/JMdict"); URLConnection ucon = url.openConnection(); InputStream is = ucon.getInputStream(); bis = new BufferedSkipStream(is); final CharsetDecoder charsetDecoder = Charset.forName("UTF8").newDecoder(); charsetDecoder.onMalformedInput(CodingErrorAction.REPLACE); charsetDecoder.onUnmappableCharacter(CodingErrorAction.REPLACE); Reader bisReader = new InputStreamReader(bis, charsetDecoder);
143
L Properties Het was nodig om voor onze settings al de informatie bij te houden in de properties. Hiervoor is het zeer belangrijk dat iedereen dezelfde propertynamen gebruikt en het juiste type meegeeft want anders kan de applicatie crashen. Om ervoor te zorgen dat iedereen wist welke properties we gebruikten hoe deze noemden, hielden we een lijst bij op onze wiki. Dit is de volledige lijst van gebruikte properties, samen met hun type en een korte beschrijving over wat ze precies doen en eventueel (bij Strings) de mogelijke opties.
Properties
alarmMode (String) o Use default notification sound o Vibrate o Select custom media o Select stream o Enter custom stream wakeUpMillisecondsBefore o Tijd in ms (int) customStreamUrl o URL naar stream (String) customMedia o URI naar stream (String) selectedStreamUrl o geselecteerde URL naar stream (String) layout o Dag of Week view (int) alarmEnabled o checkBox alarm aan/uit (bool) timeBeforeLessonMilliseconds o Aantal ms voor de les waarop het soundLevel verandert (int) changeSoundModeForLesson o Bepaalt of de gebruiker het OS van modus wilt laten veranderen (stil/vibrate) (bool) userRingerMode o Plaats de door de gebruiker geselecteerde RingerMode voor tijdens de lessen in de properties (int) vibrateBeforeLesson (boolean) forceWireless o Laat de gebruiker kiezen of hij wifi wilt laten enablen voor een sync. (boolean: true/false) lastPhoto o Laatste link naar photo om te zorgen dat de camera-intent blijft werken op elk toestel ook als de activiteit in de achtergrond verwijderd wordt door de garbage collector om geheugen vrij te maken firstTime
144
o Om te zien of het de eerste keer is dat de applicatie wordt opgestart. syncStatus o Geeft de status van de scheduled sync weer. Waardes worden bijgehouden in Utils.SyncStatus. (int) userRingerMode o Zet de gebruikersvoorkeur van ringermode in de properties (int)
145
M Code Hieronder volgen enkele klassen waarrond onze applicatie opgebouwd is. Deze zijn naar onze mening enkele van de belangrijkste klassen in KHLRooster. Dit dient mede om anderen een idee te geven van hoe men voor Android kan programmeren. SyncService.java package com.stringsandints.inventium.khlrooster.services; import java.util.ArrayList; import java.util.GregorianCalendar; import java.util.HashMap; import import import import import import import import import import
/** * Service that handles the scheduled synchronisation between the ical file and the local database */ public class SyncService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { super.onStartCommand(intent, flags, startId); doStart(intent); return START_NOT_STICKY; } /** * Legacy implementation of onStartCommand */ @Override public void onStart(Intent intent, int startId) { if(Utils.GetSDKVersion() < 7){ super.onStart(intent, startId); doStart(intent); } } @Override public IBinder onBind(Intent intent)
146
{ return null; } protected final SyncService globalcontext = this; public Intent callingIntent; /** * Handles the starting of the service */ public void doStart(Intent intent) { this.callingIntent = intent; // Quit if there's already a sync running if(Utils.getSyncStatus(this) == Utils.SyncStatus.SYNC_BUSY) return; Log.w("khlrooster", "SS: Starting sync"); Utils.setSyncStatus(Utils.SyncStatus.SYNC_BUSY, this); new AsyncTask<Service, Integer, Integer>() { @Override protected Integer doInBackground(Service... params) { Service s = params[0]; int netconn = Utils.checkInternetConnection(s); if(netconn == Utils.ConnectionStatus.INTERNET_AVAILABLE || netconn == Utils.ConnectionStatus.WIFI_ENABLING) { // Wait for the wifi to activate GregorianCalendar start = new GregorianCalendar(); while(Utils.checkInternetConnection(s) != Utils.ConnectionStatus.INTERNET_AVAILABLE) { try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); // We can't take the risk of letting it consume 100% CPU if it can't sleep return Utils.SyncStatus.SYNC_FAIL; } GregorianCalendar end = new GregorianCalendar(); long span = end.getTimeInMillis() start.getTimeInMillis(); // If it's been running for too long, set a flag and kill the service if(span > Utils.CONNECTION_TIMEOUT) { return Utils.SyncStatus.SYNC_FAIL; } } // Do the sync return doSync(s); }
147
return Utils.SyncStatus.SYNC_FAIL; } @Override protected void onPostExecute(Integer result) { super.onPostExecute(result); Utils.setSyncStatus(result, globalcontext); if(result == SyncStatus.SYNC_FAIL) Toast.makeText(globalcontext, R.string.sy_fail, Toast.LENGTH_LONG).show(); else Toast.makeText(globalcontext, R.string.sy_success, Toast.LENGTH_SHORT).show(); Utils.disableNetwork(globalcontext); /* * Tell the alarm manager to schedule a new sync */ AlarmManager mgr = (AlarmManager) globalcontext.getSystemService(ALARM_SERVICE); Intent intent = new Intent(globalcontext, SyncService.class); PendingIntent pi = PendingIntent.getService(globalcontext, 0, intent, 0); // Delete a possibly already scheduled sync mgr.cancel(pi); GregorianCalendar next = new GregorianCalendar(); if(next.get(GregorianCalendar.HOUR_OF_DAY) >= 12) { next.set(GregorianCalendar.HOUR_OF_DAY, 23); } else { next.set(GregorianCalendar.HOUR_OF_DAY, 12); next.add(GregorianCalendar.DAY_OF_MONTH, 1); } mgr.set(AlarmManager.RTC_WAKEUP, next.getTimeInMillis(), pi); /* * Call the AlarmService */ Intent asintent = new Intent(globalcontext, AlarmService.class); asintent.putExtra("timeBeforeLesson", PropertyManager.getInstance(globalcontext).getSettings().getInt("timeBeforeLessonMi lliseconds", 300000)); asintent.putExtra("timeUntilAlarm", PropertyManager.getInstance(globalcontext).getSettings().getInt("wakeUpMilliseconds Before", 3600000)); globalcontext.startService(asintent); if(globalcontext.callingIntent.getBooleanExtra("fromActivity", false)) { Intent activityintent = new Intent(globalcontext, Khlrooster.class);
148
activityintent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); globalcontext.startActivity(activityintent); } } }.execute(this); } /** * This method performs the actual sync */ public int doSync(Service s) { GregorianCalendar start = new GregorianCalendar(); Database db = Database.getInstance(s); /* * Generate list of what to update */ // Map> HashMap<String, ArrayList<String>> syncdata = new HashMap<String, ArrayList<String>>(); ArrayList lessons = db.getLessons(); ArrayList<String> lessonnames = new ArrayList<String>(); for(Lesson l : lessons) { for(LessonHour lh : l.getLessonHours()) { ArrayList<String> reeksen = syncdata.get(lh.getDepartment()); // Department not in list yet if(reeksen == null) { reeksen = new ArrayList<String>(); reeksen.add(l.getReeks()); syncdata.put(lh.getDepartment(), reeksen); } // Reeks not associated with department yet else if(!reeksen.contains(l.getReeks())) { reeksen.add(lh.getDepartment()); } } lessonnames.add(l.getEventName()); } /* * Fetch schedules */ boolean syncfailed = false; for(String dep : syncdata.keySet()) { for(String reeks : syncdata.get(dep)) { ArrayList events = ICalFetcher.fetch(dep, reeks); if(events.size() == 0) { syncfailed = true; break; }
149
ArrayList reslessons = ICalFetcher.createLessonList(events, lessonnames, reeks); // Check if there are any lessons missing in this update for(Lesson l : lessons) { if(l.getReeks().equals(reeks)) { if(!reslessons.contains(l)) l.setNotFoundInLastSync(true); else l.setNotFoundInLastSync(false); db.updateLesson(l, false); } } // Insert remaining lessonhours into the DB db.insertUpdatedLessonList(reslessons); } } GregorianCalendar end = new GregorianCalendar(); Log.w("khlrooster", "SS: Sync completed in " + (end.getTimeInMillis() - start.getTimeInMillis()) + " ms"); if(syncfailed) return Utils.SyncStatus.SYNC_FAIL; else return Utils.SyncStatus.SYNC_SUCCESS; } }
/** * AlarmService manages the application's alarms. */ public class AlarmService extends Service { AlarmManager mgr; public final static String VIBRATE_ON = "235663462"; public final static String VIBRATE_OFF = "278967896389"; public final static String ALARM_ON = "247892749"; public final static String ALARM_OFF = "8997328757"; public final static String SILENT_ON = "5675765"; @Override /** * This method creates the Service. It also gets the AlarmManager from the device to set the alarms. */ public void onCreate() { super.onCreate(); mgr = (AlarmManager) this.getSystemService(ALARM_SERVICE); } @Override /** * This method is used for backwards compatibility. Newer versions use onStartCommand. * It calls the handleEvent method to handle the event. */ public void onStart(Intent intent, int startId) { if(Utils.GetSDKVersion() < 7){ handleEvent(intent); } } @Override /** * This Method handles the start of the service. It starts the handleEvent method. */ public int onStartCommand(Intent intent, int flags, int startId) { handleEvent(intent); return START_NOT_STICKY; } @Override public IBinder onBind(Intent intent) { return null; } /** * This method gets the data needed for the alarms from the properties and gets the old data from the intent.
151
* It then calls the adjustAlarms method. * @param intent */ private void handleEvent(Intent intent) { int timeBeforeLesson = intent.getIntExtra("timeBeforeLesson", 300000); int newTimeBeforeLesson = PropertyManager.getInstance(this).getSettings().getInt("timeBeforeLessonMillisecond s", 300000); int timeUntilAlarm = intent.getIntExtra("timeUntilAlarm", 3600000); int newTimeUntilAlarm = PropertyManager.getInstance(this).getSettings().getInt("wakeUpMillisecondsBefore", 3600000); adjustAlarms(timeBeforeLesson, newTimeBeforeLesson, timeUntilAlarm, newTimeUntilAlarm); } /** * This method first cancels all alarms already set for the date. It adds the alarms to set the phone to vibrate and sets the alarmClock for the next day. * @param timeBeforeLesson: Amount of milliseconds the alarms goes off before the start of the lesson. * @param newTimeBeforeLesson: Old value of timeBeforeLesson. * @param timeUntilAlarm: Amount of milliseconds, before the first hour, the alarmClock should go of. * @param newTimeUntilAlarm: Old value of newTimeUntilAlarm. */ public void adjustAlarms(int timeBeforeLesson, int newTimeBeforeLesson, int timeUntilAlarm, int newTimeUntilAlarm){ /* * Create theIintents */ Intent silence = new Intent(this, SilenceBroadcastReceiver.class); Intent vibrate = new Intent(this, VibrateBeforeLessonService.class); ArrayList lessonHours = Database.getInstance(this).getLessonHoursForSpecificDay(new GregorianCalendar()); /* * Cancel all current alarams for vibrate on */ silence.setAction(VIBRATE_ON); PendingIntent pi = PendingIntent.getBroadcast(this, 0, silence, 0); mgr.cancel(pi); /* * Cancel all current alarams for vibrate off */ silence.setAction(VIBRATE_OFF); pi = PendingIntent.getBroadcast(this, 0, silence, 0); mgr.cancel(pi); for (LessonHour lessonHour : lessonHours){ /* * If the lesson is now or in the future, set alarms */ if (lessonHour.getStart().getTimeInMillis() > new GregorianCalendar().getTimeInMillis() || (lessonHour.getStart().before(new GregorianCalendar())&& lessonHour.getEnd().after(new GregorianCalendar()))) { silence.setAction(VIBRATE_ON); pi = PendingIntent.getBroadcast(this, 0, silence, 0); /* * Set to vibrate if set in property */ if(PropertyManager.getInstance(this).getSettings().getBoolean("changeSoundMod eForLesson", true)){ mgr.set(AlarmManager.RTC_WAKEUP, lessonHour.getStart().getTimeInMillis() - newTimeBeforeLesson, pi); } silence.setAction(VIBRATE_OFF); pi = PendingIntent.getBroadcast(this, 0, silence, 0); /*
152
* Set vibrate of set in property */ if(PropertyManager.getInstance(this).getSettings().getBoolean("changeSoundMod eForLesson", true)){ mgr.set(AlarmManager.RTC_WAKEUP, lessonHour.getEnd().getTimeInMillis() - 30000, pi); } pi = PendingIntent.getService(this, 0, vibrate, 0); /* * Set vibrate before lesson if set in property */ if(PropertyManager.getInstance(this).getSettings().getBoolean("vibrateBeforeL esson", true)){ mgr.set(AlarmManager.RTC_WAKEUP, lessonHour.getStart().getTimeInMillis(), pi); } } } /* * Create the intent for the alarmclock */ Intent alarmClockIntent = new Intent(this, AlarmClockService.class); alarmClockIntent.setAction(ALARM_ON); PendingIntent alarmClockPendingIntent = PendingIntent.getService(this, 0, alarmClockIntent, 0); mgr.cancel(alarmClockPendingIntent); /* * Get the first lesson for the next day */ int wakeUpHoursBefore = newTimeUntilAlarm; GregorianCalendar tomorrow = new GregorianCalendar(); tomorrow.add(GregorianCalendar.DAY_OF_YEAR, 1); LessonHour firstHour = Database.getInstance(this).getFirstLessonHourOfDay(tomorrow); /* * If set in property, set the alarmClock */ if(firstHour != null && PropertyManager.getInstance(this).getSettings().getBoolean("alarmEnabled", true)){ mgr.set(AlarmManager.RTC_WAKEUP, firstHour.getStart().getTimeInMillis() - wakeUpHoursBefore, alarmClockPendingIntent); } } }