• No results found

PaddelAppen Claes Barthelson

N/A
N/A
Protected

Academic year: 2022

Share "PaddelAppen Claes Barthelson"

Copied!
71
0
0

Loading.... (view fulltext now)

Full text

(1)

PaddelAppen

Claes Barthelson

Fakulteten för hälsa, natur­ och teknikvetenskap   Datavetenskap 

15 hp 

Annika Klockar 

Donald F. Ross 

150124 

(2)

Datavetenskap

Claes Barthelson

PaddelAppen

Examensarbete

(3)
(4)

PaddelAppen

Claes Barthelson

(5)
(6)

Denna rapport är skriven som en del av det arbete som krävs för att erhålla en kandidatexamen i datavetenskap. Allt material i denna rapport, vilket inte är mitt eget, har blivit tydligt identifierat och inget material är inkluderat som tidigare använts för erhållande av annan examen.

Claes Barthelson

Godkänd, 2015-01-15

Handledare: Annika Klockar

Examinator: Donald F. Ross

(7)
(8)

Sammanfattning

Mobila lösningar blir allt vanligare och appar kan utvecklas för att hjälpa mobilanvändare med det mesta. Att utveckla appar är populärt och kan göras i en mängd olika språk och utvecklingsmiljöer, och projektet har haft som mål att både utveckla en användbar app och utvärdera en sådan utvecklingsmiljö.

PaddelAppen som utvecklats i projektet fyller ett tomrum genom att vara en resurs för

paddelintresserade. Samtidigt har utvecklingsarbetet resulterat i en utvärdering av utveck-

lingsmiljön Xamarin, som använts tillsammans med Visual Studio för att plattformsobe-

roende utveckla appen för både Android och Windows Phone.

(9)

Abstract

Mobile solutions are increasingly popular and apps can be developed to help mobile users with almost anything. To develop is, as a result, also popular and can be done in a number of programming languages and development environments, and the goal of this project was to both develop a useful app and simultaneously evaluate such an environment.

PaddelAppen, the app developed in this project, fills a void by providing a resource

for paddlers. At the same time the development has resulted in an evaluation of Xamarin,

the development environment used together with Visual Studio to develop the app, cross-

platform, for both Android and Windows Phone.

(10)

Innehåll

1 Introduktion 1

1.1 Projektsammanställning och översikt . . . . 1

1.2 Projektresultat . . . . 2

2 Bakgrund 3 2.1 Om Xamarin . . . . 3

2.2 Problemområde och bakgrundsinfo . . . . 4

2.2.1 Att använda Xamarin . . . . 4

2.2.2 Xamarin.Forms . . . . 5

2.2.3 MVVM . . . . 6

2.2.4 Karta och kartpunkter . . . . 6

2.2.5 Databas för kartpunkter . . . . 8

2.2.6 XML-databas . . . . 8

2.2.7 SQL-databas . . . . 8

2.2.8 Användare, rättigheter och informationsinsamlande . . . . 9

2.3 Kapitelsammanfattning . . . . 10

3 Projektdesign 11 3.1 Design . . . . 11

3.2 Detaljer . . . . 12

3.2.1 Views . . . . 14

3.2.2 ViewModels . . . . 18

3.2.3 Models . . . . 19

3.2.4 Controllers och Custom Renderers . . . . 19

3.3 Kapitelsammanfattning . . . . 19

4 Implementation 21

(11)

4.1 Detaljer . . . . 21

4.1.1 View . . . . 21

4.1.2 ViewModel . . . . 22

4.1.3 Model . . . . 23

4.1.4 Extensions . . . . 25

4.1.5 Services . . . . 26

4.1.6 Custom Controls . . . . 28

4.1.7 Custom Renderers . . . . 30

4.1.8 Data . . . . 32

5 Resultat och Utvärdering 34 5.1 Introduktion . . . . 34

5.2 Implementationsbeskrivning . . . . 34

5.3 Utvärdering av app-utvecklingen . . . . 35

5.4 Utvärdering av Xamarin . . . . 41

5.4.1 Diskussion kring Xamarin . . . . 42

5.4.2 Alternativ till Xamarin . . . . 45

5.5 Kapitelsammanfattning . . . . 46

6 Slutsats 48 6.1 Slutsats . . . . 48

6.2 Projektutvärdering . . . . 48

6.3 Problem . . . . 50

6.4 Framtida arbete - utveckling av projektet . . . . 52

(12)

Figurer

1.1 Prioriteringspunkter . . . . 2

3.1 Översikt av projektet enlig MVVM . . . . 13

3.2 Navigationssida . . . . 16

3.3 Listsida och navigationssida . . . . 16

3.4 Nära vy av detaljsidan . . . . 17

4.1 Översikt över hur kartan får sin extra funktionalitet . . . . 32

5.1 Startmenyn i implementationen . . . . 36

5.2 Kartan i implementationen . . . . 37

5.3 Listan i implmentationen . . . . 38

5.4 Detailjsidan i implementationen . . . . 39

5.5 Punkter i närheten . . . . 40

6.1 Prioriteringspunkter . . . . 49

(13)
(14)

1 Introduktion

Projektets mål var att utveckla en app för paddlare i vilken man kan hämta information om platser som kan vara bra att känna till som paddlare samt att testa och utvärdera utveck- lingsmiljön Xamarin. En kravspecifikation enligt figur 1.1 togs fram för appen. Ett antal funktioner listades och gavs en prioritet efter hur viktig funktionen ansågs vara för appen.

Alla funktioner utom den med lägst prioritet, användarinloggning, har implementerats i appen och störst vikt har lagts vid att få en väl fungerande karta. Därefter har en utvärde- ring av hur väl Xamarin är lämpat för att åstadkomma detta gjorts. Dessutom diskuteras olika utvecklingsmetoder som Xamarin erbjuder där fördelar vägs mot nackdelar.

Motivationen till projektet har kommit från två håll. Själva appidén i sig var ett resultat av ett personligt fritidsintresse där IT-lösningar ofta saknas samt en önskan om att kunna utforska vackra platser med hjälp av sin smartphone. En app där man kan hitta bra vatten att paddla, hyra sin kajak eller sätta upp sitt tält är något som idag saknas.

Projektet skrevs på Sogeti i Karlstad och den andra delen i motivationen var Sogetis önskan att se hur Xamarin fungerar och hur väl det lämpar sig för utveckling av appar på flera plattformar och är anledningen till att just Xamarin använts och att projektet utvecklats till två plattformar, Android och Windows Phone. En stor del av det resultat som presenteras i rapporten är därför en utvärdering av hur Xamarin har upplevts under projektperioden.

1.1 Projektsammanställning och översikt

Projektet har bestått av apputveckling och rapportskrivning med stor vikt vid den utvär-

dering som finns under resultat.

(15)

Figur 1.1: Prioriteringspunkter

1.2 Projektresultat

De förväntade projektresultaten var en app färdig att använda samt en rapport där utvärde-

ring är en viktigt del men som också förklarar appens uppbyggnad och utvecklingsförloppet.

(16)

2 Bakgrund

Utvecklingsmiljöer för att utveckla appar till flera plattformar samtidigt är visserligen inget ovanligt nuförtiden [Bes], men att kunna göra det i C# och med gemensam kod för nästan allting [Inci] är både nytt och intressant. Sogeti föreslog att utvecklingen av PaddelAppen skulle ske i Xamarin för att få en idé om hur bra det fungerar, något som verkade kunna bli både intressant och lärorikt.

2.1 Om Xamarin

Xamarin är en utvecklingsmiljö som tillåter plattformsoberoende utveckling av appar i C#

[Inci]. Utvecklingsmiljön existerar som en egen IDE samt integrerad i Visual Studio [Incf]

och kommer i två varianter, Xamarin för iOS och Xamarin för Android. Eftersom man kan utveckla i Visual Studio finns därtill även stöd för Windows Phone. Programvaran är byggd på .NET-ramverket Mono [Ale].

Idén är att man ska kunna dela så mycket kod som möjligt mellan de olika plattformar- na, och på så sätt kunna skriva en app en gång, men ändå göra den tillgänglig på samtliga plattformrar.

Enligt Xamarin själva ska man kunna dela upp till 90% [Inci] av all kod mellan de olika mobila plattformarna. Resten av koden får anpassas till vardera plattform [Incj], och detta gäller till största del gränssnittet, som kommer behöva se lite annorlunda ut på de olika plattformarna. Här ger Xamarin dessutom möjligheten att designa gränssnitt i en grafisk designer för vardera plattform.

