Implementation av prototyp för inomhuspositionering Prototype Implementation for Indoor Positioning

Implementation av prototyp för inomhuspositionering  Prototype Implementation for Indoor Positioning
Detta examensarbete har utförts i samarbete med
Connecta AB
Handledare på Connecta AB: Johan Ljung
Implementation av prototyp för inomhuspositionering
Prototype Implementation for Indoor Positioning
DAN ANDERSSON
Examensarbete inom
Elektroteknik
Grundnivå, 15hp
Handledare på KTH: Ibrahim Orhan
Examinator: Thomas Lindh
Skola för teknik och hälsa
TRITA-STH 2013.39
Kungliga Tekniska Högskolan
Skolan för teknik och hälsa
136 40 Handen, Sweden
http://www.kth.se/sth
i
ii
SAMMANFATTNING
Utveckling av teknik skapar ständigt nya möjligheter men innebär också stora förändringar för företag och organisationer. Mobiltelefoner, surfplattor, bärbara datorer, mobilkommunikation och
molnteknik gör det möjligt idag att inte längre vara bunden av tid, plats eller en enhet för att kunna
arbeta. Förändringen innebär att en ny typ av flexibla och yteffektiva kontor med inga fasta arbetsplatser blir allt vanligare. Problemet med de så kallade flexkontoren är att veta var eller när en kollega befinner sig på kontoret är inte lika självklart, framförallt om det är stort kontor med flera våningsplan.
Målsättningen med detta arbete är att ta fram och implementera en inomhuspositioneringstjänst
eller en så kallad Location-Based Service, till företaget Connecta AB. Tjänsten ska göra det möjligt
för användare att med hjälp av sin mobiltelefon dela med sig av sin nuvarande arbetsplats i en kontorsmiljö.
Resultatet av arbetet är en Location Based Service som gör det möjligt för en användare att med
hjälp av en Androidtelefon med stöd för kortdistanskommunikationstekniken Near Field Communcication att dela med sig av sin nuvarande arbetsplats. Den molnbaserade serverlösningen Windows
Azure används för att lagra registrerade arbetsplatser.
iii
iv
ABSTRACT
Development of technology constantly creates new opportunities but it can also mean major changes for companies and organizations. Today phones, tablets, laptops, mobile communications and
cloud technology make it possible to be no longer bound by the time, location or device in order to
work. The change means that a new office type that is more flexible and space efficient due to no
fixed workplaces, is becoming more common. A problem with this type of offices that are known as
flex-offices is that it is not obvious where or when a colleague is in the office, especially if it is large
office with multiple floors.
The aim of this work is to develop and implement a Location-Based Service for the company Connecta AB. The service will enable users to use their mobile phone to share their current workplace
location in an office environment.
The result of this work is a Location-Based Service that enables a user to use an Android phone
with support for Near Field Communcication to share their current workplace position. The cloudbased server solution, Windows Azure is used to store indexed workplace positions.
v
vi
FÖRORD
Efter tre års studier kan denna rapport med nöje lämnas in som resultat av det examensarbete
som krävs för högskoleingenjörsexamen i Elektroteknik från KTH, Campus Haninge.
Stort tack till företaget Connecta och handledare Johan Ljung på företaget för möjligheten att
göra denna uppgift och för hjälp och vägledning. Stöd från kollegorna Mimmi Eriksson, Jim Nyström och Anna Tillander samt från klasskamrater har varit till stor hjälp. Slutligen riktas ett
tack även till handledare Ibrahim Orhan som stöd och vägledning.
vii
viii
INNEHÅLL
1 Inledning ................................................................................................................................................................................. 1
1.1 Bakgrund ........................................................................................................................................................................ 1
1.2 Målformulering ............................................................................................................................................................ 1
1.3 Avgränsningar .............................................................................................................................................................. 2
1.4 Lösningsmetoder ......................................................................................................................................................... 2
1.5 Kravspecifikation ........................................................................................................................................................ 2
1.5.1 Funktionella krav ................................................................................................................................................ 2
1.5.2 Icke-funktionella krav ....................................................................................................................................... 2
2 Nulägesbeskrivning ............................................................................................................................................................ 3
3 Positioneringstekniker ...................................................................................................................................................... 5
3.1 WLAN ............................................................................................................................................................................... 5
3.1.1 Topologier .............................................................................................................................................................. 5
3.1.2 Cellbaserad positionering ............................................................................................................................... 8
3.1.3 Avståndsbaserad positionering .................................................................................................................... 8
3.1.4 Vinkelbaserad positionering ........................................................................................................................ 11
3.1.5 Mönsterbaserad positionering .................................................................................................................... 12
3.2 NFC .................................................................................................................................................................................. 15
3.2.1 RFID ........................................................................................................................................................................ 15
3.2.2 NFC-taggar ........................................................................................................................................................... 16
3.2.3 Aktiva NFC-enheter.......................................................................................................................................... 16
3.2.4 NFC Data Exchange Format .......................................................................................................................... 17
3.2.5 NFC-positionering ............................................................................................................................................ 17
3.3 Val av positioneringsteknik .................................................................................................................................. 18
4 Mobila plattformar ............................................................................................................................................................ 21
4.1 iOS .................................................................................................................................................................................... 21
4.2 Android .......................................................................................................................................................................... 21
4.3 Windows Phone ......................................................................................................................................................... 21
4.4 Val av mobilplattform .............................................................................................................................................. 22
5 Serverlösning ....................................................................................................................................................................... 23
5.1 On-premise .................................................................................................................................................................. 23
5.2 Molnbaserad ................................................................................................................................................................ 23
ix
5.3 Val av serverlösning ................................................................................................................................................. 23
6 Kartografi .............................................................................................................................................................................. 25
7 Implementation .................................................................................................................................................................. 27
7.1 NFC-taggar ................................................................................................................................................................... 27
7.2 Androidapplikation .................................................................................................................................................. 28
7.2.1 Aktiviteter ............................................................................................................................................................ 28
7.2.2 Klassbeskrivningar........................................................................................................................................... 30
7.3 Windows Azure .......................................................................................................................................................... 33
7.3.1 Registrera Utvärderingskonto ..................................................................................................................... 33
7.3.2 Skapa en mobiltjänst ....................................................................................................................................... 33
7.3.3 Konfigurera tidsjobb ....................................................................................................................................... 33
7.3.4 Konfigurera push-notiser .............................................................................................................................. 34
7.4 Tester ............................................................................................................................................................................. 35
7.4.1 Registrering vid ledig arbetsplats .............................................................................................................. 35
7.4.2 Registrering vid upptagen arbetsplats .................................................................................................... 36
7.4.3 Avregistrering vid befintlig arbetsplats .................................................................................................. 36
7.4.4 Registrering i ledigt mötesrum ................................................................................................................... 37
7.4.5 Registrering i upptaget mötesrum ............................................................................................................ 37
7.4.6 Avregistrering i mötesrum ........................................................................................................................... 37
7.4.7 Sökning av användare ..................................................................................................................................... 38
7.4.8 Tidsbaserad avregistrering .......................................................................................................................... 38
8 Resultat och diskussion ................................................................................................................................................... 39
8.1 Arkitektur ..................................................................................................................................................................... 39
8.2 Tester ............................................................................................................................................................................. 40
8.3 Problem ......................................................................................................................................................................... 40
9 Slutsats ................................................................................................................................................................................... 41
10 Rekommendationer ....................................................................................................................................................... 43
Referenser ................................................................................................................................................................................ 45
Appendix ................................................................................................................................................................................... 51
x
1 INLEDNING
1.1 BAKGRUND
Navigationsförmåga har varit till stor betydelse för människans förmåga att utforska världen. Detta
har möjliggjort interaktion och utbyte mellan olika kulturer, geografisk expansion (genom krig och
kolonisering) och ekonomisk utveckling genom handel.
Idag är navigationsförmågan fortfarande viktig, men den senaste tiden har helt nya positionsbaserade tjänster uppkommit. Orsaken är framförallt att tillgången till positionsinformation har ökat
explosionsartat på grund av satellitnavigationssystemet Global Positioning System (GPS). Men även
utvecklingen av mobila enheter såsom bärbara datorer, mobiltelefoner och läsplattor har bidragit
till att nya positionsbaserade tjänster så kallade Location-Based Services (LBS) har uppkommit.
En LBS bygger på en kombination av teknikerna trådlös kommunikationsteknologi, kartografi, positioneringsteknik och databasteknik. Tillsammans resulterar teknikerna i tjänster där människors
eller objekts position används för att tillföra ett mervärde exempelvis positionsrelevant marknadsföring eller väderinformation [1]. Den positionsbaserade tjänsten Foursquare är ett exempel på en
sådan tjänst som gör det enkelt att dela med sig av en favoritplats till vänner och bekanta [2].
Företaget Connecta vill ta fram en LBS för flexkontor där målsättningen är att ska bli enklare för
användare att hitta varandra. Ett flexkontor består av olika miljöer såsom traditionella öppna kontorslandskap, vardagsrumsliknande rum, mötesrum och ofta någon form av tyst zon [3].
1.2 MÅLFORMULERING
Den övergripande målsättningen med arbetet är att ta fram och implementera en LBS som gör det
möjligt för en användare att med hjälp av sin mobiltelefon dela med sig av sin nuvarande arbetsplats. För att uppnå detta har arbetet delats in i följande delmål:




LBS-tjänsten ska uppfylla de krav som specificeras i kapitel 1.5. För att verkställa att kraven
uppfylls ska funktionella tester och ett användartest utföras.
Teorin bakom minst två olika positioneringstekniker ska undersökas. Vikt läggs vid att undersöka funktonalitet, noggrannhet av positionering, komplexitet att implementera och tillgänglighet på olika mobila plattformar.
Minst tre mobila plattformar ska undersökas ur ett utvecklarperspektiv. Med det menas vad
som krävs för utveckla mot respektive plattform, vilka resurser som finns som stöd och vilken plattform har störst marknadsandel.
Fördelar och nackdelar med två olika serverlösningar ska undersökas och jämföras.
1
1.3 AVGRÄNSNINGAR
I detta examensarbete tas ingen hänsyn till de säkerhetsaspekter som kan vara aktuella vid implementation av en LBS.
Arbetets omfattning är tio veckors heltidsarbete. Inlämningsdatum för rapporten är den 22 maj
2013.
1.4 LÖSNINGSMETODER
För att uppnå arbetets målsättningar utförs en litteraturstudie av de tekniker som krävs för att implementera en LBS. Teknikerna analyseras och jämförs utifrån den erhållna kravspecifikationen.
Implementationen kontrolleras med funktionella tester som verifierar om kravspecifikationen uppfylls. Identifierade förbättringsförlags sammanställs och redovisas.
1.5 KRAVSPECIFIKATION
Kraven och önskemålen togs fram i sammarbete med handledare på företaget Connecta AB utifrån
följande användarfall:



En användare av tjänsten ska kunna registrera sin närvaro vid en arbetsplats
En användare av tjänsten ska kunna registrera sin närvaro i ett mötesrum
En användare av tjänsten ska kunna söka efter andra användares registrerade position (vid
vilken arbetsplats eller i vilket mötesrum den specificerade användaren befinner sig).
1.5.1 FUNKTIONELLA KRAV



Registrering vid arbetsplats
o Endast en användare ska kunna vara registrerad vid en arbetsplats åt gången.
o En användare som är registrerad vid en arbetsplats och registrerar sig vid en ny arbetsplats, avregistreras automatiskt på den gamla arbetsplatsen.
o En arbetsplats som har varit registrerade till en användare i mer än 12 timmar i
sträck, avregistreras automatiskt.
Registrering i mötesrum
o I ett mötesrum ska flera användare kunna vara registrerade åt gången.
o Användaren ska kunna ange hur länge mötet kommer att pågå.
Sökning
o Användares namn ska vara sökbara och returnera vid en sökträff den specificerade
användarens position på en planritning.
1.5.2 ICKE-FUNKTIONELLA KRAV

Användarvänlighet ska eftersträvas, i den formen av att en ny användare snabbt och enkelt
kan ta till sig och börja använda tjänsten.
2
2 NULÄGESBESKRIVNING
Utveckling av teknik skapar ständigt nya möjligheter men innebär också stora förändringar för företag och organisationer. Mobiltelefoner, surfplattor, bärbara datorer, mobilkommunikation och
molnteknik gör det möjligt idag att inte längre vara bunden av tid, plats eller en enhet för att kunna
arbeta. Eller som företaget Microsoft beskriver denna förändring som de kallar Det nya arbetslivet:
”Vi måste tillåta oss själva att arbeta på ett nytt sätt. Där jobbet i första
hand är något vi gör, och inte en plats vi går till.” - Microsoft [4]
Utvecklingen innebär att arbetsplatser måste förändras och bli flexiblare. Det är inte längre lika
självklart att alla ska ha en egen fast arbetsplats eftersom det nya arbetssättet innebär att företags
kontor utnyttjas mindre vilket i sin tur kan innebära onödiga kostnader. Därför blir det allt vanligare idag med så kallade flexkontor där kontorsyta kan utnyttjas effektivare eftersom fria placeringar och inga fasta arbetsplatser finns. Men flexkontor i sig innebär också nya utmaningar för
företag och organisationer. Att veta var eller när en kollega befinner sig på kontoret är inte lika
självklart, framförallt om det är stort kontor med flera våningsplan.
Företaget Connecta har som affärsidé att hjälpa företag och organisationer att förändras för att nå
uppsatta mål genom att kombinera kompetens inom både management och IT. Företaget har själv
varit en del av förändringen som beskrivs ovan och verksamheten bedrivs idag i ett flexkontor. På
grund av detta och eftersom Connecta arbetar med att hjälpa företag och organisationer att förändras vill företaget implementera en LBS som underlättar för användare av tjänsten att hitta
varandra.
3
4
3 POSITIONERINGSTEKNIKER
Kännedomen om människors eller objekts position är det som tillför mervärde till en LBS-tjänst så
är det extra viktigt att rätt positioneringsteknik används. Positionering av människor eller objekt
baseras på olika trådlösa teknologier såsom:






Wireless Local Area Network (WLAN) [5]
Radio Frequency Identification (RFID) [6] [7]
Ultrawide Band (UWB) [8]
Infraröd strålning (IR) [9]
Visible Light Communication (VLC) [10] [11]
Ultraljud [12]
I detta kapitel beskrivs positionering baserat på WLAN och Near Field Communication (NFC) som
båda är två trådlösa teknologier som finns tillgängliga på flera mobila plattformar. NFC är en standard för trådlös överföring över korta avstånd som bygger på RFID [13].
3.1 WLAN
WLAN är en nätverksinfrastruktur för trådlös kommunikation baserad på standardfamiljen IEEE
802.11. WLAN använder en arkitektur som förlitar sig på en uppsättning accesspunkter för att underlätta kommunikation mellan enheter i nätverket och mellan nätverket och Internet. Accesspunkter i ett WLAN sänder periodvis ut signaler som innehåller kommunikationsrelaterad information. Informationen består bland annat av en tidsstämpel, information om utbredningsdämpning,
vilka datahastigheter som stöds och accesspunktens unika identifierare, den så kallade Basic Service
Set Identifier (BSSID). Utöver den inbäddade informationen i de utsända signalerna kan också signalernas styrka mätas. Positionering i ett WLAN baseras på informationen från de utsända signalerna
och dess signalstyrka.
3.1.1 TOPOLOGIER
WLAN-positionering kan baseras på tre olika topologier, nätverksbaserad, terminalbaserad och terminalassisterad topologi [14]. En nätverksbaserad topologi fungerar endast om mjukvaran på nätverkets accesspunkter modifieras så att information kan skickas vidare till en server. En accesspunkt (B) i en nätverksbaserad topologi mäter ofta mottagen signalstyrka från en mobil enhet (C)
och skickar resultatet vidare tillsammans med kommunikationsrelaterad information till en server
(A) (Figur 1). På servern utförs algoritmer och lagrad information på en databas används för att
bestämma en mobil enhets position. Eftersom alla beräkningar och mätningar sker på nätverkssidan i nätverksbaserad topologi behöver mobila enheter endast sända signaler till accesspunkterna.
Detta gör att det är möjligt att implementera nätverksbaserad WLAN-positionering utan att mjukvara behövs på mobila enheter. Användare i en sådan topologi kan därför positioneras utan deras
kännedom.
5
A
B
B
B
C
Figur 1 - Nätverksbaserad topologi för WLAN-positionering. Insamling av kommunikationsinformation, mätning av mottagen signalstyrka från en terminal (C) utförs på flera accesspunkter (B). Accesspunkterna vidarebefordrar insamlad data till en server (A) där beräkningar för att bestämma
en position utförs.
En terminalbaserad topologi fungerar på motsatt vis, en mobil enhet (B) tar emot signaler från accesspunkter (A) och utför mätningar (Figur 2). Information såsom referenspositioner lagras i en
databas på den mobila enheten. Informationen kan tillsammans med beräkningar och algoritmer
som utförs på den mobila enheten användas för att bestämma enhetens position. Den mobila enheten kan aktivt skicka signaler till accesspunkter och vänta på svar och använda den mottagna
signalen för att utföra mätningar. Alternativt kan den mobila enheten vänta på att accesspunkten
skickar ut signaler, vilket ofta görs periodvis. De båda metoderna kallas aktiv respektive passiv terminalbaserad topologi.
6
A
A
A
B
Figur 2 - Terminalbaserad topologi för WLAN-Positionering. Insamling av kommunikationsinformation, mätning av mottagen signalstyrka från flera accesspunkter (A) och beräkningar för att bestämma en position utförs på en terminal (B).
En terminalassisterad topologi är en mix mellan en nätverksbaserad och terminalbaserad topologi.
Skillnaden är att en mobil enhet (B) utför endas mätningar av mottagen signalstyrka och samlar in
kommunikationsrelaterad information från accesspunkterna (A). Insamlad data skickas därefter
vidare till en server (C) där algoritmer utförs och lagrad information på en databas används för att
bestämma en mobil enhets position. (Figur 3).
A
A
A
B
C
Figur 3 - Terminalassisterad topologi för WLAN-positionering. Insamling av kommunikationsinformation och mätning av mottagen signalstyrka från flera accesspunkter (A) utförs på en terminal
(B) som sedan vidarebefordrar insamlad data till en server. På servern (C) utförs beräkningar för
att bestämma en position.
7
Positionering baserat på WLAN kan implementeras med följande tekniker:




Cellbaserad
Avståndsbaserad
Vinkelbaserad
Mönsterbaserad
3.1.2 CELLBASERAD POSITIONERING
Cellbaserad WLAN-positionering eller Cell of Origin är en av de enklaste och snabbaste metoderna
eftersom inga beräkningar eller algoritmer krävs för att bestämma en mobil enhets position. En
enhets positions bestäms enklast baserat på en accesspunkts räckvidd och position. När en mobil
enhet är inom en accesspunkts räckvidd registreras enheten. Den mobila enhetens position antas
då vara i närheten av accesspunktens position (Figur 4). Problemet är att den närmsta accesspunkten inte alltid behöver väljas vilket kan leda till att en mobil enhet associeras till fel accesspunkt.
Detta kan vara ett extra stort problem om tekniken ska användas för att positionera mobila enheter
över flera våningsplan. En förbättring som kan göras är att en mobil enhet istället associeras med
den accesspunkten med starkast signalstyrka. Förbättringen kräver att signalstyrka mäts för att
fungera.
Cell A
Cell B
Cell C
Figur 4 - Cellbaserad WLAN-positionering. En mobil enhet registreras till en accesspunkt och enhetens position approximeras då till accesspunktens cell (Cell A).
3.1.3 AVSTÅNDSBASERAD POSITIONERING
Avståndsbaserad WLAN-positionering kan implementeras på två olika sätt:


Cirkulär lateration
Hyperbolisk lateration
8
Cirkulär lateration använder avståndet mellan en mobil enhet och minst tre accesspunkter med
kända positioner för att bestämma den mobila enhets position. För att beskriva metoden används
följande modell: En accesspunkts position beskrivs som centrum på en cirkel (A) och avståndet
mellan accesspunkten och en mobil enheten är cirkelns radie (B). Den mobila enheten kan då antas
befinna sig någonstans på cirkelns utkant. För att minska antalet möjliga positioner som den mobila
enheten kan befinna sig på så beräknas avståndet till en annan accesspunkt inom räckhåll. Med två
accesspunkter kan den mobila enheten antas befinna sig på två positioner, där cirklarna runt accesspunkterna skär varandra. Med en tredje accesspunkt kan slutligen en position bestämmas där alla
tre cirklar skär varandra (Figur 5). Matematisk kan metoden beskrivas som att avstånden ri mellan
en mobil enhet och accesspunkterna i = 1, . . ., n är kända. För att beräkna den mobila enhetens position används en tillämpning av Pythagoras sats som kallas avståndsformeln. Om Xi och Yi antas
vara de kända koordinaterna för accesspunkt i och x och y är den sökta mobila enhetens koordinater. Utifrån detta kan avståndet ri mellan accesspunkt i och den sökta mobila enheten utryckas med
följande ekvation [15]:
√(
)
(
)
Accesspunkt
B
Mobil enhet
A
(X1,Y1)
(x,y)
(X2,Y2)
(X3,Y3)
Figur 5 – Cirkulär lateration. Positionen för en mobil enhet bestäms genom att avståndet till minst
tre accesspunkter med kända positioner mäts. En accesspunkts position beskrivs som centrum på
en cirkel (A) och avståndet till den mobila enheten som radien på cirkeln (B). Den mobila enhetens
position är då där de tre cirklarna skär varanda.
Avståndet mellan en mobil enhet och en accesspunkt kan bestämmas på två olika sätt:


Time of Arrival (ToA)
Mottagen signalstyrka
ToA baseras på ankomstiden för en signal. Eftersom signaler överförs med en känd hastighet (cirka
300 m/µs) kan avståndet mellan en mobil enhet och en accesspunkt bestämmas genom att mäta
propageringstid. För att metoden ska fungera måste klockor som används för tidtagning vara synkroniserade. Eftersom överföring sker i väldig hög hastighet, kan väldigt små tidskillnader i synkroniseringen resultera i stor förlust av noggrannhet. Exempelvis kan ett mätfel av tiden på 100
nanosekunder resultera i ett positionsfel på 30 meter. I praktiken är det därför inte möjligt att im9
plementera metoden i WLAN. Däremot en känd positioneringsteknik som använder metoden är
GPS men där används atomklockor för synkronisering.
Avståndet mellan en mobil enhet och en accesspunkt kan också bestämmas med mottagen signalstyrka. Om signalstyrka, kabelförlust och antennförstärkning är givet för den mobila enheten eller
accesspunkten är det möjligt med hjälp av följande formel bestämma avståndet:
(
)
PL är utbredningsdämpningen mellan en accesspunkt och en mobil enhet. PL1 meter är ett referensvärde för utbredningsdämpning vid en bestämd frekvens när avståndet mellan en accesspunkt och
en mobil enhet är en meter. Avståndet i meter mellan den mobila enheten och accesspunkten betecknas som d. Hur mycket en omgivning påverkar utbredningsdämpningen representeras av exponenten n. Ett typisk värde på exponenten för utbredningsdämpning 3.5 i kontorsmiljö, 4.0 i industrimiljö och upp till 4.5 i hemmiljö. Graden fädning i omgivningen representeras av standardavvikelsen s. Måttet representerar variation i signalstyrka, (ibland kallat brus) från källor som inte tas
med i ekvationen. Detta inkluderar faktorer såsom dämpning på grund av antalet hinder, olika positioner på accesspunkter och mobila enheter, reflektioner på grund av flervägsutbredning, och så
vidare. Implementationer där två eller flera antenner används kan reducera den variation av signalstyrka som kan uppstå på grund av fädning och därför rekommenderas det nästa alltid att flera
antenner används.
För att lösa ut avståndet från ekvationen för utbredningsdämpning substitueras den i följande ekvation som bestämmer mottagen signalstyrka:
Vilket resulterar i fölande ekvation:
Detta är möjligt då uppmätt signalstyrka RPWR och TPWR, antennförstärkning RFörstärkning och TFörstärkning,
kabelförluster RFörlust och TFörlust, är givet vid mottagare R och sändare T. Nackdelen med denna metod är att den kan presterar dålig i inomhusmiljöer eftersom bland annat reflektioner som uppstår
på grund av väggar och andra hinder [16].
Hyperbolisk lateration baseras på avståndsskillnader istället för det absoluta avståndet mellan en
mobil enhet och en accesspunkt. Avståndskillnaden kan beskrivas såsom om avståndet mellan en
mobil enhet och en accesspunkt är r1 (A) och avståndet till en annan accesspunkt är r2 (B) så är avståndsskillnaden r2 – r1. Utifrån avståndsskillnad mellan en mobil enhet och två accesspunkter kan
en hyperbel (C) skapas. En hyperbel definieras som en uppsättning av alla punkter där skillnaden i
avstånd mellan två fasta punkter är konstant. Därför kan den mobila enheten antas befinna sig någonstans på hyperbeln. Om avståndet mellan den mobila enheten och ännu en accesspunkt är givet
kan en till hyperbel skapas. Den mobila enhetens kan då antas befinna sig där de båda hyperblerna
skär varandra (Figur 6). Matematisk kan man avståndskillnaden mellan varje accesspunktspar beskrivas med formeln:
10
)
√(
(
)
√(
)
(
)
Där di,j betecknar avståndsskillnaden mellan accesspunkt i och j. Avståndsskillnad kan bestämmas
genom att använda skillnaden i signalers ankomsttid från två accesspunkter till en mobil enhet.
Metoden kallas Time Differens of Arrival (TDoA) [1].
A
C
r3
B
Figur 6 - Hyperbolisk lateration. En hyperbel (C) skapas utifrån avståndsskillnaden mellan en mobil enhet och två accesspunkter och med ännu en accesspunkt skapas en till hyperbel. Den mobila
enhetens position antas då vara vid hyperblernas skärningspunkt.
3.1.4 VINKELBASERAD POSITIONERING
WLAN-positionering som är vinkelbaserad kallas även Angle of Arrival (AoA). Metoden lokaliserar
mobila enheter genom att bestämma den infallsvinkel som en signal anländer till en accesspunkt.
Det krävs att en mobil enhet är inom räckhåll med åtminstone två accesspunkter för att metoden
ska fungera. Ett alternativ för att få metoden att fungera är att motordrivna riktningsantenner används. Antennerna riktas in mot den punkt som ger högst signalstyrka och infallsvinklarna avläses.
Geometriska relationer kan därefter användas för att uppskatta positionen utifrån skärningspunkten mellan två linjer som bildas av en radiell linje från varje accesspunkt (Figur 7).
11
α1
α2
Figur 7 - Vinkelbaserad WLAN-postionering. Utifrån två accesspunkter med motordrivna riktningsantenner där infallsvinkeln kan läsas av kan en mobil enhets position bestämmas. En radiell
linje kan då bildas från varje accesspunkt och där den mobila enhets position kan antas vara vid
linjernas skärningspunkt.
Vinkelbaserad WLAN-positionering kan också implementeras genom att använda accesspunkter
med antenngrupper som kan mäta mottagna signalers fasförskjutning. Tekniken involverar även
TDoA som används för att mäta tidskillnaden då signalen ankommer till olika antennelement i antenngruppen på accesspunkten. På så sätt kan infallsvinkel av signalen bestämmas och den mobila
enhetens position bestämmas med triangulering. Precisonen för vinkelbaserad WLANpositionering påverkas negativt av hinder och därför är metoden bättre anpassad för öppna miljöer.
3.1.5 MÖNSTERBASERAD POSITIONERING
Mönsterbaserad WLAN-positionering även kallat Fingerprinting är en positioneringsteknik som
baseras på insamlad mottagen signalstyrka vid kända referenspositioner. Tekniken kan implementeras enbart genom mjukvara, vilket kan reducera komplexiteten och kostnaden signifikant jämförelsevis mot AoA.
Tekniken bygger på följande grundläggande antaganden:


Att varje potentiell position för mobila enheter har idealt en distinkt och unikt ”RFsignatur”. Desto närmare detta antagande är verkligheten, desto bättre prestanda för det
mönsterbaserade systemet.
Att varje våningsplan har signalutbredning med unika egenskaper. Med detta menas att
trots alla ansträngningar att placera utrustning identiskt, är inga våningsplan, byggnader eller områden verkligen identiska ur perspektivet från en mönsterbaserad lösning.
Det finns två faser i mönsterbaserad WLAN-positionering, en kalibreringsfas och en operativ fas.
Under kalibreringsfasen, samlas data in genom att gå runt i målmiljön med en mobil enhet. En grafisk representation över området som ska kalibreras med överliggande rutnät eller noteringar används vanligvis för att underlätta insamlandet av data (Figur 8). Insamlad data resulterar i posit12
ionsvektorer bestående av signalstyrka associerat med kalibreringsenheten vid varje position som
sparas och lagras i en databas som brukar kallas radio map eller training set. Storleken på en positionsvektor, bestäms av antalet mottagare som upptäcks vid en position.
5025mm
4188mm
(x1,y1) → (-49,-54,-56,-59)
(x2,y2) → (-67,-54,-57,-46)
Figur 8 - Mönsterbaserad WLAN-positionering. En grafisk representation av en planritning som har
kalibreras och där data har insamlats vid två positioner (x1, y1) och (x2, y2).
På grund av bland annat fädning varierar troligtvis den observerade signalstyrkan vid varje samplingsposition. Därför samlas vanligvis mycket data in och kalibreringen utförs över en längre tid.
Det finns olika tekniker för att kompensera för variationen som uppkommer på grund av fädning
och andra fenomen. En vanlig och populär metod som är enkel att implementera är att representera
vektorelement associerat med en specifik mottagare som medelvärdet av alla mätningar av signal
styrkan vid den specifika samplingspositionen. En positionsvektor består då av element som beskriver medelsignalstyrka, som följande ekvation:
(
)
( ̅
̅
̅
̅
)
Där x och y representerar koordinaterna för samplingspositionen och r representerar samplad signalstyrka.
Under den operativa fasen, samlar en grupp mottagare in mätningar av signalstyrka från en spårad
mobil enhet (nätverkssidan) som skickas vidare den informationen till en positionsserver. Positioneringsservern använder komplexa algoritmer och radio map–databasen för att uppskatta den
mobila enhetens position. Servern skickar sedan den uppskattade positionen till en klientapplikation som begär positionsinformationen.
Mönsterbaserad WLAN-positionerings algoritm kan delas in i tre basgrupper:
13



Deterministiska algoritmer försöker hitta det minsta statiskiska signalavståndet mellan en
detekterad positionsvektor och positionsvektorer bestående av olika kalibrerade punkter i
radio map – databasen. Detta kan eller inte vara lika med minsta fysiska avståndet mellan
den mobila enhetens position och den sparade positionen från kalibreringen. Exempel på
deterministiska algoritmer är de som baseras på beräkningar av Euklidisk [17], Manhattan
[18], eller Mahalanobis [19] avstånd.
Probabilistiska algoritmer använder sannolikhetsmodeller för att bestämma sannolikheten
för en viss position givet att en särskild positionsvektor redan har detekteras. Kalibreringsdatabasen betraktas på förhand som en villkorlig sannolikhetsfördelning av algoritmen för
att bestämma sannolikheten för förekomsten av en viss position. Exempel på sådana metoder inkluderar de som använder sig av Bayesiansk statistik [20].
Andra tekniker går utanför gränserna för deterministiska och probabilistiska metoder. Exempel på ett sådant tillvägagångsätt involverar antagandet att mönsterbaserad WiFipositionering är alldeles för komplext att analysera matematiskt och kräver användning av
icke-linjära diskriminanta funktioner för klassificering (neurala nätverk).
För att få förståelse för hur sådana algoritmer fungerar, kan följande enkla exempel som demonstrerar användandet av en deterministisk algoritm undersökas, i detta fall baserad på Euklidisk
avstånd:
Antag att två accesspunkter X och Y och en mobil enhet Z. Accesspunkt X rapporterar signalstyrkan
x1 från den mobila enheten Z. Nästan samtidigt, rapporterar accesspunkten Y signalstyrkan y1 från
den mobila enheten Z. Dessa två samplen kan representeras som en positionsvektor (x1,y1). Förutsätt också att under kalibreringsfasen, har ett stort antal av positionsvektorer i formatet F(x2,y2) där
F representerar de fysiska koordinaterna för en verklig position, lagrats på en positionsserver i en
kalibreringsdatabas. Positionsservern kan beräkna det Euklidiska avståndet d mellan den aktuella
positionsvektorn (x1,y1) som rapporterats och varje positionsvektor i kalibreringsdatabasen. Det
Euklidiska avståndet d kan beräknas med följande formel:
√(
)
(
)
Den uppskattade positionen för den mobila enheten erhålls genom den positionsvektor i kalibreringsdatabasen som ger det minsta Euklidiska avståndet till den aktuella positionsvektorn. De fysiska koordinaterna F som associeras med den positionsvektorn i kalibreringsdatabasen, anses
därför vara den korrekta uppskattningen av den mobila enhetens position.
I likhet till system som baseras på signalstyrka för positionering, så drar även mönsterbaserad
WiFi-positionering nytta av befintlig nätverksinfrastruktur. Detta kan ofta vara en fördel jämfört
mot system baserade på AoA, ToA och TDoA, beroende på implementationen. Metoden är kapabel
att fungera väldigt bra i inomhusmiljöer, med ett minimum på tre stycken rapporterande mottagare
inom mobila enheters räckvidd hela tiden. Förbättrad precision och prestanda är möjligt med sex
till tio mottagare inom mobila enheters räckvidd [15, 16].
14
3.2 NFC
NFC Forum bildades av Philips, Nokia och Sony 2004 för snabba på utvecklingen av tekniken NFC
[21]. NFC Forum har idag över 170 medlemmar från alla områden i NFC. Syftet med NFC är att göra
det enklare att med mobila enheter göra överföringar, utbyta digital data och ansluta till elektroniska enheter endast genom en vidröring. Tekniken bygger på RFID som är en trådlös kommunikationsteknik som används för att identifiera taggade objekt eller människor [22, 23].
3.2.1 RFID
RFID bygger på tre grundkomponenter: taggar, läsare och en kontrollenhet. En RFID-tagg består av
ett halvledarchip, en antenn och ibland ett batteri eller en extern strömkälla. Basfunktioner är att
lagra data och överföra data till en RFID-läsare. Det finns två grundtyper av taggar, passiva utan
batteri och aktiva med batteri.
Passiva RFID-taggar som inte har något batteri använder läsarens utsända signal som energikälla
för att överföra data. Det finns två olika tillvägagångsätt att överföra energi från en läsare till en
tagg: magnetisk induktion och elektromagnetisk vågfångst. Därför är passiva taggar vanligvis
mindre och billigare att tillverka än aktiva taggar. Nackdelen är att överföringsavståndet blir mycket kortare och lagringskapaciteten blir mindre jämfört mot aktiva taggar.
En RFID-läsare är i grund och botten en liten dator med en antenn och RF-kontrollenhet för att
kommunicera med taggar och en modul för att kommunicera med en kontrolenhet. Grunduppgifterna för en RFID-läsare är att läsa från och skriva data till RFID-taggar, skicka till och ta emot data
från en kontrolenhet samt strömförsörja passiva taggar. Mer avancerade läsare kan även implementera antikollision för att möjliggöra kommunikation med flera taggar samtidigt, autentisering
av taggar för att motverka bedrägeri eller otillåten tillgång av system och kryptering av data för
skydda integriteten hos data.
En kontrollenhet är ofta en dator med någon typ av databas och applikation som används för att
sammankoppla flera läsare men framför allt för att processa den data som samlas in av läsare.
RFID fungerar på olika frekvensband och vilken frekvens som används är viktigt att betänka eftersom olika frekvenser påverkar RFID:s egenskaper och prestanda. Frekvensbanden som kan användas kan delas in i ett lågt och ett högt frekvensband:


Lågt frekvensband
o Låg frekvens (LF): 125-134 kHz
o Hög frekvens (HF): 13.56 MHz
Högt frekvensband
o Ultrahög frekvens (UHF): 860-960MHz
o Mikrovågor: 2.5 GHz och över
RFID som använder en frekvens i det låga frekvensbandet kan ha en räckvidd upp till ungefär en
meter. Används frekvenser i det höga frekvensbandet ökar räckvidden och framförallt om aktiva
taggar används. RFID som använder en frekvens i det höga frekvensbandet kan uppnå räckvidder
mellan 10 – 30 meter.
15
Datahastigheten för RFID påverkas också av vilket frekvens som används. Desto högre frekvens
desto högre datahastighet.
Om andra system arbetar på en frekvens i närheten av en frekvens i det låga frekvensbandet, så
finns det stor risk att RFID som arbetar i samma frekvensband, störs ut på grund av att andra system kan ha högre fältstyrka vid läsarens antenn. RFID som arbetar i det höga frekvensbandet löper inte lika stor risk för störningar eftersom det krävs i stort sett en riktad signal som stör ut systemet.
Metaller och vätskor kan också påverka prestandan hos RFID. Om ett system ska arbeta i exempelvis vatten, har RFID som använder HF lättare att penetrera än om UHF används eftersom HF signaler har längre våglängder. Radiosignaler kan inte penetrera metall och efter som metall är en
elektromagnetisk reflektor kan antenner i närheten av metall ändra egenskaper och störas ut. Det
är framför allt RFID som arbetar i det höga frekvensbandet som påverkas mest av metaller.
Den frekvens som används bestämmer också vilka typ av antenn som används samt vilket storlek
som krävs. RFID som arbetar i det låga frekvensbandet använder induktiv koppling och induktiva
antenner medan system i det höga frekvensbandet använder kapacitiv koppling och dipola antenner [24].
3.2.2 NFC-TAGGAR
NFC-taggar baseras på passiva RFID-taggar och kan användas för att lagra data. Det finns fyra olika
bastyper av NFC-taggar som baseras delvis på den internationella standarden ISO 14443 typ A och
B för kontaktlösa smartcards. Bastyperna baseras även på standarden Sony FeliCa (JIS X 6319-4)
för passivt kommunikationsläge (Tabell 1).
Typ 1
Typ 2
Typ 3
Typ 4
ISO/IEC standar
14443 A
14443 A
JIS X 6319-4
14443 A / B
Data hastighet
106 kb/s
106 kb/s
212/424 kb/s
106/212/424
kb/s
Minne
96 bytes,
Kan expanderas
upp till 2 kbyte
48 bytes,
Kan expanderas
upp till 2 kbyte
Varierande, max
1 Mbyte
Varierande, max
32 kbyte
Antikollision
Nej
Ja
Ja
Ja
Tabell 1 - Bastyper av NFC-taggar
3.2.3 AKTIVA NFC-ENHETER
Aktiva NFC-enheter baseras på RFID-läsare och används för läsa och skriva till NFC-taggar. Men
NFC-enheter kan till skillnad från RFID-läsare kommunicera med varandra också. Aktiva enheter
arbetar på frekvensen 13.56 MHz och räckvidden är därför begränsad. Vanligvis är räckvidden för
överföring mindre än fyra centimeter. Eftersom räckvidden är så kort anses överföringar med NFC
vara säkra [13, 25]. Aktiva NFC-enheter är ofta mobila enheter, och tekniken finns implementerad
16
på ett flertal mobiltelefoner och mobila plattformar. Apples mobiltelefon iPhone med mobil platformen iOS stöder dock inte NFC [26]. En lösning är att komplettera en applikation som använder
NFC med stöd för läsning av Quick Response-koder (QR-koder) som även fungerar på plattformen
iOS. QR-koder kan lagra 3kb data [27] och kan enkelt skapas med webapplikationer [28].
3.2.4 NFC DATA EXCHANGE FORMAT
NFC Data Exchange Format (NDEF) är ett meddelandeformat definierat av NFC-forum för kommunikation mellan två aktiva NFC-enheter eller en NFC-enhet och en NFC-tagg. Formaten har utformats för att vara ett lättviktigt binärt meddelandeformat. Ett NDEF-meddelande (A) kan användas
för att kapsla in en eller flera applikationsspecifika datalaster eller så kallade records (B) som kan
vara av olika typer och storlekar. En record består av förutom datalasten en så kallad header med
information som beskriver datalasten (C). Varje datalast beskrivs av en typ, längd och en valfri
identifierare (D) (Figur 9).
A
NDEF Message
B
Record
Record
Header
Payload
Identifier
Length
Record
C
Type
D
Figur 9 – Konstruktionen av ett NDEF-meddelande
3.2.5 NFC-POSITIONERING
NFC-positionering är en enkel metod som kan liknas vid Cellbaserad WLAN-positionering. En referensposition skrivs och lagras i en NFC-tagg som placeras ut vid referenspositionen. När en NFCenhet läser taggen, associeras enheten till den lagrade referenspositionen [15].
17
3.3 VAL AV POSITIONERINGSTEKNIK
Valet av positioneringsteknik för Connectas LBS-tjänst baseras på den redan nämnda kravspecifikationen och på följande kriterier:



Noggrannhet
Komplexitet
Mobila plattformar
Noggrannhet för positionering är ett mått på det kvantifierbara felet på avståndet mellan en uppskattad och verkliga position. LBS-tjänsten som ska implementeras har som krav att en användare
ska kunna registrera sin närvaro vid en arbetsplats och i ett mötesrum. Eftersom en arbetsplats är
cirka 140x72 cm måste positioneringstekniken som implementeras uppnå en noggrannhet på
minst 72 cm.
Eftersom arbetet är tidsbegränsat är även komplexiteten på implementation en avgörande faktor.
Hur komplex en positioneringsteknik anses vara att implementera baseras på följande frågor:






Krävs ny infrastruktur och sådana fall vad?
Krävs beräkningar och algoritmer för att bestämma positioner?
Krävs mätning av signalstyrka?
Krävs förberedelser och i sådana fall vad?
Krävs modifiering av mjukvara på accesspunkter?
Krävs synkronisering?
Tillgänglighet baseras på vilka mobila plattformar som positioneringstekniken kan implementeras
på. Mobila plattformar som kontrolleras har avgränsas till iOS, Android och Windows Phone.
Se Tabell 2 för en sammanställning av positioneringsteknikerna.
18
Positioneringsteknik
Noggrannhet
Komplexitet
Mobila plattformar
Cellbaserad WLANpositionering
25 – 200
meter [14]
Avståndsbaserad
WLAN-positionering
– ToA
Avståndsbaserad
WLAN-positionering
– Mottagen signalstyrka
Avståndsbaserad
WLAN-positionering
– TDoA
Vinkelbaserad
WLAN-positionering
-
Mätningar av signalstyrka.
Databas med accesspunkters position
och BSSID.
Exakt synkronisering krävs
iOs
Android
Windows Phone
iOS
Android
Windows Phone
iOS
Android
Windows Phone
Mönsterbaserad
WLAN-positionering
1.5 m – 10 m
[15]
NFC-positionering
0 – 4 cm
3 – 6 meter
[29]
Mätningar av signalstyrka
Cirkulär lateration används för att bestämma positionen
-
Exakt synkronisering krävs
Hyperbolisk lateration används för att
bestämma positionen
Motordrivna antenner krävs eller antenngrupper
Ca 2 m [30]
[31]
Algoritmer krävs
Signalstyrka måste mätas
Kalibrering måste utföras på referenspositioner
Positionsinformation måste skrivas till
och lagras på NFC-taggar
iOS
Android
Windows Phone
iOS
Android
Windows Phone
iOS
Android
Windows Phone
Android
Windows Phone
(Kompletteras metoden med stöd för
QR-koder kan tekniken implementeras på iOS också)
Tabell 2 - Sammanställning av positioneringstekniker
Fördelen generellt med WLAN-positionering är främst tillgängligheten eftersom de flesta mobila
enheter och mobila plattformar har stöd för WLAN. Det finns även i det flesta lokaler en redan väl
etablerad nätverksinfrastruktur. Den cellbaserade WLAN-positioneringstekniken är den enklaste
implementationen men har alldeles för dålig noggrannhet då den begränsas till antalet accesspunkter och deras räckvidd. De avståndsbaserade metoderna ToA och TDoA kräver exakt synkronisering för att fungera och är därför i praktiken inte möjliga att implementera. Även om den avståndsbaserade metoden som använder signalstyrka för att bestämma positionen på en mobil enhet är
möjlig att implementera så är den bättre lämpad för utomhusbruk eller öppna inomhusmiljöer.
Detta eftersom metoden påverkas negativt av väggar och andra hinder. Den vinkelbaserade WLANpositioneringsmetoden påverkas också av väggar och hinder. Metoden kräver dessutom modifieringar av hårdvara. Den vanligaste WLAN-positioneringsmetoden som används för inomhuspositionering är den mönsterbaserade. Metoden har som fördel att den kan implementeras endast genom mjukvara samt att noggrannheten är den bästa bland de olika WLANpositioneringsteknikerna. Nackdelen med metoden är att det krävs att kalibrering utförs under en
längre tid vid alla referenspositioner för att uppnå bra noggrannhet.
19
NFC-baserad positionering har noggrannhet på 0 – 4 cm eftersom noggrannheten bestäms av antalet taggar utplacerade och räckvidden på en aktiv NFC-enhet. Eftersom räckvidden på en aktiv NFCenhet är vanligvis mindre än 4 cm krävs att användaren av enheten befinner sig vid NFC-taggen för
att läsa av den. Metoden är väldigt enkel att implementera och stöd för de specificerade mobila
plattformarna kan erhållas metoden kompletteras med QR-kod stöd. NFC-baserad positionering
används därför i implementationen.
20
4 MOBILA PLATTFORMAR
I detta kapitel undersöks tre företags mobila plattformar ur ett utvecklarperspektiv: Apples iOS,
Googles Android och Microsofts Windows Phone.
4.1 IOS
iOS är det operativsystem som används på Apple iPhone, iPad och iPod touch [32]. För att utveckla
applikationer för iOS används iOS Software Development Kit (iOS SDK) och utvecklingsmiljön Xcode.
Dessutom krävs en Intelbaserad Mac med operativsystemet Mac OS X Snow Leopard eller en senare
version installerat och det krävs också ett Apple Developer-konto. Ska dessutom applikationen testas på hårdvara krävs ett medlemskap i iOS Developer Program vilket kostar 99 dollar per år [33].
Eftersom plattformen inte stöder NFC så är det inte möjligt att implementera RFID-positionering
där NFC-används. Det finns en mängd med litteratur som beskriver programmering av applikationer i iOS [34] men den främsta resursen för utvecklare är iOS Dev Center [35].
4.2 ANDROID
Android är ett operativsystem baserat på Linux som skapades av Android Inc. men blev uppköpt av
Google [36]. Plattformen är baserad på öppen källkod och licensieras under licensen Apache Software License, 2.0 [37]. Eftersom plattformen är öppen använder flera tillverkare Android som operativsystem på mobiltelefoner och surfplattor [38]. Till skillnad från utveckling av applikationer för
iOS, kostar det inget att testa applikationer på hårdvara för Android. Däremot för att publicera applikationer på Google Play krävs ett Google Play Publisher Account som har en engångsavgift på 25
dollar.
För att utveckla applikationer för Android används Android SDK och den vanligaste utvecklingsmiljön är Eclipse med insticksprogrammet Android Developer Tools installerat. Applikationer för
Android kan utvecklas på plattformarna Windows, Mac OS X och Linux [39].
Det finns många Androidtelefoner som har NFC-stöd, framförallt nya modeller [40]. Android Developers är en webbresurs för utvecklare som ständigt uppdateras och innehåller mängder av guider
för att programmera Androidapplikationer [41]. Men även för denna platform finns det en mängd
litteratur som stöd för utvecklare [42].
4.3 WINDOWS PHONE
Windows Phone är Microsofts motsvarande operativsystem för mobila plattformar. För att utveckla
applikationer används Windows Phone SDK 8.0 och utvecklingsmiljön Visual Studio 2012. Windows
Phone SDK 8.0 kräver som minst en PC med operativsystemet 64-bit Windows 8 Pro installerat.
[43]Plattformen kräver även ett medlemskap i Windows Phone Dev Center för att testa applikationer på hårdvara. Tre olika enheter kan registreras för att testa applikationer på och medlemskapet
kostar 99 dollar per år [44, 45].
Det finns ett tiotal mobiltefoner som använder Windows Phone med stöd för NFC [46]. Plattformen
är relativt ny jämfört med Android och iOS men det finns likväl en mängd litteratur och webresursen Windows Phone Dev Center som stöd för utveckling av Windows Phone Applikationer [47, 48].
21
4.4 VAL AV MOBILPLATTFORM
Valet av mobilplattform baseras på den positioneringsteknik som används i implementation. Detta
medför att endast plattformarna Android och Windows Phone som har stöd för NFC kan användas.
Eftersom plattformen Android har markant större marknadsandel än Windows Phone [49] och
applikationer kan testas kostnadsfritt på hårdvara används operativsystemet i implementationen.
22
5 SERVERLÖSNING
Två olika typer av serverlösningar är On-premise och molnbaserad. On-premise är en serverlösning
som finns i samma byggnad som den person eller det företag som använder lösningen. Installation
och drift sköts ofta av personen eller det företag som äger lösningen. Molnbaserade serverlösningar
drivs och underhålls istället av en extern part. Servrar är ofta belägna i stora avancerade datacenter
vilket gör att driftskostnader kan hållas nere. De molnbaserade lösningarna har också ofta en prismodell som baseras på hur många och mycket resurser som används, en så kallad pay-per-usemodell. I detta kapitel undersöks och jämförs de båda serverlösningarna.
5.1 ON-PREMISE
Den främsta fördelen med en On-premise-serverlösning är att ägaren av lösningen har full kontroll
över alla system och data. Detta kan medföra högre säkerhet än molnbaserade serverlösningar eftersom data inte behöver transporteras över Internet. Nackdelen är att det krävs underhåll och att
ny infrastruktur kan behövas för att komma åt interna eller externa nätverk.
5.2 MOLNBASERAD
En molnbaserad serverlösning kräver i motsatts till en On-premise-lösning inget underhåll då det
sköts av leverantören av lösningen. Det finns ofta färdiga paketlösningar vilket kan göra att det går
snabbare att utveckla en lösning eller applikation. Eftersom åtkomst till en molnbaserad serverlösning sker över Internet, krävs ingen ny infrastruktur. Den kontroll över system och data som finns i
en On-premise-serverlösning finns inte på samma sätt i molnbaserad lösning vilket kan påverka
säkerheten. [50]
5.3 VAL AV SERVERLÖSNING
Eftersom arbetet är tidsbegränsat så används en molnbaserade serverlösningen i implementationen. Fördelen är att en sådan serverlösning varken kräver installation eller konfiguration av servermjukvara vilket gör att mycket tid kan sparas in. Att åtkomst till en molnbaserad serverlösning sker
via Internet anses också som en fördel eftersom ingen ny nätverksinfrastruktur krävs i kontrast till
om en On-premise-lösning används. På företaget Connecta finns det erfarenhet av att använda den
molnbaserade lösningen Windows Azure [51] och kommer därför att användas i implementationen.
23
24
6 KARTOGRAFI
Kartografi är konsten och vetenskapen att grafiskt representera ett område omkring en, vanligtvis
på en plan yta såsom en karta. [52] I Connectas LBS-tjänst finns en existerande grafisk beskrivning
över kontoret där tjänsten ska implementeras. Beskrivningen är en planritning med arbetsplats och
mötesrum utmärkta (Figur 10). Det finns dock ingen skala angiven men planritningen anses tillgodose tillräckligt med information för att användare av tjänsten ska kunna identifiera den verkliga
positionen. Planritningens pixlar representerar koordinater som används för att bestämma positioner.
Figur 10 - Planritning över Connectas kontor
25
26
7 IMPLEMENTATION
I kapitlet behandlas hur viktiga delar av den positionsbaserade tjänsten implementeras och testas.
7.1 NFC-TAGGAR
Positionsinformation skrivs till NFC-taggarna med webbverktyget NDEF Editor [53] och androidapplikationen NFC Developer [54]. Med NDEF Editor är det möjligt att skapa NDEF-meddelanden enkelt genom ett webbgränssnitt. Till NFC-taggarna som används i implementationen skrivs ett
NDEF-meddelande med positionsinformation och information om Androidapplikationen. Positionsinformationen består av tre NDEF-records som kan lagra klartext. En sådan NDEF-record skapas i
webbgränssnittet genom att klicka på knappen + Text Record (A). Positionsinformationen som lagras är en x-koordinat (B), en y-koordinat (C) och ett booleskt värde om positionen är vid en arbetsplats eller inte (D). Information om androidapplikationen som lagras är paketnamnet (E) och används för att rätt applikations ska startas när en NFC-tagg läses av en mobiltelefon med Android.
Paketnamet lagras i en så kallad Android Application Record och skapas i webbgränssnittet genom
att klicka på knappen + Android Application Record (F). Efter att ett meddelande är skapat kan en
QR-kod skapas i webbgränssnittet genom att klicka på knappen Create QR Code (G). En genererad
QR-kod visas därefter till höger i webbgränssnittet (H) (Figur 11).
A
F
G
B
C
H
D
E
Figur 11 - NDEF Editor. Ett webbgränssnitt för att skapa NDEF-meddelanden. Skapade meddelanden kan överföras till androidapplikationen NFC Developer via en genererad QR-kod (H).
Med NFC Developer kan NDEF-meddelandet som skapats i NDEF Editor överföras till en androidtelefon. När androidapplikationen NFC Developer startas visas en kamarevy med ett rött streck i
mitten. Om mobiltelefonens kamera riktas mot QR-koden så överförs NDEF-meddelandet till androidtelefonen och meddelandets innehåll visas (A) (Figur 12). För att skriva NDEF-meddelandet till en
NFC-tagg förs taggen till androidtelefonens baksida.
27
A
Figur 12 - NFC Developer. En androidapplikation som kan skriva till NFC-taggar NDEFmeddelanden skapade av NDEF-editor.
7.2 ANDROIDAPPLIKATION
Androidapplikationen är en central del av den positionsbaserade tjänsten. Applikationen tillhandahåller ett grafiskt användargrännssnitt som en användare kan integrera med för att exempelvis
söka efter andra användare. I Android representeras det grafiska användargränssnitten av så kallade aktiviteter. De aktiviteter som används i implementationen beskrivs i kapitel 7.2.1. En annan
viktigt del med androidapplikationen är den bakomliggande programkoden som tillhandahåller
viktig funktionallitet. I kapitel 7.2.2 klassbeskrivningar beskrivs viktiga Java klasser som är del av
den bakomliggande programkoden.
7.2.1 AKTIVITETER
Applikationen består av tre aktiviteter:



MainActivity
SettingsActivity
DebugActivity
MainActivity (Figur 13) är huvudaktiviteten som sköter registrering och avregistrering av användare vid arbetsplatser och i mötesrum. För detta krävs det att aktiviteten kan hantera och läsa NFCtaggar och den programkod som hanterar detta återfinns i appendix 1.1. Aktiviteten hanterar också
sökfunktionen (A) som används för att hitta registrerade användare och deras position (B). Navigation till de andra aktiviteterna (C, E) sker via en meny i huvudaktiviteten. I samma meny är det
möjligt att manuellt hämta registrerade användare och deras position från databasen (D).
28
A
B
A
C
D
E
Figur 13 – MainActivity. Huvudaktiviteten som sköter registrering, avregistrering, sökning och navigering till andra aktiviter.
SettingsActivity är det gränssnitt som används för att ändra inställningar för applikationen. Inställningen Name är namnet på användaren som kan registrera sig vid arbetsplatser och i mötesrum.
Inställningen ändras genom att trycka på Name (A) och skriva in valfritt namn i rutan som dyker
upp (B) (Figur 14).
B
A
Figur 14 – SettingsActivity. Gränssnitt för att ändra inställningar för applikationen.
Aktiviteten DebugActivity är ett gränssnitt som endast är till för att underlätta utveckling och test
av applikationen. Aktiviteten gör det möjligt att simulera att användare registrerar och avregistre29
rar sig vid arbetsplatser eller i mötesrum. För att utföra en simulerad registrering anges ett användarnamn (A) och användarens position i form av en x-koordinat (B) och en y-koordinat (C) i formuläret. En tidsbegränsning för hur länge registreringen ska finnas tillgänglig innan den raderas
automatiskt från databasen anges i millisekunder (D). Slutligen anges också om den angivna positioen är vid en arbetsplats eller inte (E) (Figur 15).
A
B
C
D
E
Figur 15 – DebugActivity. Aktivitet som gör det möjligt att simulera att användare registrerar och
avregistrerar sig vid arbetsplatser eller i mötesrum
7.2.2 KLASSBESKRIVNINGAR I JAVA
Klassen CheckInRecord är en modell av en registrering vid en arbetsplats eller i ett mötesrum (Figur
16). Observera att klassens namn måste vara detsamma som den skapade databastabellen. Modellen kopplas samman med databastabellen genom att klassens datamedlemmar serialiseras till
JSON med följande kod:
@com.google.gson.annotations.SerializedName("name")
private String mName;
Där strängen name motsvarar en kolumn i databastabellen med samma namn och kopplas samman
med datamedlemen mName. Klassen CheckInRecord innehåller också getters och setters som kan
användas för att hämta samt modifiera respektive datamedlem i applikationen. Modellen har också
följande metoder för att jämföra modeller mot varandra:



equalPosition – Kontrollerar om två modeller har samma position.
equalName – Kontrollerar om två modeller har användare med samma namn
equals – Kontrollerar om två modeller är lika
Det finns även en toString metoden som returnerar en sträng med namnet på den användare som
är registrerad.
30
Figur 16 - Modell av en registrering vid en arbetsplats eller i ett mötesrum
Klassen CheckInService är en modell för alla kommunikation mellan applikationen och databasen
(Figur 17). När ett objekt av modellen skapas så skapas även kopplingen till databasen och en ArrayAdapter. Metoderna refresh, checkInCheckOut, checkIn och checkOut kan därefter användas för
att interagera med databasen. För att hämta registrerade användares och ta bort avregistrerade
användares positioner används metoden refresh.
Figur 17 - Modell för all kommunikation mellan applikationen och databasen
31
Metoderna checkIn och checkOut används för att registrera respektive avregistrera en användare
vid en arbetsplats eller i ett mötesrum. Vid registrering av användare kontrolleras först om användaren finns registrerad sedan tidigare (A). Om så är fallet raderas den befintliga registreringen innan en ny läggs till (B). Slutligen utförs en kontroll om användaren ska registrera sin position vid en
arbetsplats där en annan användare redan finns registrerad (C). Finns en användare redan registrerad vid arbetsplatsen skrivs registrering över (D). Detta för att uppfylla kravet om att endast en
användare får vara registrerad vid en arbetsplats åt gången. Om registreringen är i ett mötesrum
eller vid en ledig arbetsplats läggs en ny registrering till i databasen (E) (Figur 18).
Start
A
Finns användaren registrerad vid en
annan position?
B
Nej
Ja
C
Ta bort befintlig
registrering
Finns en annan användare registrerad och
är positionen vid en arbetsplats?
Nej
D
Ja
E
A
Skriv över befintlig
registrering
Lägg till en ny
registrering
Slut
Figur 18 - Flödesschema för metoden checkIn
checkInCheckOut är en kombination av de båda metoderna checkIn och checkOut. Om en användare
redan är registrerade vid exempelvis en arbetsplats och registrerar sig ytterligare en gång vid
samma arbetsplats, så avregistreras användaren.
För att göra möjligt att zooma och panorera planritningen i applikationen används biblioteket ImageViewTouch. [55]
32
7.3 WINDOWS AZURE
Windows Azures främsta uppgift är att hantera databasen som innehåller aktiva registreringar. I
detta kapitel beskrivs hur Windows Azure används i implementationen.
7.3.1 REGISTRERA UTVÄRDERINGSKONTO
För att skapa ett utvärderingskonto krävs ett befintligt Microsoft-konto (ex. hotmail-konto eller
outlook-konto). Det krävs även en mobiltelefon och kreditkort för att skapa ett utvärderingskonto.
En mobiltelefon krävs för att en verifieringskod ska kunna mottas med SMS. Kreditkortet används
för styrka ens identitet och det finns inga krav på att köpa någonting. Under utvärderingsperioden
finns en så kallad utgiftsgräns på noll kronor vilken måste konfigureras manuellt för att avgifter ska
dras från kreditkortet. Används mer resurser än de som ingår under utvärderingsperioden så dras
inga avgifter utan kontot inaktiveras.
7.3.2 SKAPA EN MOBILTJÄNST
En mobiltjänst skapas enklast enligt guiden Get started with data in Mobile Services [56]. Guiden
innehåller ett exempel på en Androidapplikation som är bra för referens och utgångspunkt för att
komma igång men behövs inte för implementationen. Det som krävs för implementationen är att de
steg som återfinns under rubrikerna Create a new Mobile service in the Management Portal och Add
a new table to the mobile service. I detta arbete skapades tjänsten Cinlo och databasen Cinlo_db med
tabellen CheckInRecord.
7.3.3 KONFIGURERA TIDSJOBB
Guiden Schedule recurring jobs in Mobile Services [57] används som stöd för att skapa det tidsjobb
som raderar användare som varit registrerade längre än den specificerade tidsbegränsningen. Koden i Figur 19 konfigureras att köras en gång i timmen. Tidsbegränsningen som lagras i databastabellen anges i millisekunder.
Figur 19 - Koden som utför tidsjobbet för att radera inaktiva registreringar
33
7.3.4 KONFIGURERA PUSH -NOTISER
Push-notiser kan meddela en användare av LBS-tjänsten en annan användare har registrerat sig
(Figur 20). Guiden Get with push notifications in Mobile Services [58] beskriver enkelt hur pushnotiser kan konfigureras för en Andoidapplikation.
Figur 20 - Push-notis som visar att användaren Kalle Anka har registrerat sig
Ett Google-konto krävs för att genomföra konfigurationen. För specifik kod som används i projekten se appendix 1.1 och 1.6: Kod Androidapplikation och Figur 21.
Figur 21 - Kod för push-notiser
34
7.4 TESTER
LBS-tjänsten testas utifrån den specificerade kravspecifikationen i kapitel 1.5. För att simulera att
andra användare registreras och avregistreras används DebugActivity. Mobiltelefonen Samsung
Galaxy S3 används för samtliga tester. Inför varje test rensas databasen så att testen inte påverkar
varandra. Följande positionsinformation skrivs till fyra NFC-taggar:




Tagg 1
o
o
o
o
Tagg 2
o
o
o
o
Tagg 3
o
o
o
o
Tagg 4
o
o
o
o
x-koordinat: 225
y-koordinat: 585
arbetsplats: true
Packetnamn: com.connect.cinlo
x-koordinat: 405
y-koordinat: 825
arbetsplats: true
Packetnamn: com.connect.cinlo
x-koordinat: 294
y-koordinat: 76
arbetsplats: false
Packetnamn: com.connect.cinlo
x-koordinat: 367
y-koordinat: 205
arbetsplats: false
Packetnamn: com.connect.cinlo
Tagg 1 och 2 lagrar positionsinformation för två arbetsplatser medan tagg 3 och 4 lagras positionsinformation för två mötesrum.
7.4.1 REGISTRERING VID LEDIG ARBETSPLATS
Scenario 1: Registrering vid en ledig arbetsplats, användaren finns inte registrerad sedan tidigare.
Detta scenario verifierar om en användare kan registrera vid en ledig arbetsplats.
För att läsa taggen måste mobiltelefonen vara upplåst. Om applikationen inte är öppen, ska registrering fungera ändå. För att testa registrering vid arbetsplats läses därför tagg 1. Registreringen
kontrolleras genom att verifiera att en ny rad har lagts till i databastabellen. Positionsinformationen på tagg 1 och användarens namn ska finnas med i den inlagda raden i databastabell.
Scenario 2: Registrering vid en ledig arbetsplats, användare finns registrerad sedan tidigare. Detta
scenario verifierar om en användare endast kan vara registrerad vid en arbetsplats.
Databastabellen rensas inte inför detta scenario. Tagg 2 läses av mobiltelefonen för att registrera
användaren vid en ledig arbetsplats. Registreringen kontrolleras genom att verifiera att den föregående registreringen har ersatts med positionsinformationen från tagg 2.
35
7.4.2 REGISTRERING VID UPPTAGEN ARBETSPLATS
Scenario 3: Registrering vid en upptagen arbetsplats, användaren finns inte registrerad sedan tidigare. Detta scenario verifierar om endast en användare kan vara registrerad vid en arbetsplats åt
gången.
För att simulera att en annan användare redan finns registrerad vid arbetsplatsen används DebugActivity. Positionsinformation anges enligt Figur 22. Tagg 1 läses därefter med mobiltelefonen.
Registreringen kontrolleras genom att verifiera att den simulerade användarnamnet har ersatts
med applikationens inställda användarnamn.
Figur 22 – DebugActivity används för simulering av registrering vid arbetsplats
Scenario 4: Registrering vid en upptagen arbetsplats, användaren finns registrerad sedan tidigare.
Detta scenario verifierar om en användare endast kan vara registrerad vid en arbetsplats och att
endast en användare kan vara registrerad vid en arbetsplats åt gången.
Databastabellen rensas inte inför detta scenario. En simulerad registrering läggs till genom DebugActivity med samma positionsinformation som Tagg 2. Tagg 2 läses därefter av med mobiltelefonen för att registrera användaren vid en upptagen arbetsplats. Registreringen kontrolleras genom
att verifiera att den föregående registreringen har raderats och att den simulerade användarnamnet har ersatts med applikationens inställda användarnamn.
7.4.3 AVREGISTRERING VID BEFINTLIG ARBETSPLATS
Scenario 5: Avregistrering vid arbetsplats. Detta scenario verifierar om en användare kan avregistrera från arbetsplatser.
Tagg 1 läses av med mobiltelefonen för att registrera användaren vid en ledig arbetsplats. Tagg 1
läses av ännu en gång för att avregistrea användaren. Avregistrering kontrolleras genom att verifiera att databastabellen är tom.
36
7.4.4 REGISTRERING I LEDIGT MÖTESRUM
Scenario 6: Registrering i ett ledigt mötesrum, användaren finns inte registrerad sedan tidigare.
Detta scenario verifierar om en användare kan registrera i ett ledigt mötesrum.
Tagg 3 läses av med mobiltelefonen för att registrera användaren i ett ledigt mötesrum. Registreringen kontrolleras genom att verifiera att användaren får en förfrågan hur länge mötet ska pågå
och att en ny rad har lagts till i databastabellen. Positionsinformationen på tagg 3 och användarens
namn ska finnas med i den inlagda raden i databastabell.
Scenario: Registrering i ett ledigt mötesrum, användare finns registrerad sedan tidigare. Detta scenario verifierar om en användares tidigare registrering skrivs över vid en ny registrering i ett mötesrum.
Databastabellen rensas inte inför detta scenario. Tagg 4 läses av mobiltelefonen för att registrera
användaren i ett ledigt mötesrum. Registreringen kontrolleras genom att verifiera att användaren
får en förfrågan hur länge mötet ska pågå och att den föregående registreringen har ersatts med
positionsinformationen från tagg 4.
7.4.5 REGISTRERING I UPPTAGET MÖTESRUM
Scenario 7: Registrering i ett befolkat mötesrum, användaren finns inte registrerad sedan tidigare.
Detta scenario verifierar om flera användare kan vara registrerad i ett mötesrum.
En simulerad registrering läggs till genom DebugActivity med samma positionsinformation som
Tagg 3. Tagg 3 läses därefter med mobiltelefonen. Registreringen kontrolleras genom att verifiera
att användaren får en förfrågan hur länge mötet ska pågå och att en ny rad har lagts till i databastabellen. Positionsinformationen på tagg 3 och användarens namn ska finnas med i den inlagda raden
i databastabell. Den simulerade registreringen också ska finnas kvar.
Scenario 8: Registrering i ett befolkat mötesrum, användaren finns registrerad sedan tidigare. Detta
scenario verifierar om en användare endast kan vara registrerade i ett mötesrum och att flera användare kan vara registrerad i ett mötesrum.
Databastabellen rensas inte inför detta scenario. En simulerad registrering läggs till genom DebugActivity med samma positionsinformation som Tagg 4. Tagg 4 läses därefter med mobiltelefonen. Registreringen kontrolleras genom att verifiera att användaren får en förfrågan hur länge mötet ska pågå och att användarens existerande registrering uppdateras med positionsinformationen
från tagg 4. Den simulerade registreringen ska också finnas kvar.
7.4.6 AVREGISTRERING I MÖTESRUM
Scenario 9: Avregistrering i mötesrum. Detta scenario verifierar om en användare kan avregistrera
från arbetsplatser.
Tagg 3 läses av med mobiltelefonen för att registrera användaren i ett ledigt mötesrum. Tagg 3 läses av ännu en gång för att avregistrera användaren. Avregistrering kontrolleras genom att verifiera att databastabellen är tom.
37
7.4.7 SÖKNING AV ANVÄNDARE
Scenario 10: Sökning efter John Doe, registrerad användare. Detta scenario verifierar om det möjligt
att söka efter registrerade användare.
En simulerad registrering läggs till genom DebugActivity med samma positionsinformation som
Tagg 1. Sökningen kontrolleras genom att verifiera att användare går att hitta med sökfunktionen.
Och att den registrerade positionen stämmer.
7.4.8 TIDSBASERAD AVREGISTRERING
Scenario 11: Användare registreras med en kort tidsbegränsning och tidsjobbet aktiveras manuellt.
Detta scenario verifierar om den tidsbaserade avregistreringen fungerar manuellt.
En simulerad registrering läggs till genom DebugActivity med samma positionsinformation som
Tagg 1 med tidsbegränsningen 12 millisekunder. Tidsjobbet aktiveras manuellt via Windows Azure
Management Portal [59]. Den tidsbaserade avregistreringen kontrolleras genom att verifiera att
databastabellen är tom.
Scenario 12: Användare har varit registrerad minst 12 timmar vid samma arbetsplats. Detta scenario verifierar om den tidsbaserade avregistreringen kan avregistrera en användare automatiskt
efter 12 timmar.
Tagg 1 läses av med mobiltelefonen för att registrera användaren vid en ledig arbetsplats. Den tidsbaserade avregistreringen kontrolleras genom att verifiera att databastabellen är tom efter 12
timmar.
Scenario 13: Användare har varit registrerad längre än den angivna mötestiden i ett mötesrum.
Detta scenario verifierar om den tidsbaserade avregistreringen kan avregistrera en användare
automatisk efter angiven mötestid.
Tagg 3 läses av med mobiltelefonen för att registrera användaren i ett ledigt mötesrum. Mötestiden
anges till en timme. Den tidsbaserade avregistreringen kontrolleras genom att verifiera att databastabellen är tom efter en timma.
38
8 RESULTAT OCH DISKUSSION
I detta kapitel beskrivs och diskuteras resultatet av implementationen av den positionsbaserade
tjänsten.
8.1 ARKITEKTUR
Den implementerade LBS-tjänsten baseras på NFC-positionering där mobiltelefoner med NFC-stöd
används för att läsa positionsinformationen från NFC-taggarna (A). Taggar placeras ut vid varje
arbetsplats och i varje mötesrum. En tagg innehåller informationen om taggens position i form av xoch y-koordinater samt om taggen är placerad vid en arbetsplats eller i ett mötesrum. En tagg innehåller även information om vilken androidapplikation som ska startas när en mobiltelefon läser
taggen. Den implementerade androidapplikationen kombinerar positionsinformationen läst från
en NFC-tagg med användarnamnet som har specificerats av användaren. Informationen serialiseras till JSON och skickas över Internet till den molnbaserade serverlösningen Windows Azure
där informationen lagras i en databastabell (B). Androidapplikationen kan lägga till, ta bort eller
uppdatera registreringar i databastabellen och kan på så sätt utföra registrering och avregistrering
av en användare. Från Windows Azure kan också alla lagrade registreringar hämtas och användas i
applikationen för att söka efter registrerade användare och rita ut deras position (C). I Windows
Azure har även funktionen push-notiser konfigureras så att en användare kan meddalas om andra
användare har registrerat sin arbetsplats. Slutligen har även ett tidsjobb konfigureras i Windows
Azure som raderar inaktiva registreringar i databastabellen automatiskt (Figur 23). Fördelenen
med arkitekturen är dess enkelthet eftersom att inga algoritmer krävs för att bestämma en position
och att mycket information och guider finns tillgängligt för en implementation av arkitekturen.
Datacenter
Mobiltjänst
B
C
Databas
A
A
NFC-tagg med
positionsinformation
Smartphone med NFC-läsare
Figur 23 – Arkitektur för den implementerade LBS-tjänsten
39
Utöver de krav som ställs i kravspecifikationen i kapitel 1.5 infördes möjligheten för en användare
att avregistrera manuellt. Utan den möjligheten så sker endast avregistrering i följande fall:



Den registrerade användaren registrerar sig vid en annan arbetsplats eller i ett annat mötesrum
Den registrerade användaren skrivs över av en annan användare som registrerar sig vid arbetsplatsen. I mötesrum sker inte detta eftersom flera kan vara registrerade samtidigt i ett
mötesrum.
Den registreda användaren avregistreras av tidsjobbet efter 12 timmar eller efter specificerad mötestid
Sker inte någon av dessa fall, kan databastabellen innehålla felaktig information och därför infördes
manuell avregistrering.
En insikt under implantationen har varit att lagra positionsinformation på NFC-taggarna gör lösningen mindre flexibel ifall en arbetsplats flyttas. Skulle detta ske måste ny positionsinformation
skrivas till NFC-taggen associerad till arbetsplatsen. En flexiblare lösning hade varit att använda
NFC-taggarna unika identifierare eller skapa en egen som lagras på varje NFC-tagg. En arbetsplats
position lagras tillsammans med identifieraren för arbetsplatsen associerade NFC-tag. På så sätt om
en arbetsplats flyttas behöver bara positionsinformationen uppdateras i databasen. Nackdelen är
dock att vid registrering vid en arbetsplats krävs fler förfrågningar till databasen eftersom den associerade positionsinformationen måste hämtas.
8.2 TESTER
Resultaten av testerna som beskrivs i kapitel 7.4 visar att de funktionella kraven som beskrivs i
kapitel 1.5.1 uppfylls. Testerna har endast utförts på mobiltelefonen Samsung Galaxy S3 och därför
kan fler tester på andra Androidtelefoner säkerställa LBS-tjänstens funktionalitet ytterligare.
Inga tester för att testa de icke-funktionella kraven som beskrivs i kapitel 1.5.2 har utförts.
8.3 PROBLEM
Ett problem som har upptäckts under implementationen är att registrering och avregistrering kan
ske även fast ingen tagg har lästs av mobiltelefonen. Problemet uppstår då telefonen efter en registrering eller avregistrering låser skärmen. När skärmen öppnas så utförs registrering om avregistrering utfördes innan. Om det istället var registrering som utfördes så utförs avregistrering.
40
9 SLUTSATS
Den övergripande målsättningen med arbetet att ta fram och implementera en LBS som gör det
möjligt för en användare att med hjälp av sin mobiltelefon dela med sig av sin nuvarande arbetsplats har uppnåtts. För att uppnå målsättningen har en litteraturstudie av de tekniker som krävs för
att implementera en LBS utförts.
Två positioneringstekniker baserat på WLAN respektive NFC har undersöks. NFC-positionering
används i implementationen eftersom tekniken är enkel att implementera och har bäst noggrannhet av de undersökta teknikerna.
De mobila plattformarna iOS, Android och Windows Phone har utvärderats utifrån ett utvecklarperspektiv. Företaget Googles mobila plattform Android som har störst marknadsandel, stöd för
NFC och där applikationer kan utvecklas och testas på hårdvara kostnadsfritt används i implementationen.
För och nackdelar mellan en molnbaserad och en On-premise-baserad serverlösning har också jämförts. En molnbaserad serverlösning kräver varken hårdvara eller installation och konfiguration av
servermjukvara och är tillgänglig direkt via Internet och används därför i implementationen. Den
molnbaserade serverlösningen som används i implementation är Windows Azure eftersom Connecta har erfarenhet av serverlösningen.
Resultatet är en implementation som baseras på en enkel arkitektur där NFC-positionering, den
mobila plattformen Android och den molnbaserade serverlösningen Windows Azure används. De
funktionella kraven som ställs i kravspecifikationen i kapitel 1.5 uppfylls alla men de ickefunktionalla kraven har inte verifieras.
Ett identifierat problem under implementationen är att registrering och avregistrering kan ske
även fast ingen NFC-tagg har lästs av mobiltelefonen. Då telefonen efter en registrering eller avregistrering går till låst läge så uppstår problemet när det låsta läget inaktiveras. Ingen lösning för problemet är funnen eller implementerad.
41
42
10 REKOMMENDATIONER
Det är rekommenderat att tester av LBS-tjänsten på fler Androidtelefoner utförs för att verifiera
funktionaliteten ytterligare. Användartest bör också utföras för att säkerställa tjänstens användarvänlighet. Problemet att registrering och avregistrering kan ske även fast ingen tagg har lästs av
mobiltelefonen bör ses över.
När den befintliga LBS-tjänstens funktionalitet och användarvänlighet har säkerhetställs rekommenderas att följande funktionalitet utvärderas och möjligtvis implementeras:





Att tjänsten kopplas samman med befintlig användardatabas. Användaren måste i den befintliga applikationen specificera sitt namn manuellt. Med en sammankoppling med befintlig användardatabas kan bättre autentisering utföras och mer information erhållas. Exempelvis kontaktuppgifter såsom telefonnummer.
Att tjänsten kopplas samman med Microsoft Lync [60]. Lync är ett kommunikationsverktyg
som används av Connecta.
Att lagra positionsinformation i en databas med associerad taggidentifierare för att göra system flexiblare
Implementera tjänsten på Windows Phone
Lägg till stöd för QR-koder. Positionsinformation eller unika identifierare kan lagras på QRkoder utöver NFC-taggar. Detta för att göra det möjligt att implementera tjänsten på iOS.
43
44
REFERENSER
[1]
A. Kushki, K. N. Plataniotis och A. N. Venetsanopoulos, WLAN Positioning Systems - Principles
and Applications in Location-Based Services, Cambridge: Cambridge University Press, 2012
[2]
Foursquare, ”About Foursquare”, Januari 2013, https://foursquare.com/about/, 18 Maj
2013
[3]
A. Langseth, ”Planer på flexkontor oroar”, 28 November 2012,
http://www.publikt.se/artikel/planer-pa-flexkontor-oroar-45002, 18 Maj 2013
[4]
Microsoft, ”Det nya arbetslivet”, http://www.microsoft.com/sverige/dna/, 22 Maj 2013
[5]
A. Lou och L. Ge, ”Indoor Location Detection using WLAN”,
http://web.it.kth.se/~maguire/DEGREE-PROJECT-REPORTS/100111-Anqi_Luo_and_Lei_Gewith-cover.pdf, 21 Maj 2013
[6]
A. . W. Reza och T. K. Geok, ”Investigation of Indoor Location Sensing via RFID”, 28 Juni 2008,
http://link.springer.com/content/pdf/10.1007%2Fs11277-008-9556-4.pdf, 21 Maj 2013
[7]
A. Lim och K. Zhang, ”A Robust RFID-Based Method for Precise Indoor Positioning”,
http://link.springer.com/content/pdf/10.1007%2F11779568_126.pdf, 21 Maj 2013
[8]
B. S. Heyi, ”Implementation of Indoor Positioning using IEEE802.15.4a (UWB)”, 2013,
http://kth.diva-portal.org/smash/get/diva2:603894/FULLTEXT01, 21 Maj 2013
[9]
D. R. Mautz, ”Indoor Positioning Technologies”, http://ecollection.library.ethz.ch/eserv/eth:5659/eth-5659-01.pdf?pid=eth:5659&dsID=eth-565901.pdf, 21 Maj 2013
[10] L. Xiaohan och M. Hideo, ”Improved indoor location estimation using fluorescent light
communication system with a nine-channel receiver”,
https://www.jstage.jst.go.jp/article/transcom/E93.B/11/E93.B_11_2936/_pdf, 21 Maj 2013
[11] Y. U. Lee och M. Kavehrad, ”Long-range Indoor Hybrid Localization System Design with
Visible Light Communications and Wireless Network”,
http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=6280712&tag=1, 21 Maj 2013
[12] H. Schweinzer och G. Kaniak, ”Ultrasonic device localization and its potential for wireless
sensor network security”, http://ac.els-cdn.com/S0967066109000021/1-s2.0S0967066109000021-main.pdf?_tid=58365fae-c212-11e2-bdf500000aab0f6b&acdnat=1369139662_4a57523cc68020b1d747351ae5c632fc, 21 Maj 2013
45
[13] R. Minihold, ”Near Field Communication (NFC) Technology and Measurements”,
http://cdn.rohdeschwarz.com/dl_downloads/dl_application/application_notes/1ma182/1MA182_4e.pdf, 21
Maj 2013
[14] Robin Henniges, ”Current approches of Wifi Positioning”, 2012, http://www.snet.tuberlin.de/fileadmin/fg220/courses/WS1112/snet-project/wifi-positioning_henniges.pdf, 18
Maj 2013
[15] A. Küpper, Location-Based Services - Fundamentals and Operation, Chichester: John Wiley &
Sons Ltd, 2005
[16] Cisco, ”Location Tracking Approaches”,
http://www.cisco.com/en/US/docs/solutions/Enterprise/Mobility/wifich2.html#wp10455
38, 18 Maj 2013
[17] A. Teuber och B. Eissfeller, ”WLAN Indoor Positioning Based on Euclidean Distances and
Fuzzy Logic”,
http://www.wpnc.net/fileadmin/WPNC06/Proceedings/31_WLAN_Indoor_Positioning_Base
d_on_Euclidean_Distances_and_Fuzzy_Logic.pdf, 27 Maj 2013
[18] I. Nikolaou och S. Denazis, ”POSITIONING IN Wi-Fi NETWORKS”,
http://sfhmmy3.sfhmmy.gr/cd/data/17.pdf, 27 Maj 2013
[19] R. Gutierrez-Osuna, ”Pattern recognition principles”,
http://research.cs.tamu.edu/prism/lectures/sp/l11.pdf, 27 Maj 2013
[20] P. Castro, P. Chiu, T. Kremenek och R. Muntz, ”A Probabilistic Room Location Service for
Wireless Networked Environments”,
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.1.7748, 27 Maj 2013
[21] P. Preuss, ”NFC Forum”, September 2009, http://www.nfcforum.org/events/oulu_spotlight/Forum_and_Use_Cases.pdf, 18 Maj 2013
[22] NXP Semiconductors, ”NTAG203”, 12 December 2011,
http://www.nxp.com/documents/short_data_sheet/NTAG203_SDS.pdf, 18 Maj 2013
[23] Samsung Geeks, ”NFC for Smartphones - What is NFC”,
http://samsunggeeks.com/2012/07/03/nfc-explained-nfc-forsmartphones/#.UZdfq6NvmM8, 18 Maj 2013
[24] D. V. Hunt, A. Puglia och M. Puglia, RFID - A Guide to Radio Frequency Identification, New
Jersey: John Wiley & Sons, 2007
[25] Google, ”Near Field Communication”,
http://developer.android.com/guide/topics/connectivity/nfc/index.html, 27 Maj 2013
46
[26] NFC World, ”NFC phones: The definitive list”, 18 Maj 2013, http://www.nfcworld.com/nfcphones-list/, 18 Maj 2013
[27] T. Lee, ”How Much Data Can A QR Code Store?”,
http://qrcode.meetheed.com/question7.php, 22 Maj 2013
[28] Kaywa.com, ”Kaywa QR Code”, http://qrcode.kaywa.com/, 22 Maj 2013
[29] J. Yang, Y. Chen, R. P. Martin, W. Trappe och M. Gruteser, ”On the Performance of Wireless
Indoor Localization Using Received Signal Strength”,
http://www.winlab.rutgers.edu/~gruteser/papers/chap12.pdf, 22 Maj 2013
[30] C. M. Wong, ”Investigation of Wireless Local Area Network Facilitated Angle of Arrival Indoor
Location”,
https://circle.ubc.ca/bitstream/handle/2429/2792/ubc_2008_fall_wong_carl.pdf?sequence=
1, 22 Maj 2013
[31] C. Wong, R. Klukas och G. Messier, ”Using WLAN Infrastructure for Angle-of-Arrival”,
http://www.ucalgary.ca/~gmessier/pdfs/vtc08_AoA.pdf, 22 Maj 2013
[32] Apple, ”iOS”, http://www.apple.com/ios/, 19 Maj 2013
[33] Apple, ”Support Center”, https://developer.apple.com/support/ios/ios-dev-center.html, 19
Maj 2013
[34] bokus.com, ”Mac-programmering", http://www.bokus.com/cgibin/product_search.cgi?search_word=ios&subject=4.8.9&rank_order=ranking_desc&ac_used
=no, 19 Maj 2013
[35] Apple, ”iOS Dev Center”, https://developer.apple.com/devcenter/ios/index.action, 19 Maj
2013
[36] Bloomberg Businessweek, ”Google Buys Android for Its Mobile Arsenal”,
http://www.businessweek.com/stories/2005-08-16/google-buys-android-for-its-mobilearsenal, 19 Maj 2013
[37] Google, ”Android Source Licenses”, http://source.android.com/source/licenses.html, Använd
19 Maj 2013
[38] Google, ”Android Devices”, http://www.android.com/devices/?country=all, 19 Maj 2013
[39] Google, ”Get the Android SDK”, http://developer.android.com/sdk/index.html, 19 Maj 2013
[40] NFC World, ”NFC devices tagged with 'Android'”, http://www.nfcworld.com/nfcdata/android/, 19 Maj 2013
[41] Google, ”Android Developers”, http://developer.android.com/index.html, 19 Maj 2013
47
[42] Bokus.com, ”Sökresultat Android”, http://www.bokus.com/cgibin/product_search.cgi?ac_used=no&search_word=Android, 19 Maj 2013
[43] Microsoft, ”Getting started with developing for Windows Phone”,
http://msdn.microsoft.com/library/windowsphone/develop/ff402529(v=vs.105).aspx,
Använd 19 Maj 2013
[44] Microsoft, ”How to register your phone for development”, http://msdn.microsoft.com/enUS/library/windowsphone/develop/ff769508(v=vs.105).aspx, 19 Maj 2013
[45] Microsoft, ”Join Windows Phone Dev Center”, http://dev.windowsphone.com/en-us/join, 19
Maj 2013
[46] NFC World, ”NFC devices tagged with 'Windows'”, http://www.nfcworld.com/nfcdata/windows/page/2/, 19 Maj 2013
[47] Bokus.com, ”Sökresultat: 'Windows Phone'”, http://www.bokus.com/cgibin/product_search.cgi?ac_used=no&search_word=Windows+Phone, 19 Maj 2013
[48] Microsoft, ”Windows Phone | Dev Center”, http://developer.windowsphone.com/en-us, 19
Maj 2013
[49] IDC, ”IDC - Press Release”, http://www.idc.com/getdoc.jsp?containerId=prUS23946013, 22
Maj 2013
[50] GFI Software, ”ON-PREMISE VS. CLOUD-BASED SOLUTIONS”,
http://www.gfi.com/whitepapers/Hybrid_Technology.pdf, 27 Maj 2013
[51] Microsoft, ”Windows Azure”, http://www.windowsazure.com/sv-se/, 17 Maj 2013
[52] Britannica Academic Edition, ”Cartography”,
http://www.britannica.com/EBchecked/topic/97492/cartography, 20 Maj 2013
[53] T. R. Skjolberg, ”NDEF Editor”, http://ndefeditor.com/, 18 Maj 2013
[54] T. R. Skjolberg, ”NFC Developer”,
https://play.google.com/store/apps/details?id=com.antares.nfc, 18 Maj 2013
[55] A. Crugnola, ”ImageViewTouch”, https://github.com/sephiroth74/ImageViewZoom, 19 Maj
2013
[56] ”Get started with data in Mobile Services”, http://www.windowsazure.com/enus/develop/mobile/tutorials/get-started-with-data-android/?fb=sv-se, 17 Maj 2013
[57] Microsoft, ”Schedule recurring jobs in Mobile Services”, http://www.windowsazure.com/enus/develop/mobile/tutorials/schedule-backend-tasks/?fb=sv-se, 20 Maj 2013
48
[58] Microsoft, ”Get started with push notifications in Mobile Services”,
http://www.windowsazure.com/en-us/develop/mobile/tutorials/get-started-with-pushandroid/?fb=sv-se, 19 Maj 2013
[59] Microsoft, ”Windows Azure Management Portal”, https://manage.windowsazure.com/, 17
Maj 2013
[60] Microsoft, ”Lync”, http://www.microsoft.com/sverige/lync/default.html, 20 Maj 2013
49
50
APPENDIX
1 Kod Androidapplikation ................................................................................................................................................... 1
1.1 src\MainActivity.java ................................................................................................................................................ 1
1.2 src\SettingsActivity.java .......................................................................................................................................... 8
1.3 src\DebugActivity.java............................................................................................................................................ 10
1.4 src\CheckInRecord.java ......................................................................................................................................... 13
1.5 src\CheckInService.java ......................................................................................................................................... 17
1.6 src\DebugCheckInService.java ............................................................................................................................ 22
1.7 src\GCMIntentService.java.................................................................................................................................... 26
1.8 src\NFCUtils.java ....................................................................................................................................................... 28
1.9 src\Util.java ................................................................................................................................................................. 29
1.10 AndroidManifest.xml ............................................................................................................................................. 30
1.11 res\layout\activity_main.xml ............................................................................................................................ 32
1.12 res\layout\activity_debug.xml.......................................................................................................................... 33
1.13 res\layout\action_search.xml ........................................................................................................................... 35
1.14 res\menu\main.xml .............................................................................................................................................. 36
1.15 res\values\strings.xml ......................................................................................................................................... 37
1.16 res\values\dimens.xml ........................................................................................................................................ 38
1.17 res\values\styles.xml ........................................................................................................................................... 39
1.18 res\xml\userpreferences.xml ........................................................................................................................... 40
51
52
1 KOD ANDROIDAPPLIKATION
1.1 SRC\MAINACTIVITY.JAVA
package com.connect.cinlo;
import java.net.MalformedURLException;
import java.util.ArrayList;
import
import
import
import
import
import
import
com.connect.cinlo.R;
com.google.android.gcm.GCMRegistrar;
com.microsoft.windowsazure.mobileservices.NextServiceFilterCallback;
com.microsoft.windowsazure.mobileservices.ServiceFilter;
com.microsoft.windowsazure.mobileservices.ServiceFilterRequest;
com.microsoft.windowsazure.mobileservices.ServiceFilterResponse;
com.microsoft.windowsazure.mobileservices.ServiceFilterResponseCallback;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
it.sephiroth.android.library.imagezoom.ImageViewTouch;
it.sephiroth.android.library.imagezoom.ImageViewTouchBase.DisplayType;
android.net.ConnectivityManager;
android.net.NetworkInfo;
android.nfc.NdefMessage;
android.nfc.NfcAdapter;
android.os.Bundle;
android.os.Parcelable;
android.preference.PreferenceManager;
android.app.Activity;
android.content.Context;
android.content.Intent;
android.content.SharedPreferences;
android.graphics.Bitmap;
android.graphics.BitmapFactory;
android.graphics.Canvas;
android.graphics.Color;
android.graphics.Paint;
android.util.DisplayMetrics;
android.util.Log;
android.view.Menu;
android.view.MenuItem;
android.view.MenuItem.OnActionExpandListener;
android.view.View;
android.widget.AdapterView;
android.widget.AdapterView.OnItemClickListener;
android.widget.ArrayAdapter;
android.widget.AutoCompleteTextView;
android.widget.ProgressBar;
android.widget.TextView;
android.widget.Toast;
public class MainActivity extends Activity {
/* Debugging*/
private static final boolean D = true;
1
private static final String TAG = "MainActivity";
/* Shared preferences */
public static final String PREF_NAME = "PREF_NAME";
/* Push notifications id */
public static final String SENDER_ID = "YOU PUSH NOTIFICATION ID";
/* Paint constants */
private static final int POS_CIRCLE_RADIUS = 6;
private static final int POS_STROKE_WIDTH = 3;
/* Objects */
private CheckInService mCheckInService;
private CheckInRecord mCheckInRecord;
private String mRegstrationId;
private ConnectivityManager mConnManager;
private Bitmap mFloorplan;
private ArrayList<CheckInRecord> mPositions;
private ArrayAdapter<CheckInRecord> mAdapter;
private ImageViewTouch mFloorplanView;
private ProgressBar mProgressView;
private AutoCompleteTextView mSearchView;
private TextView mInfoView;
private Paint mPaint;
private SharedPreferences prefs;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/* Init shared prefs */
Context context = getApplicationContext();
prefs = PreferenceManager.getDefaultSharedPreferences(context);
/* Init the progress bar view */
mProgressView = (ProgressBar) findViewById(R.id.progress);
mProgressView.setVisibility(ProgressBar.GONE);
/* Init Connectivity Manager */
mConnManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
/* Init floorplan view */
mFloorplan = BitmapFactory.decodeResource(getResources(), R.raw.floorplan);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setColor(Color.RED);
/* Init position cache */
mPositions = new ArrayList<CheckInRecord>();
mAdapter = new ArrayAdapter<CheckInRecord>(this, android.R.layout.select_dialog_item, mPositions);
2
/* Init push notifications */
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
mRegstrationId = GCMRegistrar.getRegistrationId(this);
if (mRegstrationId.equals("")) {
GCMRegistrar.register(this, SENDER_ID);
}
/* Init infor view */
mInfoView = (TextView) findViewById(R.id.textViewNoConnection);
}
@Override
protected void onResume() {
super.onResume();
/* Gets the name of the user specified in settings */
String name = prefs.getString(PREF_NAME, "");
/* A name must be specified, if not SettingsActivity is shown */
if (name == null || name == "") {
Intent iSettings = new Intent(this, SettingsActivity.class);
startActivity(iSettings);
} else {
/* Check if the check-in service is available and a Internet connection exists */
if (isServiceAccessable(mConnManager.getActiveNetworkInfo())) {
/* If the activity was started by a NFC tag, read the nfcmessage */
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
Intent nfcIntent = getIntent();
Parcelable[] rawMsgs =
nfcIntent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
NdefMessage msg = (NdefMessage) rawMsgs[0];
try {
/* Tries to parse the positioninfo stored on
the tag */
int x = Integer.parseInt(NFCUtils.parseTextRecord(msg.getRecords()[0]));
int y = Integer.parseInt(NFCUtils.parseTextRecord(msg.getRecords()[1]));
boolean atWorkplace = Boolean.parseBoolean(NFCUtils.parseTextRecord(msg.getRecords()[2]));
/* Createas a new Check-in record and performs a check-in or a checkout */
mCheckInRecord = new CheckInRecord();
mCheckInRecord.setRegistrationId(mRegstrationId.equals("") ?
GCMIntentService.getRegistrationId() :
mRegstrationId);
3
mCheckInRecord.setName(prefs.getString(PREF_NAME, "John Doe"));
mCheckInRecord.setX(x);
mCheckInRecord.setY(y);
mCheckInRecord.setAtWorkplace(atWorkplace);
mCheckInRecord.setLimit(Util.hoursToMilliseconds(12));
mCheckInService.checkInCheckOut(mCheckInRecord);
mCheckInRecord = null;
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
}
} else {
/* If no nfc-tag was read the position cache is updated */
mCheckInService.refresh();
}
}
}
}
/* Used for zooming */
@Override
public void onContentChanged() {
super.onContentChanged();
mFloorplanView = (ImageViewTouch) findViewById(R.id.imageViewTouch);
mFloorplanView.setDisplayType(DisplayType.FIT_IF_BIGGER);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
MenuItem menuItem = menu.findItem(R.id.action_search);
menuItem.setOnActionExpandListener(new OnActionExpandListener() {
@Override
public boolean onMenuItemActionExpand(MenuItem item) {
mSearchView = (AutoCompleteTextView)
item.getActionView().findViewById(R.id.searchView);
mSearchView.setAdapter(mAdapter);
mSearchView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View
arg1, int pos,
long id) {
CheckInRecord record = (CheckInRecord)parent.getAdapter().getItem(pos);
if (record != null) {
drawUserPosition(mFloorplan, record.getX(), record.getY());
4
}
}
});
return true;
}
@Override
public boolean onMenuItemActionCollapse(MenuItem item) {
// TODO Auto-generated method stub
return true;
}
});
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch(item.getItemId()) {
case R.id.action_settings :
if (D) Log.i(TAG, "Clicked on settings");
Intent iSettings = new Intent(this, SettingsActivity.class);
startActivity(iSettings);
return true;
case R.id.action_debug :
if (D) Log.i(TAG, "Clicked on debug");
Intent iDebug = new Intent(this, DebugActivity.class);
startActivity(iDebug);
return true;
case R.id.action_refresh :
if (D) Log.i(TAG, "Clicked on refresh");
if (isServiceAccessable(mConnManager.getActiveNetworkInfo())) {
mCheckInService.refresh();
}
return true;
default :
return super.onOptionsItemSelected(item);
}
}
private void showInfoText() {
mFloorplanView.setVisibility(View.GONE);
mInfoView.setVisibility(View.VISIBLE);
}
private void hideInfoText() {
//mSearchView.setVisibility(View.VISIBLE);
mFloorplanView.setVisibility(View.VISIBLE);
mInfoView.setVisibility(View.GONE);
}
/*
5
* From a search the selected users position is draw on the floorplan
*/
private void drawUserPosition(Bitmap floorplan, int x, int y) {
if (D) Log.i(TAG, "Drawing user position at: (" + x + ", " + y + ")");
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
float logicalDensity = metrics.density;
mPaint.setStrokeWidth(POS_STROKE_WIDTH*logicalDensity);
Bitmap tempFloorplan = Bitmap.createBitmap(floorplan.getWidth(), floorplan.getHeight(), Bitmap.Config.RGB_565);
Canvas tempCanvas = new Canvas(tempFloorplan);
tempCanvas.drawBitmap(floorplan, 0, 0, null);
tempCanvas.drawCircle(x*logicalDensity, y*logicalDensity,
POS_CIRCLE_RADIUS*logicalDensity, mPaint);
tempCanvas.drawLine(0, y*logicalDensity, floorplan.getWidth(),
y*logicalDensity, mPaint);
tempCanvas.drawLine(x*logicalDensity, 0, x*logicalDensity, floorplan.getHeight(), mPaint);
mFloorplanView.setImageBitmap(tempFloorplan);
}
/*
* Check if the checkin service is available
*/
private boolean isServiceAccessable(NetworkInfo networkInfo) {
if (networkInfo != null && networkInfo.isConnected()) {
hideInfoText();
if (mCheckInService == null) {
try {
mCheckInService = new CheckInService(this, new ProgressFilter(), mAdapter);
return true;
} catch (MalformedURLException e) {
mCheckInService = null;
showMessage("Failed to connect to mobile service,
please try again.");
}
} else {
return true;
}
} else {
showInfoText();
}
return false;
}
/*
* Shows a toast message
*/
6
private void showMessage(String msg) {
Toast.makeText(
this,
msg,
Toast.LENGTH_SHORT
).show();
}
/*
* Shows the progress circle
*/
private class ProgressFilter implements ServiceFilter {
@Override
public void handleRequest(ServiceFilterRequest request, NextServiceFilterCallback nextServiceFilterCallback,
final ServiceFilterResponseCallback responseCallback) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mProgressView.setVisibility(ProgressBar.VISIBLE);
}
});
nextServiceFilterCallback.onNext(request, new ServiceFilterResponseCallback() {
@Override
public void onResponse(ServiceFilterResponse response, Exception exception) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mProgressView.setVisibility(ProgressBar.GONE);
}
});
responseCallback.onResponse(response, exception);
}
});
}
}
}
7
1.2 SRC\SETTINGSACTIVITY.JAVA
package com.connect.cinlo;
import com.connect.cinlo.R;
import
import
import
import
import
import
import
android.content.SharedPreferences;
android.content.SharedPreferences.OnSharedPreferenceChangeListener;
android.os.Bundle;
android.preference.EditTextPreference;
android.preference.Preference;
android.preference.PreferenceActivity;
android.util.Log;
public class SettingsActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener {
private static final boolean D = true;
private static final String TAG = "SettingsActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
if (D) Log.i(TAG, "onCreate");
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.userpreferences);
}
@Override
protected void onResume() {
if (D) Log.i(TAG, "onResume");
super.onResume();
getPreferenceScreen().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
updatePreferences(MainActivity.PREF_NAME);
}
@SuppressWarnings("deprecation")
@Override
protected void onPause() {
super.onPause();
getPreferenceScreen().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
String key) {
updatePreferences(key);
}
/*
* Sets the summary in the SettingsActivity to the entered username
*/
8
private void updatePreferences(String key) {
@SuppressWarnings("deprecation")
Preference preference = findPreference(key);
if (preference instanceof EditTextPreference) {
EditTextPreference editTextPreference = (EditTextPreference)preference;
String text = editTextPreference.getText();
if (text != null && text.trim().length() > 0) {
editTextPreference.setSummary(text);
} else {
if (key.equals(MainActivity.PREF_NAME)) {
editTextPreference.setSummary(R.string.pref_firstname_summary);
}
}
}
}
}
9
1.3 SRC\DEBUGACTIVITY.JAVA
package com.connect.cinlo;
import java.net.MalformedURLException;
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
com.connect.cinlo.R;
com.google.android.gcm.GCMRegistrar;
com.microsoft.windowsazure.mobileservices.NextServiceFilterCallback;
com.microsoft.windowsazure.mobileservices.ServiceFilter;
com.microsoft.windowsazure.mobileservices.ServiceFilterRequest;
com.microsoft.windowsazure.mobileservices.ServiceFilterResponse;
com.microsoft.windowsazure.mobileservices.ServiceFilterResponseCallback;
android.app.Activity;
android.os.Bundle;
android.util.Log;
android.view.View;
android.widget.Button;
android.widget.CheckBox;
android.widget.EditText;
android.widget.ProgressBar;
public class DebugActivity extends Activity {
// Debug constants
private static final boolean D = true;
private static final String TAG = "DebugActivity";
// Push notifications id
public static final String SENDER_ID = " YOU PUSH NOTIFICATION ID";
private DebugCheckInService mCheckInService;
private String mRegstrationId;
private
private
private
private
private
private
private
ProgressBar mProgressBar;
EditText mEditTextName;
EditText mEditTextX;
EditText mEditTextY;
EditText mEditTextLimit;
CheckBox mCheckBoxAtWorkplace;
Button mSubmitButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_debug);
// Initialize views
mProgressBar = (ProgressBar) findViewById(R.id.progress);
mProgressBar.setVisibility(ProgressBar.GONE);
mEditTextName = (EditText) findViewById(R.id.editTextName);
mEditTextX = (EditText) findViewById(R.id.editTextX);
mEditTextY = (EditText) findViewById(R.id.editTextY);
mEditTextLimit = (EditText) findViewById(R.id.editTextLimit);
10
mCheckBoxAtWorkplace = (CheckBox) findViewById(R.id.checkBoxAtWorkplace);
mSubmitButton = (Button) findViewById(R.id.buttonSubmit);
mSubmitButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
if (mCheckInService != null) {
CheckInRecord record = new CheckInRecord();
record.setRegistrationId(mRegstrationId.equals("") ?
GCMIntentService.getRegistrationId() :
mRegstrationId);
record.setName(mEditTextName.getText().toString());
record.setX(Integer.parseInt(mEditTextX.getText().toString()));
record.setY(Integer.parseInt(mEditTextY.getText().toString()));
record.setLimit(Integer.parseInt(mEditTextLimit.getText().toString()));
record.setAtWorkplace(mCheckBoxAtWorkplace.isChecked());
mCheckInService.checkInCheckOut(record);
}
}
});
// Initialize push notifications
GCMRegistrar.checkDevice(this);
GCMRegistrar.checkManifest(this);
mRegstrationId = GCMRegistrar.getRegistrationId(this);
if (mRegstrationId.equals("")) {
GCMRegistrar.register(this, SENDER_ID);
}
// Initialize CheckInService
try {
mCheckInService = new DebugCheckInService(this, new ProgressFilter());
} catch (MalformedURLException e) {
if (D) Log.e(TAG, e.getMessage(), e);
}
}
private class ProgressFilter implements ServiceFilter {
@Override
public void handleRequest(ServiceFilterRequest request, NextServiceFilterCallback nextServiceFilterCallback,
final ServiceFilterResponseCallback responseCallback) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mProgressBar.setVisibility(ProgressBar.VISIBLE);
}
11
});
nextServiceFilterCallback.onNext(request, new ServiceFilterResponseCallback() {
@Override
public void onResponse(ServiceFilterResponse response, Exception exception) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mProgressBar.setVisibility(ProgressBar.GONE);
}
});
responseCallback.onResponse(response, exception);
}
});
}
}
}
12
1.4 SRC\CHECKINRECORD.JAVA
package com.connect.cinlo;
public class CheckInRecord {
/**
* CheckInRecord ID
*/
@com.google.gson.annotations.SerializedName("id")
private int mId;
/**
* Push notifications ID
*/
@com.google.gson.annotations.SerializedName("channel")
private String mRegistrationId;
/**
* Name of the the person who checked-in
*/
@com.google.gson.annotations.SerializedName("name")
private String mName;
/**
* X-coordinate of the CheckInRecord
*/
@com.google.gson.annotations.SerializedName("x")
private int mX;
/**
* Y-coordinate of the CheckInRecord
*/
@com.google.gson.annotations.SerializedName("y")
private int mY;
/**
* Indicates if the check-in was made at a workplace
*/
@com.google.gson.annotations.SerializedName("at_workplace")
private boolean mAtWorkplace;
/**
* The time limit the CheckInRecord will retain in milliseconds
*/
@com.google.gson.annotations.SerializedName("limit")
private int mLimit;
/**
* CheckInRecord constructor
*/
public CheckInRecord() { }
/**
* Initializes a new CheckInRecord
13
*
*
*
*
*
*
*
*
*
*
*
*
*
@param id
The CheckInRecord ID
@param name
Name of the the person who checked-in
@param x
X-coordinate of the CheckInRecord
@param y
Y-coordinate of the CheckInRecord
@param atWorkplace
Indicates if the check-in was made at a workplace
@param limit
The time limit the CheckInRecord will retain in milli-
seconds
*/
public CheckInRecord(int id, String name, int x, int y, boolean atWorkplace,
int limit) {
this.setId(id);
this.setName(name);
this.setX(x);
this.setY(y);
this.setAtWorkplace(atWorkplace);
this.setLimit(limit);
}
/**
* Returns the CheckInRecord id
*/
public int getId() {
return mId;
}
/**
* Sets the CheckInRecord id
* @param id
*
id to set
*/
public void setId(int id) {
mId = id;
}
/**
* Returns the id used for push notifications
*/
public String getRegistrationId() {
return mRegistrationId;
}
/**
* Sets the id used for push notifications
* @param registrationId
*
id to set
*/
public final void setRegistrationId(String registrationId) {
mRegistrationId = registrationId;
14
}
/**
* Returns the name of the the person at the checked-in position
*/
public String getName() {
return mName;
}
/**
* Sets the name of the the person at the checked-in position
* @param name
*
name to set
*/
public void setName(String name) {
mName = name;
}
/**
* Returns the x-coordinate of the CheckInRecord
*/
public int getX() {
return mX;
}
/**
* Sets the x-coordinate of the CheckInRecord
* @param x
*
x-coordinate to set
*/
public void setX(int x) {
mX = x;
}
/**
* Returns the y-coordinate of the CheckInRecord
*/
public int getY() {
return mY;
}
/**
* Sets the y-coordinate of the CheckInRecord
* @param y
*
y-coordinate to set
*/
public void setY(int y) {
mY = y;
}
/**
* Indicates if the CheckInRecord was made at a workplace
*/
public boolean isAtWorkplace() {
return mAtWorkplace;
15
}
/**
* Marks the CheckInRecord to be at a workplace or not
*/
public void setAtWorkplace(boolean atWorkplace) {
mAtWorkplace = atWorkplace;
}
/**
* Returns the time limit the CheckInRecord will retain in milliseconds
*/
public int getLimit() {
return mLimit;
}
/**
* Sets the time limit the CheckInRecord will retain in milliseconds
* @param limit
*
limit to set
*/
public void setLimit(int limit) {
mLimit = limit;
}
@Override
public String toString() {
return mName;
}
public boolean equalPosition(CheckInRecord o) {
return o.mX == mX && o.mY == mY;
}
public boolean equalName(CheckInRecord o) {
return o.mName.equals(mName);
}
@Override
public boolean equals(Object o) {
return o instanceof CheckInRecord
&& equalName((CheckInRecord)o)
&& equalPosition((CheckInRecord)o);
}
}
16
1.5 SRC\CHECKINSERVICE.JAVA
package com.connect.cinlo;
import java.net.MalformedURLException;
import java.util.List;
import
import
import
import
import
import
import
android.app.TimePickerDialog;
android.app.TimePickerDialog.OnTimeSetListener;
android.content.Context;
android.util.Log;
android.widget.ArrayAdapter;
android.widget.TimePicker;
android.widget.Toast;
import
import
import
import
import
import
import
com.microsoft.windowsazure.mobileservices.MobileServiceClient;
com.microsoft.windowsazure.mobileservices.MobileServiceTable;
com.microsoft.windowsazure.mobileservices.ServiceFilter;
com.microsoft.windowsazure.mobileservices.ServiceFilterResponse;
com.microsoft.windowsazure.mobileservices.TableDeleteCallback;
com.microsoft.windowsazure.mobileservices.TableOperationCallback;
com.microsoft.windowsazure.mobileservices.TableQueryCallback;
public class CheckInService {
// Debug constants
private static final boolean D = true;
private static final String TAG = "CheckInService";
private
private
private
private
MobileServiceClient mClient;
Context mContext;
MobileServiceTable<CheckInRecord> mCheckInRecordTable;
ArrayAdapter<CheckInRecord> mAdapter;
public CheckInService(Context context, ServiceFilter filter, ArrayAdapter<CheckInRecord> adapter) throws MalformedURLException {
mContext = context;
mAdapter = adapter;
mClient = new MobileServiceClient(
"MobileServiceUrl/",
"AppKey",
context).withFilter(filter);
mCheckInRecordTable = mClient.getTable(CheckInRecord.class);
if (D) Log.d(TAG, "CheckInService created");
}
public void refresh() {
mCheckInRecordTable.execute(new TableQueryCallback<CheckInRecord>() {
@Override
public void onCompleted(List<CheckInRecord> savedRecords, int
count,
17
Exception exception, ServiceFilterResponse response)
{
if (exception == null) {
mAdapter.clear();
for (CheckInRecord savedRecord : savedRecords) {
mAdapter.add(savedRecord);
}
} else {
showMessage("Failed to retrive saved check-in records, please try again.");
}
}
});
}
public void checkInCheckOut(CheckInRecord record) {
mCheckInRecordTable
.where()
.field("name").eq(record.getName())
.or()
.field("x").eq(record.getX())
.and()
.field("y").eq(record.getY())
.execute(new TableQueryCallback<CheckInRecord>() {
private CheckInRecord qRecord;
private CheckInRecord savedUserRecord;
private CheckInRecord savedRecordAtPosition;
@Override
public void onCompleted(List<CheckInRecord> savedRecords,
int count,
Exception exception, ServiceFilterResponse
response) {
if (exception == null) {
savedUserRecord = getSavedUserRecord(qRecord,
savedRecords);
savedRecordAtPosition = getSavedRecordAtPosition(qRecord, savedRecords);
if (savedUserRecord != null &&
qRecord.equals(savedUserRecord)) {
checkOut(savedUserRecord);
} else {
if (!qRecord.isAtWorkplace()) {
TimePickerDialog td = new
TimePickerDialog(mContext, new OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
qRecord.setLimit(Util.hoursToMilliseconds(hourOfDay)
18
+
Util.minutesToMilliseconds(minute));
checkIn(qRecord,
savedUserRecord, savedRecordAtPosition);
}
}, 1, 0, true);
td.setMessage("Set time in meeting");
td.show();
} else {
checkIn(qRecord, savedUserRecord, savedRecordAtPosition);
}
}
} else {
if (D) Log.e(TAG, exception.getMessage(),
exception);
showMessage("Failed to recieve records,
please try again.");
}
}
private TableQueryCallback<CheckInRecord> init(CheckInRecord record) {
qRecord = record;
return this;
}
}.init(record));
}
public void checkIn(CheckInRecord record, CheckInRecord savedUserRecord,
CheckInRecord savedRecordAtPosition) {
if (savedUserRecord != null) {
mCheckInRecordTable.delete(savedUserRecord, new TableDeleteCallback() {
@Override
public void onCompleted(Exception exception, ServiceFilterResponse response) {
if (exception == null) {
if (D) Log.i(TAG, "Removed old user record");
} else {
if (D) Log.e(TAG, "Failed to remove old user
record", exception);
}
}
});
}
if (savedRecordAtPosition != null && savedRecordAtPosition.isAtWorkplace()) {
record.setId(savedRecordAtPosition.getId());
mCheckInRecordTable.update(record, new TableOperationCallback<CheckInRecord>() {
19
@Override
public void onCompleted(CheckInRecord result, Exception
exception,
ServiceFilterResponse response) {
if (exception == null) {
refresh();
showMessage("You have checked-in.");
if (D) Log.i(TAG, "New check-in. Updated
saved record at position");
} else {
showMessage("Failed to check-in");
if (D) Log.e(TAG, "Failed to update saved
record at position", exception);
}
}
});
} else {
mCheckInRecordTable.insert(record, new TableOperationCallback<CheckInRecord>() {
@Override
public void onCompleted(CheckInRecord result, Exception
exception,
ServiceFilterResponse response) {
if (exception == null) {
refresh();
showMessage("You have checked-in.");
if (D) Log.i(TAG, "New check-in. Inserted new
record");
} else {
showMessage("Failed to check-in, please try
again.");
if (D) Log.e(TAG, "Failed to insert new record", exception);
}
}
});
}
}
public void checkOut(CheckInRecord savedUserRecord) {
mCheckInRecordTable.delete(savedUserRecord, new TableDeleteCallback() {
@Override
public void onCompleted(Exception exception, ServiceFilterResponse response) {
if (exception == null) {
refresh();
showMessage("You have been checked out.");
if (D) Log.i(TAG, "User checked-out. Removed old
record.");
} else {
showMessage("Failed to check out, please try
again.");
20
if (D) Log.e(TAG, "Failed to remove old record",
exception);
}
}
});
}
private CheckInRecord getSavedUserRecord(CheckInRecord record,
List<CheckInRecord> savedRecords) {
for (CheckInRecord savedRecord : savedRecords) {
if (record.equalName(savedRecord))
return savedRecord;
}
return null;
}
private CheckInRecord getSavedRecordAtPosition(CheckInRecord record,
List<CheckInRecord> savedRecords) {
for (CheckInRecord savedRecord : savedRecords) {
if (record.equalPosition(savedRecord) &&
savedRecord.isAtWorkplace()
&& !record.equalName(savedRecord)) {
return savedRecord;
}
}
return null;
}
private void showMessage(String msg) {
Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
}
}
21
1.6 SRC\DEBUGCHECKINSERVICE.JAVA
package com.connect.cinlo;
import java.net.MalformedURLException;
import java.util.List;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import
import
import
import
import
import
import
com.microsoft.windowsazure.mobileservices.MobileServiceClient;
com.microsoft.windowsazure.mobileservices.MobileServiceTable;
com.microsoft.windowsazure.mobileservices.ServiceFilter;
com.microsoft.windowsazure.mobileservices.ServiceFilterResponse;
com.microsoft.windowsazure.mobileservices.TableDeleteCallback;
com.microsoft.windowsazure.mobileservices.TableOperationCallback;
com.microsoft.windowsazure.mobileservices.TableQueryCallback;
public class DebugCheckInService {
// Debug constants
private static final boolean D = true;
private static final String TAG = "CheckInService";
private MobileServiceClient mClient;
private Context mContext;
private MobileServiceTable<CheckInRecord> mCheckInRecordTable;
public DebugCheckInService(Context context, ServiceFilter filter) throws MalformedURLException {
mContext = context;
mClient = new MobileServiceClient(
"MobileServiceUrl”,
"AppKey",
context).withFilter(filter);
mCheckInRecordTable = mClient.getTable(CheckInRecord.class);
if (D) Log.d(TAG, "CheckInService created");
}
public void checkInCheckOut(CheckInRecord record) {
mCheckInRecordTable
.where()
.field("name").eq(record.getName())
.or()
.field("x").eq(record.getX())
.and()
.field("y").eq(record.getY())
.execute(new TableQueryCallback<CheckInRecord>() {
private CheckInRecord qRecord;
private CheckInRecord savedUserRecord;
private CheckInRecord savedRecordAtPosition;
@Override
22
public void onCompleted(List<CheckInRecord> savedRecords,
int count,
Exception exception, ServiceFilterResponse
response) {
if (exception == null) {
savedUserRecord = getSavedUserRecord(qRecord,
savedRecords);
savedRecordAtPosition = getSavedRecordAtPosition(qRecord, savedRecords);
if (savedUserRecord != null &&
qRecord.equals(savedUserRecord)) {
checkOut(savedUserRecord);
} else {
checkIn(qRecord, savedUserRecord,
savedRecordAtPosition);
}
} else {
if (D) Log.e(TAG, exception.getMessage(),
exception);
showMessage("Failed to recieve records,
please try again.");
}
}
private TableQueryCallback<CheckInRecord> init(CheckInRecord record) {
qRecord = record;
return this;
}
}.init(record));
}
public void checkIn(CheckInRecord record, CheckInRecord savedUserRecord,
CheckInRecord savedRecordAtPosition) {
if (savedUserRecord != null) {
mCheckInRecordTable.delete(savedUserRecord, new TableDeleteCallback() {
@Override
public void onCompleted(Exception exception, ServiceFilterResponse response) {
if (exception == null) {
if (D) Log.i(TAG, "Removed old user record");
} else {
if (D) Log.e(TAG, "Failed to remove old user
record", exception);
}
}
});
}
if (savedRecordAtPosition != null && savedRecordAtPosition.isAtWorkplace()) {
23
record.setId(savedRecordAtPosition.getId());
mCheckInRecordTable.update(record, new TableOperationCallback<CheckInRecord>() {
@Override
public void onCompleted(CheckInRecord result, Exception
exception,
ServiceFilterResponse response) {
if (exception == null) {
showMessage("You have checked-in.");
if (D) Log.i(TAG, "New check-in. Updated
saved record at position");
} else {
showMessage("Failed to check-in");
if (D) Log.e(TAG, "Failed to update saved
record at position", exception);
}
}
});
} else {
mCheckInRecordTable.insert(record, new TableOperationCallback<CheckInRecord>() {
@Override
public void onCompleted(CheckInRecord result, Exception
exception,
ServiceFilterResponse response) {
if (exception == null) {
showMessage("You have checked-in.");
if (D) Log.i(TAG, "New check-in. Inserted new
record");
} else {
showMessage("Failed to check-in, please try
again.");
if (D) Log.e(TAG, "Failed to insert new record", exception);
}
}
});
}
}
public void checkOut(CheckInRecord savedUserRecord) {
mCheckInRecordTable.delete(savedUserRecord, new TableDeleteCallback() {
@Override
public void onCompleted(Exception exception, ServiceFilterResponse response) {
if (exception == null) {
showMessage("You have been checked out.");
if (D) Log.i(TAG, "User checked-out. Removed old
record.");
} else {
showMessage("Failed to check out, please try
again.");
24
if (D) Log.e(TAG, "Failed to remove old record",
exception);
}
}
});
}
private CheckInRecord getSavedUserRecord(CheckInRecord record,
List<CheckInRecord> savedRecords) {
for (CheckInRecord savedRecord : savedRecords) {
if (record.equalName(savedRecord))
return savedRecord;
}
return null;
}
private CheckInRecord getSavedRecordAtPosition(CheckInRecord record,
List<CheckInRecord> savedRecords) {
for (CheckInRecord savedRecord : savedRecords) {
if (record.equalPosition(savedRecord) &&
savedRecord.isAtWorkplace()
&& !record.equalName(savedRecord)) {
return savedRecord;
}
}
return null;
}
private void showMessage(String msg) {
Toast.makeText(mContext, msg, Toast.LENGTH_SHORT).show();
}
}
25
1.7 SRC\GCMINTENTSERVICE.JAVA
package com.connect.cinlo;
import
import
import
import
import
import
import
import
android.app.Notification;
android.app.NotificationManager;
android.app.PendingIntent;
android.content.Context;
android.content.Intent;
android.content.SharedPreferences;
android.preference.PreferenceManager;
android.support.v4.app.NotificationCompat;
import com.connect.cinlo.R;
import com.google.android.gcm.GCMBaseIntentService;
public class GCMIntentService extends GCMBaseIntentService {
private static String sRegistrationId;
public static String getRegistrationId() {
return sRegistrationId;
}
public GCMIntentService(){
super(DebugActivity.SENDER_ID);
}
@Override
protected void onError(Context arg0, String arg1) {
// TODO Auto-generated method stub
}
@Override
protected void onMessage(Context context, Intent intent) {
String name = intent.getStringExtra("message");
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
if (name != null && !name.equals(prefs.getString(MainActivity.PREF_NAME,
"John Doe"))) {
Intent resultIntent = new Intent(context, MainActivity.class);
PendingIntent pIntent = PendingIntent.getActivity(context, 0,
resultIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder mBuilder =
new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle("New check-in!")
.setContentIntent(pIntent)
.setAutoCancel(true)
.setPriority(Notification.PRIORITY_HIGH)
.setContentText(intent.getStringExtra("message"));
26
NotificationManager mNotificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
mNotificationManager.notify(0, mBuilder.build());
}
}
@Override
protected void onRegistered(Context context, String registrationId) {
sRegistrationId = registrationId;
}
@Override
protected void onUnregistered(Context arg0, String arg1) {
// TODO Auto-generated method stub
}
}
27
1.8 SRC\NFCUTILS.JAVA
package com.connect.cinlo;
import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import com.google.common.base.Preconditions;
import android.nfc.NdefRecord;
public class NFCUtils {
public static String parseTextRecord(NdefRecord record) {
Preconditions.checkArgument(record.getTnf() == NdefRecord.TNF_WELL_KNOWN);
Preconditions.checkArgument(Arrays.equals(record.getType(), NdefRecord.RTD_TEXT));
try {
byte[] payload = record.getPayload();
String textEncoding = ((payload[0] & 0200) == 0) ? "UTF-8" :
"UTF-16";
int languageCodeLength = payload[0] & 0077;
String text = new String(payload, languageCodeLength + 1,
payload.length - languageCodeLength - 1, textEncoding);
return text;
} catch(UnsupportedEncodingException e) {
throw new IllegalArgumentException(e);
}
}
}
28
1.9 SRC\UTIL.JAVA
package com.connect.cinlo;
public class Util {
public static final int HOUR_IN_MS = 3600000;
public static final int MINUTE_IN_MS = 60000;
public static int hoursToMilliseconds(int hours) {
return hours * HOUR_IN_MS;
}
public static int minutesToMilliseconds(int minutes) {
return minutes * MINUTE_IN_MS;
}
}
29
1.10 ANDROIDMANIFEST.XML
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.connect.cinlo"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="17" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<permission android:name="com.connect.cinlo.permission.C2D_MESSAGE"
android:protectionLevel="signature" />
<uses-permission android:name="com.connect.cinlo.permission.C2D_MESSAGE" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme">
<activity
android:name="com.connect.cinlo.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
</activity>
<activity
android:name="com.connect.cinlo.SettingsActivity"
android:label="@string/title_settings_activity" >
</activity>
<activity
android:name="com.connect.cinlo.DebugActivity"
android:label="@string/tittle_debug_activity" >
</activity>
<receiver
android:name="com.google.android.gcm.GCMBroadcastReceiver"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.connect.cinlo" />
30
</intent-filter>
</receiver>
<service android:name="com.connect.cinlo.GCMIntentService" />
</application>
</manifest>
31
1.11 RES\LAYOUT\ACTIVITY_MAIN.XML
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<ProgressBar
android:id="@+id/progress"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical|center_horizontal"
android:visibility="gone" />
<AutoCompleteTextView
android:id="@+id/autocomplete_name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:hint="@string/search_hint"
android:visibility="gone">
<requestFocus />
</AutoCompleteTextView>
<TextView
android:id="@+id/textViewNoConnection"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:text="@string/text_no_connection"
android:textColor="@android:color/darker_gray"
android:textAppearance="?android:attr/textAppearanceLarge" />
<it.sephiroth.android.library.imagezoom.ImageViewTouch
android:id="@+id/imageViewTouch"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:scaleType="fitCenter"
android:visibility="gone" />
</LinearLayout>
32
1.12 RES\LAYOUT\ACTIVITY_DEBUG.XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/LinearLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ProgressBar
android:id="@+id/progress"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center_vertical|center_horizontal"
android:visibility="gone" />
<TextView
android:id="@+id/textViewName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_name"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="@+id/editTextName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="textPersonName" >
<requestFocus />
</EditText>
<TextView
android:id="@+id/textViewX"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_x"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="@+id/editTextX"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number" />
<TextView
android:id="@+id/textViewY"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_y"
android:textAppearance="?android:attr/textAppearanceMedium" />
33
<EditText
android:id="@+id/editTextY"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number" />
<TextView
android:id="@+id/textViewLimit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/label_limit"
android:textAppearance="?android:attr/textAppearanceMedium" />
<EditText
android:id="@+id/editTextLimit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:inputType="number" />
<CheckBox
android:id="@+id/checkBoxAtWorkplace"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/chk_at_workplace" />
<Button
android:id="@+id/buttonSubmit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/btn_submit" />
</LinearLayout>
34
1.13 RES\LAYOUT\ACTION_SEARCH.XML
<?xml version="1.0" encoding="utf-8"?>
<AutoCompleteTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/search_hint" />
35
1.14 RES\MENU\MAIN.XML
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="@+id/action_search"
android:title="@string/action_search"
android:icon="@android:drawable/ic_menu_search"
android:showAsAction="ifRoom|collapseActionView"
android:actionLayout="@layout/action_search" />
<item
android:id="@+id/action_settings"
android:icon="@android:drawable/ic_menu_preferences"
android:title="@string/action_settings"
android:showAsAction="collapseActionView" />
<item
android:id="@+id/action_refresh"
android:icon="@android:drawable/ic_popup_sync"
android:title="@string/action_refresh"
android:showAsAction="collapseActionView" />
<item
android:id="@+id/action_debug"
android:title="@string/action_debug" />
</menu>
36
1.15 RES\VALUES\STRINGS.XML
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string
<string
<string
<string
<string
<string
<string
<string
<string
<string
<string
<string
<string
<string
<string
<string
<string
<string
name="app_name">Cinlo</string>
name="action_settings">Settings</string>
name="hello_world">Hello world!</string>
name="title_settings_activity">Settings</string>
name="pref_firstname_summary">Enter your first name</string>
name="pref_lastname_summary">Enter your last name</string>
name="label_x">Enter position x-coordinate:</string>
name="label_y">Enter position y-coordinate:</string>
name="chk_at_workplace">Position at a workplace</string>
name="btn_submit">Submit</string>
name="action_debug">Debug</string>
name="tittle_debug_activity">Debug</string>
name="search_hint">Firstname Lastname</string>
name="label_name">Enter your name:</string>
name="label_limit">Enter time limit:</string>
name="action_refresh">Refresh</string>
name="text_no_connection">No connection</string>
name="action_search">Search for checkins</string>
</resources>
37
1.16 RES\VALUES\DIMENS.XML
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
</resources>
38
1.17 RES\VALUES\STYLES.XML
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-Base application theme, dependent on API level. This theme is replaced
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
-->
<style name="AppBaseTheme" parent="android:Theme.Light">
<!-Theme customizations available in newer API levels can go in
res/values-vXX/styles.xml, while customizations related to
backward-compatibility can go here.
-->
</style>
<!-- Application theme. -->
<style name="AppTheme" parent="AppBaseTheme">
<!-- All customizations that are NOT specific to a particular API-level can
go here. -->
</style>
<style name="LoginFormContainer">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:padding">16dp</item>
</style>
</resources>
39
1.18 RES\XML\USERPREFERENCES.XML
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<EditTextPreference android:summary="Enter your name" android:title="Name" android:key="PREF_NAME"/>
</PreferenceScreen>
40
Was this manual useful for you? yes no
Thank you for your participation!

* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project

Related manuals

Download PDF

advertisement