Xamarin erbjuder även ett API för gränssnittskontroller [Incy] som kan delas mellan alla plattformar för att ytterligare utöka den delade kodbasen, kallad Xamarin.Forms.

Xamarin.Forms kan designas i Extensible Application Markup Language, XAML [Micd;

Micg], eller C# och innehåller de flesta gränssnittselement från de tre plattformarna.

(17)

2.2 Problemområde och bakgrundsinfo

2.2.1 Att använda Xamarin

Xamarin kommer som tillägg till Visual Studio [Incf] eller som fristående miljö i form av Xamarin Studio [Ince]. För att jobba mot Android eller iOS behöver man köpa en licens av Xamarin avsedd för respektive ändamål [Inci], vill man jobba mot Windows Phone finns det redan stöd i Visual Studio och man kan därför använda Xamarin utan licens. För att jobba med iOS behöver man dessutom tillgång till en Mac - antingen att jobba på eller använda som build server [Inco]

När man skapar ett projekt i Xamarin gör man det för en eller flera plattformar sam- tidigt. I projektet ingår sedan flera underliggande projekt, ett för koden som delas mellan de plattformar som inkluderats samt ett projekt för varje plattform [Inch]. För detta pro- jekt skapas alltså ett Android/Windows Phone-projekt med totalt tre underliggande delar.

Utvecklingen av projekt sker sedan i programspråket C#, det språk som används vid ut- veckling för Microsofts plattformar, och det som används för Windows Phone även i vanliga fall. Att detta fungerar för Android och iOS, som använder Java respektive Objective-C, beror på att Xamarin vid kompilering översätter från C# till rätt språk för vardera platt- form [Incs].

All bakomliggande kod, såsom logik och databaser skrivs sedan i den del av projeket

som delas mellan plattformarna. Man har sedan två alternativ på var koden som utgör

användargränssnittet kan skrivas. Xamarin erbjuder nämligen användaren att bygga an-

vändargränssnitt separata, antingen med Xamarins visuella designer eller via kod, så att

man kan anpassa gränssnitten efter plattform, och dessa skrivs då i den del av projektet

som hör till respektive plattform [Incg]. Vill man hellre hålla ihop allting i den gemen-

samma kodbasen, även användargränssnitt, kan man använda Xamarins kontrollbibliotek,

Xamarin.Forms [Incy], som är en uppsättning kontroller som skrivs i XAML eller C# och

fungerar plattformsoberoende. Här får man dessutom möjlighet att (likt exempelvis utveck-

(18)

ling för Windows Phone) använda ModelViewViewModel-designmönstret [Gos], MVVM, fullt ut med hjälp av MVVMCross [autc], något som kan vara en fördel för den som är van.

2.2.2 Xamarin.Forms

För att göra utvecklingen i Xamarin än mer enhetlig har Xamarin.Forms[Incc] utvecklats, för att man ska kunna utveckla ett gränssnitt gemensamt för alla plattformar, istället för ett gränssnitt för vardera. Xamarin.Forms är ett API som innehåller de flesta gränssnitts- kontroller som finns över de tre plattformarna och låter användaren skriva ett gränssnitt som sedan kan användas i alla plattformar genom att koden mappas mot motsvarande interface-element på vardera plattform.

Xamarin.Forms kan designas både i C# och XAML och påminner således mycket om Windows Presentation Foundation [Micf; Mich] eller Windows Phone-utveckling, och stö- der alla vikta gränssnittskontrollers [Incy]. Men det finns begränsningar. Till exempel är kartan, som är en viktig del i PaddelAppen, en av de kontroller som är minimalt utrustad i Xamarin.Forms [Incv]. Funktionaliteten sträcker sig här såpass långt att det går att ta fram en karta och det går att sätta ut punkter på kartan med hjälp av koordinater, men därutöver finns inga fler funktioner. PaddelAppen kräver fler funktioner än så, och behöver använda de plattformsspecifika kartorna istället för de som finns i Xamarin.Forms.

En nackdel med att använda Xamarin.Forms är att det inte finns något officiellt [Jas;

Dan] IntelliSense, en funktionalitet som erbjuder förslag på vad du försöker skriva när

du påbörjat ett ord, som man kanske är van vid om man skrivit XAML i Visual Studio

tidigare. Det finns dessutom inget bra sätt att hitta fel i XAML-koden, utan den enda

feedback man får är ett generellt felmeddelande vid kompilering, som inte erbjuder några

ledtrådar.

(19)

2.2.3 MVVM

Model-View-ViewModel [Gos] är ett designmönster eller standard att försöka hålla sig till när man bygger mjukvara, vilken är till för att hjälpa utvecklaren skilja på kod med olika uppgifter. I just MVVM skiljer man kod som rör användargränssnittet samt logiken bakom, som i sin tur är uppdelad i logik som utnyttjas av användargränssnittet samt logik som används i den bakomliggande koden.

När man kodar enligt MVVM delar man upp alla klasser i tre separata klasstyper. Alla klasser som hanterar gränssnitt och ren gränssnittslogik är Views, medan klasser som hör till backenden samt all data är Models. De klasser som binder ihop Views och Models, alltså de som gör datan och logiken presenterbar i gränssnittet, är ViewModels.

ViewModels ska tillhandahålla egenskaper som Views kan binda mot och metoder som Views kan använda samt ha koll på när olika Event triggas så att de kan reagera på detta och uppdatera det som Views binder mot så att det får genomslag till gränssnittet. Views i sin tur ska bygga upp gränssnittet och eventuellt hantera sådan logik som behövs för att åstamdkomma önskat utseende i detsamma, samt binda mot egenskaper och metoder i sin underliggande ViewModel.

För att fullt ut kunna anpassa sig efter MVVM i Xamarin finns hjälpmedel som MVVMCross [autc].

2.2.4 Karta och kartpunkter

Den kanske mest vitala delen i appen är användning av kartan, då översikt över alla platser

som finns lagrade i databasen är den viktigaste delen i appens utformning. Kartorna är den

centrala delen i att skapa denna översikt. Appen måste alltså först och främst kunna visa

en karta. Kartor kan verka komplicerat i sig, men eftersom appen skrivs för Android och

Windows Phone kan deras respektive API:er för kartor användas. Det enda som krävs är

egentligen att man registrerar sig hos Google och får en nyckel som låser upp användningen

av deras API, samt för Windows Phone att man gör ett par inställningar i config-filen i

(20)

det projektet.

Sedan finns två alternativ för implementation av kartor i appen. Det första alternativet är att använda kart-API:er för varje plattform för sig. Det vill säga, i Android-projektet används Androids kart-API och i Windows Phone-projektet används Windows kart-API.

Den här koden skulle alltså inte delas utan vara separat för vardera plattform.

Men det finns möjligheter i Xamarin att utöka den gemensamma kodbasen till gräns- snittet genom att använda Xamarin.Forms. Xamarin.Forms är skapat av Xamarin och är en samling gränssnittskontroller som använder underliggande gränssnitts-API för vardera plattform och på så vis erbjuder utvecklaren möjlighet att skriva ett gränssnitt som kan användas på alla tre plattformar, och som, om man vill, kan anpassas via villkor för de enskilda plattformarna. Rapporten går in mer i detalj på vad Xamarin och Xamarin.Forms i avsnitt 2.2.2.

Xamarin.Forms innehåller de flesta gränssnittselement, däribland kartor [Incy]. I båda alternativen är själva införandet av kartor i appen simpelt, man lägger till elementen via XAML eller i koden.

Funktionaliteten i kartorna ska sedan utökas med möjligheten att sätta ut punkter, vilket även detta är enkelt med båda alternativen då båda erbjuder metoder för att sätta ut punkter på givna koordinater. Punkterna bör representera olika kategorier, till exempel för uthyrningsplatser, rutter eller rastplatser där kategorin både anges av en unik färg samt är tydlig i namnet som sätts på punkten.

Nästa utmaning är att rita linjer på kartan för att representera rutter. Det här saknas

stöd för i Xamarin.Forms version av kartan [Incv], men det bör ändå gå att hitta någon

form av lösning då Xamarin erbjuder specialanpassning av kontroller [Incj]. Alternativt kan

man utnyttja användandet av plattformsspecifika villkor för att nyttja funktionaliteten i

Google’s kart-API för att rita linjer.

(21)

2.2.5 Databas för kartpunkter

Appen kommer ha behov av att lagra en del data, bland annat i form av information om platser, såsom koordinater, beskrivningar och namn. Då appen bör ha utrymme att växa, dvs att antalet platser som ska lagras ska kunna bli ganska många, bör metoden att lagra datan vara lämpad för stora mängder. Det finns ett par alternativ, Extensible Markup Language (XML) och Structured Query Language (SQL) [Incr], för att lagra denna typ av data som båda skulle lämpa sig, med vissa nackdelar för vardera implementation.

2.2.6 XML-databas

XML är ett markup-language, likt HTML, som används för att strukturera upp informa- tion och samtidigt ge en indikation om vilken roll specifik information innehar [Wal]. Man kan alltså spara information och märka upp den med till exempel kategorier. Det fungerar utmärkt att spara information i XML-formatet och använda dokumentet som en databas, men det kan bli lite osmidigt att hantera stora mängder information när den ska manipu- leras, då XML främst är anpassat för att flytta data mellan andra typer av databaser eller från en mjukvara till en databas [Har03].

2.2.7 SQL-databas

En SQL-databas är både enkelt, man slipper serialiseringen till XML, och effektivt, stora

mängder data går snabbt att söka igenom i en databas [SQL]. Xamarin själva rekommen-

derar att man använder SQLite.net för att hantera data [Incu]. SQLite.net finns att ladda

hem till projekt via NuGet, Visual Studio:s pakethanterare, och kan sedan användas för

att skapa databaser och utföra enkla frågor med hjälp av kod som den fil man laddar

hem tillhandahåller. Man kan med hälp av denna kod spara objekt som man definierat i

sitt projekt, så länge objekten har definierat vilka egenskaper som ska fungera som attri-

but och en primärnyckel. Dock är funktionaliteten förhållandevis låg, man kan exempelvis

inte använda sig av främmandenycklar för att länka objekt i olika databastabeller mot

(22)

varandra, något som skulle vara bra att kunna. Det finns ett tillägg till SQLite.net som går att använda för att åstadkomma detta [Aut], och det finns dessutom en Query-metod [Aut] i SQLite-filen som ger en möjlighet att skriva databasfrågor via C# mot databasen.

SQLite.net verkar således vara den smidigaste vägen att gå för att hantera appens data.

2.2.8 Användare, rättigheter och informationsinsamlande

En av de icke tekniska utmaningarna är hur man bör fylla appen med relevant information.

Den inledande tanken var att användare skulle kunna ladda upp platser de tror kan vara av intresse för andra, samt betygsätta platser för att förenkla för andra användare. På så sätt skulle appen kunna byggas av användarna, likt ett community, och från att den publicerats mer eller mindre sköta sig själv. Efter samtal med kajak-kunniga på bland annat kajakuthyrningar [Zet] framkom dock vissa risker med denna metod. Den främsta av dessa risker är att vissa platser kan vara rentav farliga att paddla på under fel förutsättningar, såsom vind eller vattenstånd, något som kanske undgår “vanliga” användare.

En metod som skulle undanröja en sådan risk vore att man ger vissa användare särskilt tillstånd att ladda upp platser till databasen. Dessa användare skulle isåfall behöva utses av någon, och skulle företrädesvis vara personer som jobbade med uthyrning av utrustning eller höll kurser i paddling.

Ett tredje tillvägagångssätt, som också är det som implementerats, vore att utvecklaren samlar så mycket befintlig information som möjligt och manuellt fyller upp databasen med det som finns. Detta skulle dock innebära en väldigt begränsad databas om inte utvecklaren flitigt uppdaterar den med ny data även efter projektets slut.

Ett webgränssnitt som har tillgång till databasen och via vilken man kan tillföra data

vore ett naturligt steg för samtliga alternativ. Ett krav är också att databasen är central

och kan uppdateras för alla användare.

(23)

2.3 Kapitelsammanfattning

Utvecklingen av appen kräver lösningar på ett flertal problem som generellt har presenterats i kapitlet. För att över huvud taget kunna använda Xamarin behövs en licens samt antingen att man installerar Xamarin Studio eller har en installation av Visual Studio att använda tillsammans med Xamarin. Projektet skapas sedan för flera plattformar, med underliggande projekt specifika för Android och Windows Phone.

Xamarin.Forms är Xamarins API för att tillåta göra gränssnittskod plattformsobero- ende och har använts i projektet. Forms kan designas i både C# och XAML och passar därför MVVM-designmönstret efter vilket appen designats. MVVM strukturerar klasserna i appen efter funktion för att skilja gränssnitt från bakomliggande kod.

En fungerande karta med bakomliggande databas är en viktig del för appen. För att

kartan ska ha någonting att visa krävs data om platser och leder. En SQLite.NET-databas

används med fördel, något som också rekommenderas av Xamarin. Kartan behöver mycket

funktionalitet för att vara användbar men Xamarin.Forms version av kartan har bara stöd

för mycket enkel funktionalitet. Kartan behöver därför utökas med det som saknas.

(24)

3 Projektdesign

Appen, som fått projektnamnet PaddelAppen, är en app som låter användaren via en karta hitta platser som är av intresse då man vill ut och paddla. Det kan vara uthyrningsplatser, paddlingsleder eller rastplatser. Appen låter dessutom användaren ta reda på vilka av dessa platser som finns i närheten samt betygsätta alla platser för att underlätta för andra användare. Dessutom finns möjlighet för vissa användare att lägga upp och dela med sig av platser de tycker kan vara bra för andra att veta om.

3.1 Design

Appen skrivs i C# enligt MVVM-designmönstret, och utvecklas parallellt till Android och Windows Phone. Att utveckla i C# för Android är möjligt tack vare Xamarin.Android, Windows Phone appar skrivs ursprungligen i C#. Appen består av tre delprojekt, ett som håller den kod som delas mellan plattformarna ett projekt för vardera plattform som egentligen bara innehåller det som krävs för att starta appen på den specifika plattformen.

Den grundläggande designen innebär alltså att tre projekt utgör appens källkod, men bara två av dessa projekt kommer att kompileras till den slutliga appen. Ett av projekten innehåller all den delade kod som både Android-versionen och Windows Phone-versionen av appen kommer att använda sig av. De andra två projekten är plattformsspecifika och innehåller var för sig endast kod som kommer att användas till Android respektive Windows Phone.

I det delade projektet finns nära på all backend-kod, det som i MVVM kallas model, och

dessutom en hel del gränssnittskod. Det är här appen accessar databaser, hanterar använ-

darinput, och utför all logik. I de plattformsspecifika projekten finns den kod som behövs

för att starta upp appar på respektive plattformar och dessutom en del gränssnittskod

samt viss kod som behövs för att anpassa eller utöka den delade koden, exempelvis kart-

vyer. Även den klass som hanterar databasen med SQLite behöver initieras från dessa två

(25)

projekt separat, även om den i sig existerar i den delade koden.

Att appen designas i enlighet med MVVM-designmönstret innebär rent praktiskt att de flesta klasser som skrivs delas in i Views, Models och ViewModels för att kunna skilja på varje klass uppgift. Dessa delas in i egna mappar samt har en viss namnstandard för att man enkelt ska se i vilken nivå man är och jobbar. Tack vare detta kan man jobba i gränssnittet helt separat, utan att påverka hur någon av de andra delarna fungerar, och vice versa. I figur 3.1 ses en översikt över projektet enligt MVVM. Här syns de tre klasstyperna och vilket jobb det är tänkt att de olika typerna ska utföra. Dessutom syns hur mycket av koden som kan delas mellan plattformar och vad som behöver anpassas specifikt.

Eftersom Xamarin.Forms finns tillgängligt och erbjuder utveckling av gränssnitt i XAML, vilket är vad MVVM avsetts för [Incl], används det för att göra appens gränssnitt. XAML är ett markup-språk, precis som HTML, och låter utvecklaren bygga gränssnitt på ungefär samma vis som man bygger websidor med HTML. Detta innebär att för varje sida som gränssnittet består av kommer en XAML-page att finnas i Views-mappen, med en under- liggande C#-klass som binder sidan mot en underliggande ViewModel, så att man i sin tur i XAML-koden kan binda till alla nödvändiga egenskaper.

Xamarin.Forms erbjuder egna varianter av kontroller, såsom knappar, menyer eller text- fält, för de flesta kontroller som finns för respektive plattform, så alla sidor bör gå att skriva med Xamarin.Forms som bas. Däremot är vissa kontroller något fattiga på funktionalitet, i synnerhet kartorna, som därför behöver utökas med hjälp av lite specialanpassning.

3.2 Detaljer

Appen består som ovant nämnt av tre olika typer av klasser, nämligen Views, i fortsätt-

ningen hänvisade till som vyer, ViewModels, vymodeller, samt Models eller modeller. I

designfasen är det viktigt att se till att rätt filer får rätt tillhörighet, det vill säga att alla

de filer som har med datahantering eller logik att göra hamnar bland övriga modellerna,

att filer som bygger upp användargränssnittet hamnar bland vyerna samt att länkarna

(26)

Figur 3.1: Översikt av projektet enlig MVVM

(27)

däremellan är vymodeller.

3.2.1 Views

PaddelAppen använder sig till stor del av kartor och listor, så det är det första som tas med i designen. Både listor och kartor behöver en snygg representation i användargränssnittet, och dessutom bakomliggande logik som låter användaren navigera både i kartvy och listvy för att enkelt kunna hitta det den vill komma åt. Både kartvy och listvy designas för att ta upp hela skärmen, då översikt är viktigt för dessa två kontroller. Användaren ska dessutom kunna klicka på punkter på kartan eller poster i listan för att få upp info om den platsen.

Både listvyn och kartvyn ska kunna visa olika typer av punkter, för att tydliggöra för

användaren om en punkt är led, uthyrning eller något annat. Detta ska vara någorlunda

enkelt att fixa i listvyn, men är någonting som behöver ganska mycket jobb i kartvyn,

då kontrollen för kartor i Xamarin.Forms inte stöder någonting annat än att helt enkelt

rita ut kartan och sedan sätta ut vanliga kartnålar på koordinater efter instruktioner från

sin vymodell. Det som krävs för att anpassa kartan efter sina behov är att man skapar

vad som kallas för en Custom Renderer. Detta är en klass som måste finnas i båda de

plattformsspecifika projekten och som används som ett lager mellan Androids eller Win-

dows Phones kart-API och Xamarin.Forms kartor. Custom Renderer:n används sedan för

att lägga till funktionalitet som finns i Androids och Windows Phones kartor men som

saknas i Xamarin.Forms kartor. Dessutom behöver en klass skapas i den delade koden som

ärver Xamarin.Forms.Maps och som har metoder för att hantera den funktionalitet som

Custom Renderer-klassen tillhandahåller. Det är också denna klass som används för att

skapa kartor i appen, istället för ursprungliga Xamarin.Forms.Maps. En enkel illustration

finns i figur 3.1, där de blå fälten visar Androids respektive Windows kart-API med den

överliggande Custom Renderer-klassen som skickar funktionalitet ett steg upp. Det gröna

fältet är den specialanpassade klass som ärver Xamarins karta och som sedan används för

att skapa nya, anpassade kartobjekt.

(28)

Med hjälp av dessa två nya klasser kan man sedan få kartan i sitt Xamarin.Forms- baserade användargränssnitt att klara av allt som den underliggande kartan i Android eller Windows Phone klarar av. I PaddelAppens fall rör det sig alltså om att kunna anpassa punkterna som sätts ut på kartan (byta utseende) och göra dem klickbara. Dessutom läggs stöd in i Custom Renderer:n för att rita ut linjer mellan koordinater på kartan, eftersom Xamarin.Forms kartan inte klarar detta heller, eftersom detta behövs för att visa rutter på ett bra sätt.

Övriga delar i användargränssnittet rör mest olika typer av navigation. Användaren ska

ju på ett enkelt sätt kunna ta sig fram till alla sidor appen består av. Det smidigaste sättet

att göra detta är att använda sig av navigationsstacken, som finns på smarta telefoner. Man

får då automatiskt tillgång till exempelvis en bakåtknapp, som bara tar bort den översta

sidan ur navigationsstacken och visar föregående. För att åstadkomma en sådan lägger man

helt enkelt in den första sidan man vill visa som en NavigationPage, och alla sidor man se-

dan öppnar via denna eller vidare hamnar på navigationsstacken och det fungerar utmärkt

att använda telefonens bakåtknapp för att navigera tillbaka i användargränssnittet. I figur

3.2 syns den sida som läggs in från början i navigationsstacken, navigationssidan, via vilken

man navigerar till resterande sidor. Här syns knappar man kan använda för att ta sig till

sidor som visar alla platser på en lista eller en karta, och sedan därifrån ta sig vidare till en

detaljsida som visar en mindre karta samt en beskrivning av den plats man valt. Figur 3.3

visar listsidan och kartsidan. Listsidan har en lista som största element, längst upp finns

också knappar för filtrering och en titel. Kartsidan visar enbart kartan och på kartan syns

alla punkter inom det område som visas. Detaljsidan visas i figur 3.4 och här finns övrig

info som kan vara bra att veta, tex om det finns rastplatser med möjlighet att sätta upp

tält eller elda, samt hur lång rutten är om det är en sådan man klickat sig till.

(29)

Figur 3.2: Navigationssida

Figur 3.3: Listsida och navigationssida

(30)

Figur 3.4: Nära vy av detaljsidan

(31)

3.2.2 ViewModels

Även om vyerna inte behöver någon vymodell för att fungera, så behöver ju varje vy någon typ av logik bakom sig eller någon data att visa för att vara funktionella, i form av en vymodell.

Vymodellen för navigationssidan behöver bara metoder för att skicka vidare användaren till olika sidor. Detta kan göras genom att den sida som ska öppnas läggs på navigations- stacken och på så sätt visas i appen och dessutom låter användaren backa med telefonens bakåtknapp.

Kartvyn behöver en vymodell som hjälper till med att sätta ut alla platser som ska visas på kartan, samt dra ruttlinjer. Vymodellen till kartvyn bör alltså ha koll på vilka platser som ska sättas ut och vilka koordinater dessa har ska kunna passas till kartvyn.

Eftersom vymodellen också är kopplingen till modellerna ska den också hämta data den behöver därifrån, i detta fall ur databasen som innehåller alla platser som ska ut på kartan.

Vymodellen bör dessutom kunna navigera till en detaljsida som hör till platsen som väljs i kartvyn.

Listvyn behöver, likt kartvyn, en vymodell som har koll på alla platser. Dessa ska dock i detta fall förstås laddas in i en lista som kan representeras i listvyn. I övrigt behöver listvyn logik som på olika sätt kan sortera listan och filtrera resultaten i listan. Det behövs metoder för att sortera efter tex bokstavsordning, längd på rutter, närhet till rutter (i detta fall finns även specialfallet med sidan för närliggande rutter, och om metoden existerar här kanske samma logik och lista kan användas) eller betyg. Även här behövs en metod för att navigera vidare till nästa sida, för vald plats. Därtill behövs metoder för att hämta data från modellerna, närmare bestämt det samma som i kartvyns vymodell, platsdata ur databasen.

Detaljsidan behöver ganska mycket logik bakom sig för att vara funktionell. Bland annat

visas här en karta som visar var platsen ligger eller hur rutten är dragen, vymodellen

behöver således bidra med platsdata i form av koordinater. Därtill ska en beskrivning

(32)

hämtas ur databasen och göras tillgänglig för vyn och på samma sätt ska betyg, längd på rutt och övrig info som lagrats i databasen göras tillgänglig för vyn. Här behöver vymodellen dessutom tillhandahålla olika typer av ikoner för att göra informationen översiktlig för vyn.

3.2.3 Models

Till modellerna hör all logik som hanterar data samt hanterar databasen. Dessutom är alla klasser som behövs för att skapa de objekt som representerar platser i koden modeller.

Dessa klasser behöver definiera vad som är attribut och primärnyckel, det behövs när de objekt som skapas av klassen ska lagras i databasen.

Klassen som hanterar databasaccess är också en modell, och använder sig av SQLite.net- klassen som finns att ladda hem i NuGet, den pakethanterare som finns i Visual Studio.

Denna klass ska tillhandahålla logik för att spara, plocka fram och ta bort data i en eller flera databaser.

3.2.4 Controllers och Custom Renderers

Appen behöver utöka funktionaliteten hos Xamarin.Forms kartor och därför skapas en kartklass som ärver Xamarins kartor samt utökar funktionaliteten med hjälp av en Custom Renderer i de plattformsspecifika projekten. Här läggs funktionalitet in för att göra kart- nålarna mer interaktiva samt för att kunna rita på kartan, linjer mellan olika koordinater.

I Custom Renderer:n görs den funktionalitet som finns i Androids och Windows Phones kartor tillgänglig för den utökade kartklassen, så att dessa låses upp för användning.

3.3 Kapitelsammanfattning

Appen skrivs i C# enligt MVVM-designmönstret. Klasser delas därför upp i tre typer; vyer,

vymodeller och modeller där man skiljer grässnittskod från bakomliggande kod. Ytterligare

en distinktion ges genom att gränssnittet skrivs i XAML.

(33)

Vyerna består av en meny samt en karta och en lista. Menyn och listan går att ko- da enligt kravspecifikationen genom att bara använda XAML och rätt logik i respektive vymodell, medan kartan behöver specialanpassas. Till detta används en anpassningsklass, Custom Renderer, för att bidra med den funktionalitet som saknas i kartan. Vyerna pre- senteras dessutom genom grafiska skisser för att ge en idé om designen.

Vymodellerna är de klasser som binder ihop logiken, modellerna, med vyerna, så att dessa har någonting att visa i gränssnittet. Vymodellen för menyn är den klass som bidrar med metoder, dvs den klass som vet vad som ska hända när en knapp i menyn används.

Vymodellen för kartvyn hämtar data om platser från databasen och sätter ut dessa platser på kartan så att de syns i vyn, precis som vymodellen för listvyn fyller listan med data att visas i listvyn.

Modellerna håller all logik och hanterar databasanrop. Även klassen som representerar platser är en modell.

Utöver de tre klasstyperna som finns i MVVM behövs också ett antal klasser för spe-

cialanpassning, av exempelvis kartan.

(34)

4 Implementation

4.1 Detaljer

4.1.1 View BrowsePage

Sidan, som illustreras i figur 3.2, visar fyra knappar intill varandra, mitt på sidan, två i en övre rad samt två i en undre rad. Detta åstadkoms i XAML-koden genom att en Stacklayout skapas och som sedan innehåller ett Grid, med två rader och två kolumner. När knapparna skapas placeras de samtidigt ut i Grid:et, och önskat utseende uppnås.

MapPage

Denna sida visar endast en karta i grundutförande och syns i figur 3.3, och tillhörande vymodell sköter tilläggning av ytterligare element, såsom kartnålar. Kartan i sig läggs även den in via vymodellen, och det enda som existerar i XAML:en är en Stacklayout i vilken kartan kan placeras. Stacklaouyten förses med ett namn och den bakomliggande vymodellen kan sedan lägga till kartan genom en enkel add-metod på Stacklayouten.

ListPage

ListPage visar en lista, som skapas inuti en Stacklayout i XAML-koden. Det är bara listan som skapas och den fylls sedan av sedan av PointCells-objekt, som beskrivs nedan, i sin vymodell. Som synes i figur 3.3 finns här också en del knappar längst upp på sidan som är till för att filtrera resultaten som visas i listan.

PointCell

PointCell består av två labels placerade bredvid varandra i en Stacklayout. Det är

denna sida som utgör varje cell som läggs till i ListPage, på så sätt kan man skilja

listcellerna från själva listan och designa den som en egen sida. Varje label i PointCell

(35)

binder mot en egenskap, Name respektive Notes, som hör till det som cellen i sin tur ska fyllas med, en plats.

DetailsPage

DetailsPage i figur 3.4 är till för att hålla utförlig information om en plats har en del olika gränssnittselement. Det första är en karta som läggs in i XAML-koden, förutom den omkringliggande Stacklayouten. Under kartan placeras sedan ett antal ikoner som även dessa kan läggas in via XAML-kod. Dessa ikoner är egentligen typsnitt, och kan läggas in som text. Ikoner finns för att visa att platsen har tex en eldplats, tältplats, uthyrning eller andra intressanta saker. Dessutom finns en ikon för att öppna bilder från platsen samt fem runda små ikoner för att visa vilket betyg rutten har fått av andra användare. Därefter följer en TableView med en TableSection som i sin tur håller två TextCells, där dels platsens beskrivning länkas in, och dels kommentarer eller övrig info länkas in.

4.1.2 ViewModel BrowsePageViewModel

BrowsePageViewModel står för logiken bakom vyn BrowsePage. Den har ett antal Command objekt som de knappar som finns i BrowsePage kan binda till. Varje Com- mand sätts sedan via metoder till en Task som asynkront öppnar en ny sida. Mer än så behövs inte göras i den här klassen då detta ger den navigation som behövs. Genom att navigationen sker via ett Navigation-objekt läggs nya sidor på navigationsstacken som gör det enkelt att backa till föregående sida.

MapPageViewModel

MapPageViewModel är klassen bakom kartsidan MapPage och skapar ett objekt av

den specialanpassade kartklassen CustomMap utifrån den position som hämtats från

telefonens GPS. Därefter skapas ett antal menyknappar för filtrering. Varje knapp

(36)

använder sig av kartans AddPoints-metod för att visa endast en specifik typ av punkt på kartan, alltså filtrera bort alla typer av punkter utom en, genom att ange en viss typ som parameter. De olika knapparna kan filtrera fram punkter av typerna rutt, lägerplats, uthyrning och återställa så att alla punkter visas. Därefter läggs alla knappar in i navigationsmenyn och kartan läggs till i den LayoutStack som skapats i MapPage-klassen avsedd för just kartan.

ListPageViewModel

ListPageViewModel liknar MapPageViewModel i det att den lägger till samma me- nyknappar, men istället för en karta skapas en lista. Listans ItemTemplate och ItemTemplate-binding sätts och därefter även listans ItemSource. Till ItemSource sätts den lista man får från databasens GetPoI-metod. Här skapas även ett Command- objekt som ett klick på ett objekt i listan som syns i ListPage kan binda till. Detta kommando sätts till en Task som asynkront navigerar till detaljsidan för avsedd punkt.

DetailsPageViewModel

DetailsPageViewModel har ett antal olika strängar. Dessa är till för att alla textfält i DetailsPage ska ha något att binda till och returnerar helt enkelt ett strängvärde från den punkt som är representerad på sidan. Därtill läggs en mindre karta till i den MapStack som skapats i DetailsPage. Denna karta skapas i en egen metod med center i den punkt sidan ska representera och som dessutom krympts till ett passande format.

4.1.3 Model PointOfInterest

PointOfInterest är klassen som representerar en punkt på kartan. Klassen håller infor-

mation om allting som användaren behöver veta om en plats samt allting själva appen

(37)

behöver veta för att representera platsen på kartan i form av en punkt. Egenskaperna är således ganska många, det finns ett namn och en beskrivning samt koordinater.

Därtill finns ytterligare information som hur lång sträckan är ifall det rör som en rutt, samt vilken användarpoäng platsen har tilldelats. Till sist finns det en typangivelse som talar om vilken typ av plats det rör sig om, uthyrning, rutt eller övernattnings- plats och dessutom en sträng som håller alla koordinater som behövs för att sätta ihop en sträcka på kartan ifall platsen är av typen rutt.

Anledningen till att den här klassen håller koordinater som enskilda double-värden för latitud respektive longitud istället för ett Location-objekt (som beskrivs nedan) är att databasen inte klarar att lagra objekt som i sig håller objekt av en klass, utan endast klarar av rena värden som tal och strängar. Detta är också anledningen till att rutten lagras som sträng och inte tex en lista med Location-objekt - det går inte att lagra en lista, som ju är ett objekt av klassen List, i databasen.

Objekt av den här klassen kommer att finnas lagrade i databasen och klassen har därför implementerat SQLite’s Attribut-bibliotek, så att klassens egenskaper kan ses som speciella attribut (såsom primärnyckel) i databasen genom att man lägger till taggar innan man deklarerar egenskaperna. Detta görs enkelt genom att man på raden ovan egenskaperna lägger in exempelvis [PrimaryKey, AutoIncrement], vilket gör att egenskapen under ses som primärnyckelattributet i databasen, och dessutom automatiskt tilldelas ett nummer högre än det objekt som lades till innan, så att man slipper sätta primärnyckeln själv.

Location

Location är en klass som enbart håller två koordinater och används för att hålla

reda på var platser finns på kartan. Klassen används på en hel del platser i appen,

bland annat i MapExtensions för att göra om strängen som representerar en rutt i

PointOfInterest-klassen (som beskrivits ovan) till en lista med Location-objekt för

(38)

att läggas ut på kartan.

4.1.4 Extensions MapExtensions

Den här klassen är en modifierad version av klassen MapExtensions, skriven av Ro- bert Ecthen i projektet BindableMapTest [Ech].

Den här klassen håller en mängd metoder som används i olika delar i appen för att utöka eller förbättra funktionalitet. Det är en statisk klass, just för att olika andra klasser i appen ska kunna använda sig av metoderna i den. Dessutom finns här en typdeklarering i form av en enum som kallas LocationType, där rutt, uthyrning samt tält-/eldplats representeras och därför kan utnyttjas av hela appen när kontroll av typ behöver göras.

De olika metoderna är dels en metod som används för att representera ett objekt av appens specialanpassade kartnål (CustomPin) som en kartnål (Pin) som går att placera ut på en Xamarin.Forms.Maps-karta. Detta är nödvändigt helt enkelt för att man på en Xamarin.Forms.Maps-karta inte kan placera ut något annat än just objekt av klassen Pin, och eftersom CustomPin är en egen klass som är en utökad version av just Pin, måste man gå tillbaka till Pin innan man placerar ut punkterna på kartan.

Därtill finns två metoder för att hantera rutter och dess omvandling mellan sträng och lista som beskrivits i avsnitten om PointOfInterest och Location ovan. Som bekant kan PointOfInterest endast hålla rena värden, därför hålls en rutt som en sträng av koordinater, medan på alla andra ställen i appkoden en rutt representeras som en lista av Location-objekt. De två nämnda metoderna behövs alltså för att översätta från det normala formatet i from av en lista till en sträng att lagra i databasen, och vice versa.

För att omvandla från lista till sträng används en metod kallad MakeTrailString som

tar en lista (ObservableCollection) med Location-objekt som parameter och sedan,

för varje objekt i listan plockar ut latitud och longitud och sparar i en sträng med

(39)

ett specialtecken som skiljetecken däremellan, och fortsätter så för varje objekt tills listan är slut. Varje objekt skiljs i sin tur åt i strängen med ett annat skiljetecken.

Det hela sparas i en resultatsträng efterhand och returneras. För att vända på det används metoden MakeTrailPoints, som returnerar en lista efter att ha fått en sträng som parameter. Metoden delar först på strängen efter det skiljetecken som användes för att skilja Location-objekten åt och lägger dessa in en sträng-array, varpå varje sträng i denna sträng-array delas efter det skiljetecken som lades in mellan latitud och longitud och dessa parsas sedan till double-värden och sparas i ett Location-objekt som i sin tur sparas i en resultatlista, vilken sedan returneras.

4.1.5 Services

Alla klasser under den här kategorin är modifierade versioner av den kod [Bur] Amy Burns skrivit som exempelkod för Xamarins webbplats enligt den guide [Incd] som behandlar Backgrounding. Klasserna jobbar tillsammans för att i bakgrunden prenumerera på upp- dateringar från enhetens GPS så att appen vet på vilka koordinater den befinner sig.

LocationProvider

LocationProvider hanterar objekt av övriga klasser och ett objekt av LocationPro-

vider används i Android-projektets MainActivity-klass för att uppdatera informa-

tion om GPS-koordinaterna i enheten i bakgrunden, genom att köra uppdatering-

en på en egen tråd. I LocationProvider finns ett privat LocationServiceConnection-

objekt och ett publikt LocationService-objekt, dock endast med get-funktion, samt

en EventHandler, LocationServiceConnected. Sedan körs på en bakgrundstråd genom

en Task. I den här Task:en sätts LocationServiceConnection-objektet för att man

ska kunna binda till Servicen då LocationServiceConnection innehåller ett Binder-

objekt. LocationServiceConnection innehåller även en EventHandler kallad Service-

Connected som också den sätts här till den EventHandler som finns i Location-

Provider, LocationServiceConnected. Detta för att MainActivity-klassen ska få ve-

(40)

ta när det är dags att börja uppdatera. Dessa EventHandlers kommer triggas av OnServiceConnected-metoden i LocationServiceConnection. Till sist binds servicen med LocationServiceConnection-objektet samt en Intent som skapas strax innan och Task:en startas.

LocationServiceConnection

Som nämnt ovan har LocationServiceConnection en EventHandler, ServiceConnec- ted, som triggas av OnServiceConnected-metoden för att det då är dags att börja uppdatera data från enhetens GPS samt ett objekt av LocationServiceBinder-klassen.

OnServiceConnected-metoden anropas när klienten försöker binda till servicen varpå systemet letar reda på den bindern som hör till den service som körs. Denna bin- der castas sedan som en LocationServiceBinder och sätts till LocationServiceBinder- objektet. När detta är gjort triggas ServiceConnected-eventet som låter MainActivity-

klassen veta att den nu kan börja uppdatera. Därefter anropas en metod i LocationServiceBinder- objektets LocationService-objekt, nämligen StartLocationUpdates, för att börja sam-

la in data från GPS:en.

LocationServiceBinder

LocationServiceBinder har ett objekt, ett av typen LocationService, via vilken StartLocationUpdates- metoden nås. Det viktiga i den här klassen är att den ärver Binder och således är en

Binder-subklass.

LocationService

LocationService har ett antal EventHandlers, för att få uppdateringar angående posi- tion eller när GPS:en sätts på eller stängs av. Den har dessutom ett LocationManager- objekt som sätts till Androids positionsservice. Här finns sedan den metod som fak- tiskt anropar Android-systemets positionsservice för att få positionsuppdateringar.

Den här metoden heter StartLocationUpdates och börjar med att sätta vissa kriteri-

er, som hur noggranna uppdateringarna ska vara. Därefter hämtas det system (GPS

(41)

eller nätverk) som ska leverera uppdateringarna och därifrån begärs sedan en posi- tionsuppdatering. LocationService prenumererar sedan på uppdateringar och får en uppdatering varje gång en ny position upptäcks vilka sedan delegeras via EventHand- lers till MainActivity som har en metod, HandleLocationChanged, för att göra det som behövs när den får en positonsuppdatering.

4.1.6 Custom Controls CutomMap

Den här klassen är en modifierad version av klassen ExtendedMap, skriven av Robert Ecthen i projektet BindableMapTest [Ech].

CustomMap ärver och är en utbyggnad av Xamarin.Forms.Maps, och är till för att lägga till funktionalitet som existerar i Googles kartor men som saknas i Xamarins.

För detta behövs, förutom denna klass, dessutom en så kallad Custom Renderer-klass som beskrivs längre fram. Man kan säga att den här klassen är ett mellanlager mel- lan Custom Renderer-klassen som skickar upp funktionalitet från Googles karta och Xamarin.Forms karta som ska utnyttja funktionerna. Först och främst håller kartan listor med objekt av typerna Location, respektive CustomPin, som är appens egen version av Pin, Xamarin.Forms.Maps kartnålar (som också beskrivs nedan).

Listan med objekt av typen Location kommer att användas av den tillhörande Custom Renderer-klassen där funktionalitet för att rita på kartan finns, så att rutter (som är vad listan representerar) kan ritas ut på kartan med hjälp av Google Maps PolyLines [Inca].

Ytterligare funktionalitet som det läggs till stöd för är att det på kartan går att klicka

på en kartnål och på så sätt välja den samt att det då visas en inforuta tillhörande den

valda kartnålen. Informationsrutan kan även den klickas på för att ta användaren till

den sida som tillhör den valda platsen. Detta görs genom att det i denna klass finns

en BindableProperty (som tillåter data bindning från Custom Renderer-klassen) för

(42)

den kartnål som användaren klickar på. Den valda kartnålen håller ett id som skickas till den metod i CustomMap-klassen som sedan hämtar den plats med samma id i databasen och lägger tillhörande sida på navigationsstacken.

Dessutom finns här metoder för att lägga till de kartnålar som är anpassade efter appens ändamål, CustomPin. Det finns metoder för att lägga till alla platser i data- basen som kartnålar, lägga till alla platser som uppfyller ett villkor om typ, samt en enskild plats efter ID. Detta görs genom att alla önskvärda platser i databasen läggs till som objekt av typen CustomPin i en lista, och alla objekt i denna lista läggs sedan till Xamarin.Forms.Maps egen lista med Pins (sin egen klass för kartnålar) med hjälp av en metod i CustomPin som översätter mellan just CustomPin och den vanliga Pin.

En enkel beskrivning av CustomMap och hur den förhåller sig till övriga klasser finns i figur 4.1.

CustomPin

Den här klassen är en modifierad version av klassen ExtendedPin, skriven av Robert Ecthen i projektet BindableMapTest [Ech].

CutomPin-klassen är en utbyggnad, likt CustomMap, av Xamarin.Froms.Maps egna

Pin-klass. Den har fler egenskaper, för att kunna hålla bland annat all information

som finns i objekt av typen PointOfInterest, vilken CustomPin är avsedd att repre-

sentera på en karta. Dessutom finns en metod för att hämta ut en rutt med hjälp av

metoder ur MapExtensions-klassen. CustomPin används (även här, likt CustomMap)

av CustomMapRenderer som ett led i utökandet av funktionalitet för kartan, här i

form av anpassade kartnålar. CustomPin finns med två konstruktorer, en för att ange

all info i form av parametrar samt en för att helt enkelt bara skicka in ett objekt av

PointOfInterest och göra den till en kartnål.

(43)

4.1.7 Custom Renderers

CustomMapRenderer - Android

Den här klassen är en modifierad version av klassen ExtendedMapRenderer, skriven av Robert Ecthen i projektet BindableMapTest [Ech].

CustomMapRenderer är den klass som har allra mest att göra med utökning av kart- funktionaliteten. Den här klassen finns i Android-delen av projektet och lyfter fram olika funktioner som finns i den för Android ursprungliga Google-kartan. Med hjälp av den här klassen blir sådan funktionalitet som inte existerar i Xamarin.Forms.Maps, ändå tillgänglig i den klass som beskrivits ovan, CustomMap, genom att denna är- ven just Xamarin.Forms.Maps och samtidigt drar nytta av den funktionalitet som CustomMapRenderer lyfter fram.

I den här klassen finns en mängd metoder för att lyfta fram all relevant funktionali- tet. Det första som görs är att två EventHandlers, händelser som sker när någonting ändras, tilldelas. Dels en för den händelse som triggas när användaren trycker på ett informationsfönster (det fönster som poppar upp när man trycker på en kartnål) och dels en för den händelse som triggas när samlingen av kartnålar på något sätt förändras. Dessa två EventHandlers tilldelas metoder, i det ena fallet, där ett klick på informationsfönstret triggar en händelse, anropar metoden helt enkelt motsvaran- de metod i CustomMap-klassen som skickar användaren till en ny sida. Den andra händelsen, där en förändring i samlingen kartnålar är vad som triggar, tilldelas en metod som endast anropar metoden UpdatePins. UpdatePins har till uppgift att rita ut alla kartnålar på kartan genom att lägga till en Marker, som kartnålarna kallas i Android.

Innan detta görs så rensas kartan via dess Clear-metod, eftersom detta behöver göras

för att man varje gång metoden körs inte ska få en ny uppsättning markörer på de

gamla. Därefter läggs en EventHandler till för att reagera på när användaren klickar

(44)

på en markör. Att detta görs här, och inte tidigare, beror på att, eftersom kartan rensas varje gång denna metod körs, existerar inte händelsen därefter, och måste läggas till på nytt. Metoden fortsätter sedan med att hämta listan med CustomPin- objekt från sitt CustomMap-objekt (vilket beskrivs i avsnittet om CustomMap ovan) och lägger för CustomPin i listan till en ny markör enligt Google-kartans regler.

Metoden avslutar med att sätta en ikon på markören som är anpassad efter typ genom att anropa metoden GetPinIcon och skicka typen som finns i CutomPin- objektet (rutt, uthyrning eller rastplats) som parameter samt lägga till markören i med hjälp av Android-kartans AddMarker-metod. I samband med detta sista steg mappas dessutom markörens id (som är i form av sträng) mot CustomPin-objektets id (som är detsamma som platsen den representerar som finns lagrat i databasen) med hjälp av ett Dictionary. Detta görs för att det annars inte finns något sätt att förknippa Google-kartans markörer med appens CustomPins- och PointOfInterest- objekt, då Google-markörens id inte går att sätta utan sätts automatiskt till en genererad sträng.

GetPinIcon-metoden som används i UpdatePins tar, som bekant, en typ som para- meter och avgör med hjälp av den vilken ikon som ska returneras. Ikonerna har lagts in under Androids Resurs-mapp och returneras rakt av.

Den andra metoden som används i UpdatePins, HandleMarkerClick, tar den mar- kör som triggat händelsen som parameter och öppnar det infofönster som hör till denna markör. Dessutom sätts CustomMap-objektets SelectedPin till en Custom- Pin som får alla egenskaper av den markör som triggat eventet, detta för att även CustomMap-objektet ska veta vad som klickats på. Det sista som görs här är att me- toden AddPolyLines anropas, med markör-objektets id som parameter. Denna metod ritar ut en rutt, ifall en sådan existerar, och behöver således ett id för att leta efter rätt rutt.

I lite mer detalj så jobbar AddPolyLines-metoden mot en lista av PolyLine-objekt.

(45)

Figur 4.1: Översikt över hur kartan får sin extra funktionalitet

Det första som görs i metoden är att listan töms, vilket är enda sättet att slippa rita ut linjer som är tillagda sedan innan, då det inte finns något sätt rensa dem utan att rensa hela kartan (och alla kartpunkter därtill). Därefter skapas ett objekt av typen PolyLineOptions, som kan ta en samling koordinater vilka den kan använda att rita en linje mellan alla koordinater. Linjerna ritas sedan ut på kartan.

En översikt av hur CustomMapRenderer förhåller sig till övriga klasser finns i figur 4.1.

4.1.8 Data PointDatabase

Den här klassen kopplar ihop appen med databasen genom att tillhandahålla metoder för att lägga till och ta bort objekt på olika sätt.

När ett objekt av databas-klassen skapas så skapas också de tabeller som behövs i

databasen. I det här fallet behövs bara en tabell, då vi bara har objekt av typen

PointOfInterest att spara. Att jobba mot databasen görs med hjälp av ORM[Incu].

(46)

ORM står för Object Relational Mapping och innebär att man tillåts spara objekt i en SQL-databas utan att använda SQL-frågor [Incu]. Databasklassen använder sig av SQLite.NET’s hjälpbibliotek, som bland annat tillhandahåller funktioner för att skapa (CreateTable), lägga till (Insert), ta bort (Delete) och hämta (Get eller via Table). Dessutom kan man via metoden Query skriva SQL-frågor om man skulle behöva göra något specifikt, som inte finns i hjälpbiblioteket. I PointDatabase behövs detta bara göras i en metod, då en specifik typ av plats efterfrågas, tex en rutt eller en uthyrning, då alla olika typer lagras i samma tabell.

Resten av metoderna i PointDatabase använder sig av ORM-bibliotekets metoder och klarar av att hämta alla objekt i databasen, lägga till i databasen, hämta ett specifikt objekt via ID, ta bort ett specifikt objekt via id samt ta bort alla objekt.

När man accessar databaser måste man se till att samma databas inte samtidigt kan accessas från en annan tråd, därför använder alla metod en låsmekanism, som i appen kallas locker. Om alla databasanrop omges av samma låsning kommer inget anrop att kunna göras samtidigt som ett annat då det anrop som görs först kommer att låsa tillgången för alla rader kod som omges av låsningen oavsett var den utförs.

Man måste dessutom se till att all kod som omges av en låsning är simpel. Skulle

man tex råka anropa en metod utanför den egna låsningen som också har en låsning

fastnar programmet i låsningen [Inck].

(47)

5 Resultat och Utvärdering

5.1 Introduktion

Resultatet består av två delar, där en del är implementationen och den andra en utvärdering av utvecklingsmiljön som implementationen skrivits i.

5.2 Implementationsbeskrivning

Implementationen, eller appen, som är tänkt som ett hjälpmedel för paddelintresserade, fungerar till fullo på Android och med begränsningar på Windows Phone och kan visa olika typer av intressepunkter knutna till paddling på två olika sätt, karta och lista.

När appen startas sker anrop till det underliggande API som hanterar enhetens GPS och kan ta fram en geografisk plats. Denna plats sparas och uppdateras sedan när när platsen ändras, alltså när enheten flyttas, eller mer korrekt, när GPS-koordinaterna uppdateras.

Den första sidan som visas är menyn som ses i figur 5.1. Menyn har tre knappar för olika alternativ, visar en titel och en kort vägledningstext. Varje knapp tar användaren vidare till en ny sida där intressepunkter presenteras på olika sätt. Den första knappen tar användaren till kartsidan, den andra till listan och den tredje till en sida där rutter som finns i användarens närhet presenteras. Sidan är en navigationssida och har därför också en meny längst upp som fungerar som en navigationsmeny, inte olikt den i en webläsare.

Den enda knappen som existerar där som standard är en knapp som indikerar att man är på första sidan. Navigationsmenyn stannar genom alla sidor eftersom navigationen sker med hjälp av att den sida som öppnas läggs på navigationsstacken och ligger ovanpå den första sidan. När detta sker byts knappen i navigationsmenyn mot en bakåtknapp och indikerar detta med en bakåtpil, så att användaren ser att den inte längre är på första sidan. Navigationsmenyn kan dessutom användas för att lägga till knappar om så önskas, vilket syns på nästa sida.

Kartsidan som syns i figur 5.2 visar enbart en karta, på vilken de intressepunkter som

(48)

finns inom kartans område visas. Användaren kan klicka på punkter på kartan för att få upp mer info, såsom en dragen rutt och informationsruta, som även i sin tur går att klicka på för att ta sig vidare till en detaljsida för vald punkt. I menyn syns även ett antal knappar som kan användas för att filtrerar resultaten på kartan så att dessa enbart visar en viss typ av punkt, om man exempelvis skulle vara intresserad av att bara se alla uthyrningsställen.

Listsidan visar enligt figur 5.3 en lista över intressepunkter och erbjuder samma fil- trering som kartsidan. Även här tas man till en detaljsida om man klickar på någon av punkterna.

På detaljsidan i figur 5.4 visas lite mer info om en punkt, såsom längd och en beskrivning som lagts in av den som underhåller databasen. Här finns även en mindre karta så att man kan se var punkten är.

Den sista sidan som syns i figur 5.5 är den som visar punkter som finns i närheten. Den visar både en lista och en karta och presenterar den karta som finns inom ett vist avstånd från enhetens position.

Som synes har varje sida kvar navigationsmenyn med vilken man kan backa genom navi- gationsstacken. Det går dessutom att använda telefonens bakåtknappt för samma funktion.

5.3 Utvärdering av app-utvecklingen

Att arbeta i C# och Visual Studio med eller utan Xamarin innebär inga större förändringar, bortsett från en del uteblivna hjälpmedel som lyfts fram i avsnitt 5.4.1. Detta betyder dock inte att det inte finns mycket nytt att lära sig när man börjar utveckla med Xamarin. Det finns det ett flertal API:er [Incw; Incz] som motsvarar de som finns på Android-, iOS och Windowsplattformarna man behöver använda och man behöver viss förståelse för hur Xamarin fungerar [Inct].

När man arbetar med något nytt hålls förväntningarna nere och man försöker vara öp-

pen för att kunna anpassa utvecklingen i takt med att den sker. Det enda som egentligen

förväntades var att det, just för att mycket var så nytt, skulle behövas läsas nästan lika

(49)

Figur 5.1: Startmenyn i implementationen

(50)

Figur 5.2: Kartan i implementationen

(51)

Figur 5.3: Listan i implmentationen

(52)

Figur 5.4: Detailjsidan i implementationen

(53)

Figur 5.5: Punkter i närheten

(54)

mycket som skrivas - och att det skulle dyka upp en hel del oväntade problem. Något som också blivit just som det förväntades. Uppskattningsvis hälften av tiden lagd på implemen- tation har spenderats i Xamarins guider, dokumentation och exempel, inte bara innan, utan också under tiden, som projektet fortskridit. Något som gjorde att tiden lagd på att faktiskt koda blev lidande, då läsandet blev en nödvändig del i arbetet.

Ganska tidigt i projektet, när vidden av Xamarins dokumentation uppdagades, höjdes förväntningarna för resterande delar i implementationen. Det finns, på Xamarins hemsida [Incx] guider och dokumentation för så gott som allt, och det ger ett intryck av att det går att göra nästan allt i Xamarin. Det som saknas kom därför som en lite större överraskning än det borde ha gjort. Att kartorna skulle sakna en del funktionalitet stod klart från början, men hur mycket som skulle saknas var oväntat. Den överlägset största delen tid spenderad på implementationen lades på få kartorna att fungera enligt kravspecen, och då bara för en plattform. Att anpassa kartorna var ju som tidigare diskuterats plattformsspecifikt, och det tog alltför mycket tid bara att få det att fungera på Android för att överväga att göra en liknande insats för Windows Phone. Resten av implementationen gjordes dock för båda plattformarna och även om menyer och listor, i princip allt utom kartan, fungerar på Windows Phone så är appen inte helt användbar för denna plattform utan kartan.

Det har heller inte lagts mycket arbete på att snygga till appens utseende, utan först och främst att få funktionerna att fungera, vilket de också gör. Appen har många vägar att utvecklas vid projektets slut, och kanske också kommer göra det. Men projektet avslutas med en fullt användbar app.

5.4 Utvärdering av Xamarin

Ett av de uttalade målen med projektet var att genom att använda Xamarin för att utveckla

en app sedan kunna utvärdera Xamarin som mjukvara. Som beskrivits används Xamarin

för att skriva appar till Android och iOS i C#, precis som Windows Phone, och erbjuder

dessutom möjligheten att dela kod mellan projekt i det fall då man vill skriva sin app

(55)

till fler än en plattform. Hur väl detta fungerar är den första delen av utvärderingen, och bedöms utifrån hur väl Xamarin har fungerat för just den app som kodats i detta projekt. Även om appen är förhållandevis begränsad i användningsområde och tiden till utveckling varit begränsad till ett examensarbete har appen fått använda många olika element både i bakomliggande kod och användargränssnitt, samt har en bakomliggande databas, så Xamarin och dess funktioner har utnyttjats med bredd.

Den andra delen av utvärderingen gäller beslutet att använda Xamarin.Forms istället för att utveckla användargränssnitt för varje app för sig. Xamarin.Forms är alltså det bibliotek som Xamarin erbjuder som ett alternativ till plattformsspecifika användargränssnitt och innehåller de allra flesta [Incy] kontroller som återfinns i de olika plattformarna så att man som utvecklare bara behöver koda en typ av användargränssnitt, vilket sedan översätts av Xamarin till varje specifik plattform. Det finns med Xamarin.Forms möjlighet att båda använda XAML och C# [Incaa] samt anpassa sin app till MVVM [LeB].

5.4.1 Diskussion kring Xamarin

Till att börja med måste nämnas att Xamarin är under ständig utveckling och funktioner som inte funnits tillgängliga under appens utveckling skulle mycket väl kunna vara under utveckling och finnas tillgängliga i framtiden [Jas; Staa]. Till exempel introducerades Xa- marin.Forms i samband med släppet av Xamarin 3 bara tre månader innan projektet drog igång [Fri].

Den övergripande upplevelsen har under projektets gång varit att Xamarin är ett verk- tyg med vilket man kan spara både tid och resurser när man utvecklar för fler plattformar genom att bara behöva skriva stora delar av koden en gång, istället för två eller tre, men att man noga bör planera i vilken utsträckning Xamarin används och vilka funktioner man vill nyttja för inte hamna i en situation där tiden man förväntas spara på att använda Xamarin går åt till att lösa oväntade svårigheter.

Efter att ha använt Xamarin i projektet har både fördelar och nackdelar med att an-

References

Related documents

Ser du spår från djur, till exempel hål från hackspettar, djurspillning, rutter från olika kryp eller finns det spår av människor i omgivningen. Du kan samla ett barr eller en

I Tabell 7-27 nedan beräknas körtiden för slingan och hur många rutter som behövs för att täcka kapacitetsbehovet, alltså antal ärenden för område I under mars 2017.. Tabell

Denna parameter skulle kunna vara ett ”skall- krav”, men då det inte framkommit om andra lik- värdiga lösningar finns för att optimera rutter valdes att istället vikta

Livsmedelsverket råder även till att salladsutbudet bör bestå av minst två C-vitaminrika livsmedel, till exempel paprika, apelsin och blomkål, bland annat för att främja upptaget

Anslut trådlöst appen till utrustningen för att överföra dina rutter och markörer och uppdatera dina plottersjökort. Parkoppla appen med en kompatibel AISmottagare för att

Fotbollsdomaren måste därmed inte bara i sin roll som hierarkisk ledare dela ut ansvarsområden till sina assisterande fotbollsdomare, utan även implementera en förståelse

Denna parameter skulle kunna vara ett ”skall-krav”, men då det inte framkommit under examensarbetets gång ifall andra likvärdiga lösningar finns för att optimera rutter valdes

Dijkstra´s algoritm [2] konstruerar utifrån en startnod ett SPT (Shortest Path Tree) som innehåller de kortaste rutterna från startnoden till varje nod i grafen [6].. För