• No results found

Marknadsplatsapplikation för Android

N/A
N/A
Protected

Academic year: 2021

Share "Marknadsplatsapplikation för Android"

Copied!
93
0
0

Loading.... (view fulltext now)

Full text

(1)

Institutionen för datavetenskap

Department of Computer and Information Science

Examensarbete

Marknadsplatsapplikation för Android

av

Simon Arvidsson och Tobias Ekblom

LIU-IDA/LITH-EX-A—12/002—SE

2012-03-14

(2)

Linköpings universitet

Institutionen för datavetenskap

Examensarbete

Marknadsplatsapplikation för Android

av

Simon Arvidsson och Tobias Ekblom

LIU-IDA/LITH-EX-A—12/002—SE

2012-03-14

Handledare: Mikael Asplund Examinator: Simin Nadjm-Tehrani

(3)

Sammanfattning

Målet med examensarbetet är att utveckla en marknadsplatsapplikation för Android. Marknadsplatsapplikationen ska tillhandahålla funktioner för att ge användaren förutsättningar att hitta och ladda ner applikationer över Inter-net ifrån marknadsplatsens serversida. Marknadsplatsapplikationen kommer likt en tunn klient vara helt beroende av innehåll från en serversida. Vid examensarbetets utförande existerade dock ingen serversida då denna ännu inte var färdigutvecklad.

För att utveckla marknadsplatsapplikationen utan närvaron av en server-sida, implementerades en emulerad serversida som utåt sett hade funktiona-liteten av en framtida serversida. En mjukvaruarkitektur implementerades bestående av tre lager: användargränsnitt (GUI), kärnfunktionalitet (Core) och webbkommunikation (WebCom). Syftet med arikitekturen var dels att begränsa inverkan av övergången från en emulerad serversida till en riktig serversida, och dels att avgränsa och avlasta användargränsnittet från tunga operationer för att därigenom uppnå god responsivitet.

Marknadsplatsapplikationen implementerades med all funktionalitet som planerades. Arkitekturen med tydlig separation mellan GUI, Core och WebCom, förväntas leda till en smidig övergång till en riktig serversida. Även ett tydligt öde för att hämta och skicka data mellan marknadsplatsapplikationen och serversida förväntas underlätta att implementera ny funktionalitet som är beroende av en serversida. Användargränsnittet uppvisar fortfarande brist på responsivitet. Arkitekturen med endast en asynkron klass GuiWorker, som hanterar exekveringen av tunga operationer på bakgrundstrådar, förväntas dock kunna uppnå ett responsivt användargränsnitt.

(4)

Innehåll

1 Introduktion 1 1.1 Bakgrund . . . 1 1.2 Problembeskrivning . . . 1 1.3 Problemområden . . . 3 1.4 Angreppsätt . . . 6 1.5 Arbetsdelning . . . 7 1.6 Läsinstruktioner . . . 8 1.7 Begränsningar . . . 8 2 Androidplattformen 9 2.1 Översikt . . . 9 2.2 Marknadsapplikationens huvudkomponenter . . . 10 2.3 Användargränssnitt . . . 11 2.4 Resurser . . . 13 2.5 Plattformsversioner . . . 14 2.6 Andra marknadsplatsappar . . . 16

3 Kommunikation med WEB 17 3.1 Angreppsätt . . . 17 3.2 Designval . . . 18 3.3 Implementation . . . 19 3.3.1 Fetcher . . . 19 3.3.2 Sender . . . 20 3.3.3 ConnectionHandler . . . 21 4 Serialiseringsformat 22 4.1 Angreppssätt . . . 22 4.1.1 XML . . . 23

(5)

4.1.2 JSON . . . 24

4.1.3 Protocol Buers . . . 24

4.1.4 Jämförelse av hastighet . . . 26

4.2 Designval . . . 28

4.3 Implementation . . . 28

5 Fylla och visa applista 30 5.1 Angreppssätt . . . 31 5.1.1 Adapters . . . 31 5.1.2 Cachning av bildikoner . . . 35 5.1.3 Proxy för bildikoner . . . 36 5.2 Designval . . . 37 5.3 Implementation . . . 37

6 Ladda ner och installera appar 41 6.1 Angreppssätt . . . 41

6.1.1 Nedladdning med standardwebbläsaren . . . 41

6.1.2 Nedladdning inne i appen . . . 42

6.1.3 Standard android install . . . 43

6.1.4 Installation inne i APP . . . 44

6.2 Designval . . . 46

6.3 Implementation . . . 47

6.3.1 Nedladdning . . . 48

6.3.2 Installering . . . 48

7 Uppdatera och synkronisera appstatus mellan WEB och APP 50 7.1 Angreppsätt . . . 50

7.2 Designval . . . 51

7.3 Implementation . . . 52

7.3.1 Ny till Nedladdad . . . 52

7.3.2 Till Installerad och Avinstallerad . . . 53

7.3.3 PackageIntentReciever . . . 53

7.3.4 AppStatusHandler . . . 54

8 Swipe och ing med menywidget 58 8.1 Angreppssätt . . . 59

8.1.1 Gallery . . . 60

(6)

8.1.3 HorizontalPager . . . 60

8.1.4 Skapa en egen View . . . 62

8.2 Designval . . . 62 8.3 Implementation . . . 63 8.3.1 Horizontal Pager . . . 63 8.3.2 Menywidget . . . 64 8.3.3 SwipeHolder . . . 66 9 Responsivt användargränssnitt 68 9.1 Angreppsätt . . . 69 9.1.1 Java Thread . . . 69 9.1.2 Android AsyncTask . . . 70 9.2 Designval . . . 70 9.3 Implementation . . . 71 10 Byggverktyg 73 10.1 Angreppssätt . . . 73 10.1.1 Maven . . . 74 10.1.2 Ant . . . 75 10.2 Designval . . . 75 10.3 Implementation . . . 76

11 Funktionella och icke-funktionella tester 77 11.1 Responsivt användargrässnitt . . . 77 11.2 MockWEB . . . 79 11.3 Sammanfattning . . . 81 12 Diskussion 82 12.1 Resultat . . . 82 12.2 Framtida arbete . . . 83 12.3 Slutsats . . . 84

(7)

Kapitel 1

Introduktion

Denna rapport beskriver arbete utfört inom ramen av ett projekt som täcker två 30hp examensarbeten inom civingenjörutbildningen Informationstekno-logi vid Linköpings universitet.

1.1 Bakgrund

Uppdragsgivaren för examensarbetet är ett nystartat företag som skapar en marknadsplats för Androidapplikationer. En marknadsplats är en tjänst som låter användare köpa eller gratis ladda ner applikationer, så kallade appar, till sina telefoner. I dagsläget nns ett tiotal marknadsplatser för Android-applikationer i världen, varav Googles Android Market är den största. Utbudet av applikationer har växt explosionsartat de senaste åren och idag nns det drygt 200 000 appar på Android Market. Trots det ofta låga priset på appar förväntas applikationsindustrin göra en vinst på 15 miljarder dollar 2011 och vinsten väntas växa till 58 miljarder dollar inom fem år [1].

Marknadsplatserna består oftast av en webbplats där användare kan pusha applikationer till telefonen och en applikation på smartphonen där användare direkt kan nå maknadsplatsen och ladda ned applikationer.

1.2 Problembeskrivning

Det beställande företaget vill utveckla en marknadsplatsapplikation till Andro-id. Alla delar av Marknadsapplikationen, kommer hädanefter benämnas APP, som inte inkluderar graska element ska vara klara efter examensarbetets

(8)

slutförande och kommer därför att ha en tidsram på 40 arbetsveckor.

Den förutbestämda arkitekturen för marknadsplatsen kan ses på nedanstå-ende bild. APP GUI Databas Betalsystem Databas Internet GUI WEB Affärssystem

Figur 1.1: Marknadsplatsens arkitektur

APP är en del av hela marknadsplatsen och kommer att fungera som en tunn klient mot marknadsplatsens serversida, kallad WEB, där all information som visas i APP nns. APP kommer med andra ord inte lagra någon infor-mation, utan istället kommer allt att hämtas ifrån WEB, likt en traditionell webbläsare. APP kommer dock innehålla en databas för att cacha information för snabbare laddningar.

WEB kommer att hantera kommunikationen med ett betalsystem som hanterar köp av applikationer ifrån APP. WEB kommer också att exponera en webbsida där köp av applikationer kommer att kunna genomföras.

All kommunikationen ifrån APP med WEB sker över internet. Under utveck-lingen av APP kommer ingen serversida att existera då utveckutveck-lingen av WEB sker parallellt och kommunikationen mellan dessa inte är prioriterad. Det innebär att verieringen av funktionaliteten i APP försvåras då den är väldigt beroende av kommunikationen med WEB.

(9)

det beställande företaget vill att den färdiga APP ska inneha, följande: • Visa lista med appar

• Söka efter appar

• Ladda ner och installera en app • Visa mina appar

• Ett användargränssnitt med swipe och ing

Utöver de funktionella kraven ovan har det beställande företaget även icke funktionella krav i form av:

• Applikationen och dess användargränssnitt ska vara responsivt, det vill säga att användargränssnittet inte ska hänga sig eller lagga.

• Applikationen ska kunna kvalitetstestas med enhetstester och kodtäck-ning av ett byggverktyg.

1.3 Problemområden

Funktionaliteterna som presenterades i problembeskrivningen delar liknande problem med varandra. Dessa kan delas upp i olika problemområden. Figur 1.2 visar övergången ifrån funktionalitet till problemområden.

Utöver dessa problemområden ger de icke funktionella kraven ifrån pro-blembeskrivningen två problemområden till. Ett problemområde som handlar om användargränssnittets responsivitet och ett som handlar om att nna ett byggverktyg som kan enhetstesta och köra kodtäckning på källkoden.

Problemområdena kommer att fungera som kapitelrubriker i rapporten där olika angreppsätt för att lösa dem kommer att beskrivas. Varje kapitel avslutas med ett avsnitt om de designval som gjorts för att lösa problemet samt hur den konkreta implementationen har gjorts. Nedan beskrivs respek-tive problemområde i korthet:

(10)

Ansluta till webbserver

Serialiserings-format

Fylla och visa applista

Uppdatera och synkronisera

appstatus

Ladda ner och installera apk:er Visa applista Söka Ladda ner och installera Mina Appar

Swipe och fling

Figur 1.2: Funktionaliteter och deras gemensamma problemområden

Anslutning till webbserver

Problemområdet handlar om hur APP ansluter till WEB. Det rör framförallt hur arkitekturen ska se ut i APP för att ansluta och hämta information ifrån WEB.

Serialiseringsformat

Handlar om vilket serialiseringsformat som är lämpligast att använda på lerna som skickas mellan APP och WEB. De serialiseringsformat som ska undersökas är XML, JSON och Protocol Buers.

Fylla och visa applista

Handlar om vilka sätt det går att fylla en lista på i Android. Området berör också vilka tekniker det nns för att snabba upp renderingen av en lista.

(11)

Uppdatera och synkronisera appstatus

Problemområdet diskuterar hur applikationers status uppdateras. Det vill säga om den är nedladdad, installerad, uppdateringsbar eller avinstallerad. Området beskriver också hur denna information kan synkroniseras mellan APP och WEB.

Ladda ner och installera appar

Behandlar hur nedladdning och installation av appar hanteras.

Swipe och ing med menywidget

Beskriver de olika tekniker som nns för swipe och ing som är en teknik att röra ett fönster i sidled med hjälp av att dra ngret i sidled på skärmen. Typiskt exempel är bläddring mellan bilder i ett album. Området beskriver också hur en menywidget kan kopplas till denna swipe och ing.

Responsivt användargränssnitt

Behandlar vilka tekniker som kan användas för att få ett användargränssnitt som är responsivt, det vill säga ett användargränssnitt som användaren kan ständigt interagera med och inte hänger sig.

I APP utförs många tunga operationer som inte får interferera med använ-darupplevelsen. Dessa operationer utgörs bland annat av kommmunikation med WEB och läsning och skrivning lokalt på enheten. Även om ett anrop till WEB med routring, parsning och behandling på en extern server, är mer avancerad än ett lokalt anrop är de likvärdiga från användargränssnittets perspektiv, det vill säga: tidskrävande. Användargränssnittet bör designas för att kunna klara alla typer av tunga operationer.

Byggverktyg

Problemområdet beskriver vilka byggverktyg som är lämpliga att använda för Android. Byggverktygen ska kunna automatisera processen att kompilera, testa och skapa kodtäcknignsrapporter för källkoden.

(12)

Veriering

Behandlar hur funktionaliteten i APP verieras då en WEB inte existerar. Pro-blemområdet behandlar också benchmarktester för olika serialiseringsformat.

1.4 Angreppsätt

För att täcka in alla funktionella och icke funktionella krav, designades en mjukvaruarkitektur enligt gur 1.3. Här har de delar som gäller APP förnats i förhållande till gur 1.1. Alla anrop initeras i det översta lagret, antingen genom att användaren interagerar med det graska interfacet(gui), eller av att Androidplattformen skickar ut meddelande i systemet(ett så kallat intent). Anropen går sedan till Core-lagret, då de översta lagren aldrig får anropa WebCom direkt. Syftet är att beroenden inte ska sträckas över hela systemet, utan begränsas till intilligande moduler.

GUI CORE WEBCOM Detailed App View My Apps View Search View Gui Worker Gui Task ApkInstall Handler ApkUnInstall Handler AppStatus Handler

Parser Fetcher Connection

Handler MOCK WEB MockWEB Filesystem MOCK Data ApkDownload Handler Category View Intent Recievers PackageIntent Reciever WEB UriBuilder ImageLoader Sender Toplist View DB Cache

(13)

i GUI-lagret som via Core-lagret hämtar data från WEB med hjälp av Fetcher i WebCom.

Det funktionella kravet som säger att det ska vara möjligt att ladda ner och installera appar, initeras av Detailed App View och utnyttjar modulerna ApkInstallHandler och ApkUninstallHandler.

För det funktionella kravet att visa mina appar, krävs en hantering av status för mina appar. Detta sköts av AppStatusHandler som initieras från GUI:t, men även av så kallade intents från Androidplattformen, som fångas av IntentRecievers. Intent används i Android för att kommunicera inom och mellan olika applikationer.

Det sista funktionella kravet att användargränsnittet ska ha swipe- och ing-funktionalitet, hanteras helt i GUI-lagret.

Det icke funktionella kravet att användargränssnittet ska vara responsivt hanteras av GuiWorker och GuiTask, som skyddar användargränsnittet från att överbelastas. För att göra upplevelsen än snabbare används en Cache, dels virtuellt i minnet och dels till en databas för längre förvaring.

1.5 Arbetsdelning

För att kunna göra en individuell bedömning så ansvarade Simon och Tobias för olika delar. Sett utifrån arkitekturen i gur 1.3 ansvarade Tobias för ut-vecklingen av Parser (i WebCom-lagret), Gui-lagret och delar nära kopplade till GuiTask och ImageLoader med Cache (i Core-lagret). Simon ansvarade för IntentReceivers, övriga delar av Core- och WebCom-lagret samt MockWeb. Tobias ansvarade för veriering av kommunikationsprotokollet och Simon ansvarade för responsiviteten. I denna rapport innebär det att Tobias har skrivit kapitel 2, 4, 5, 8, 10 och Simon har skrivit 3, 5, 6, 7, 9. De andra kapitlerna har skrivits gemensamt. Enhetstesterna för varje del skrevs av den ansvariga och de gemensamma integrationstesterna ansvarade båda för. Ut-veckling skedde i samma projekt med ett versionhanteringssystem där arbetet utfördes i separata branscher som sedan integrerades in i huvudprojektet. Brancherna varade inte mer än en vecka för att, med korta intervall, kunna genomföra integrationstester på den gemensama lösningen.

(14)

1.6 Läsinstruktioner

Kapitel två är en introduktion till Androidplattformen och de komponenter som är viktiga att förstå i en Androidapplikation. Om läsaren inte är in-satt i Android är kapitlet en förutsättning för att förstå resonemangen i de kommande kapitlerna . Kapitel tre till nio berör de problemområden som har identierats i detta inledande kapitel. Var och ett av dessa kapitel inleds med en introducerande text kring problemet. Nästa avsnitt Angreppssätt visar på olika sätt att lösa problemet. I Designval förs utifrån de angreppsätt som har presenterats ett resonemang kring vilket angreppssätt är bäst att välja för att lösa problemet. I det avslutate avsnittet Implementation beskrivs hur lösningen implementerades utifrån de gjorda designvalen.

1.7 Begränsningar

Då implementationen genomförs utan en riktig WEB ökar svårighetsgraden för att uppnå en felfri och robust APP. Det är sannolikt att kraven på funktiona-liteten kommer att ändras då kravställaren får ett nytt och vidare perspektiv i och med integrationen med en riktig WEB.

Förutom att betydande delar av funktionaliteten kan bli lidande och behöva göras om är det också stor risk att felaktiga antaganden gällande prestandan hos en riktig WEB kan få stora konsekvenser för hur APP presterar, i synnerhet med avseende på responsivititet. Trots avsaknanden av en riktig WEB måste appen kunna hantera en skiftande prestanda. Hur responsivitet hanteras be-skrivs i kapitel 9 och i kapitel 11 bebe-skrivs sedan hur responsiviteten verieras genom att emulera en minimal WEB.

(15)

Kapitel 2

Androidplattformen

Operativsystemet Android är en mjukvaruplattform för mobila enheter som har uppstått genom ett samarbete mellan 80 olika teknik- och mobilföre-tag. Samarbetet kallat Open Handset Alliance initierades 2007 och drivs av Google. Android är en open-source-baserad plattform där vem som helst kan bidra med funktionalitet. Androids OS är baserad på Linux 2.6 som tillhan-dahåller kärnfunktionalitet som säkerhet, minneshantering, processhantering, nätverksprotokoll och drivrutinsramverk. I detta kapitel beskrivs Android OS lite närmare och de delar i Androids API som används i utvecklingen av APP. Avsnitten som följer är om inte annat anges baserat på Google's utveck-lingsidor för Android [6] samt boken Android Wireless Application Develop-ment av Lauren Darcey och Shane Conder [7].

2.1 Översikt

Androidapplikationer är skrivna i programmeringsspråket Java. Tillsammans med data- och resursler kompilerar Androids utvecklingsverktyg Java-koden till en exekverbar l med suxet .apk. All kod som nns i en .apk anses vara en applikation och är den l Android-systemet använder för att installera applikationen på enheten.

Efter installation agerar varje applikation i, som det kallas, en egen sand-box:

(16)

• Som standard får varje applikation ett unikt användar-id i Linux vilket är okänt för applikationen. Systemet sätter sedan behörighet så att endast det användare-id:et får tillåtelse att komma åt lerna i applika-tionen.

• Varje applikation har en egen virituell maskin(VM) vilket betyder att all applikationskod körs isolerat ifrån andras applikationer.

• Som standard kör varje applikation sin egen Linux-process. Android startar processen när någon av applikationens komponenter behöver exekveras och stänger processen när den inte längre behövs eller måste ha minnet för andra applikationer.

Genom att låta applikationerna agera i denna sandbox så tillämpar Android OS:et principen: principle of least privilege. Det innebär att varje applikation enbart har tillgång till de komponenter den behöver för att köra sitt program. Detta skapar en säker miljö där applikationer inte kan komma åt delar av systemet som de inte har fått tillgång till. Det går dock att komma åt andra delar av systemet genom att:

• Ha samma id som en annan applikation. Applikationerna ges då tillgång till samma ler och kan köra på samma Linux-tråd samt ha samma VM. • En applikation kan begära tillstånd om att komma åt telefonens kon-taktlista, SMS, SDCard, kamera, Bluetooth med mera. Dessa måste i så fall godkännas av användare vid installation av applikationen.

2.2 Marknadsapplikationens

huvudkomponen-ter

Tre viktiga huvudkomponenter i Android SDK:et används för att bygga upp APP. Nedan beskrivs dessa:

• Activities

En Activity är komponenten som ger användaren en fönsteryta som är integrerbar. Denna används för att visa de olika interkationsvyer som nns, så som att bläddra i en lista av appar, söka efter appar osv.

(17)

• Services

En Service är en komponent som körs i bakgrunden för att kommu-nicera med externa processer eller utföra långvariga operationer. I APP används en Service för att ladda ned apk:er i bakgrunden.

• Broadcast receivers

En broadcast receiver är en komponent som svarar till allmäna med-delanden som sänds ut i systemet, så kallade intents. APP fångar med hjälp av en Broadcast receiver upp meddelanden när en applikation har blivit installerad eller avinstallerad.

2.3 Användargränssnitt

I en Androidapplikation är användargränssnittet byggt av View- och ViewGroup-objekt. Objekten kan vara allt ifrån en textruta till en scrollbar lista. An-vändargränssnittet arrangeras i en hierarki av View- och ViewGroup-objekt. APP kommer att bestå av många olika View- och ViewGroup-objekt. En schematisk bild för hur View och Viewgroups anordnas visas nedan:

Figur 2.1: En hierarki av View- och ViewGroupobjekt [6]

Layouten av View och ViewGroups görs antingen i XML eller kodmässigt i JAVA. Användningen av XML förenklar mycket av designprocessen och föryttar den statiska layouten till att enkelt deneras i XML:en. Dynamiska förändringar görs sedan ifrån JAVA-koden.

(18)

kolumner beroende på vilken orientation som är vald. I exemplet nedan är det två stycken TextViews som placerats i kolumner då orientation är satt till vertical.

<LinearLayout xmlns : android=" http : / / schemas . android . com/apk/ r e s / android "

android : o r i e n t a t i o n=" v e r t i c a l "

android : layout_width=" f i l l _ p a r e n t "

android : layout_height=" f i l l _ p a r e n t "> <TextView android : t e xt="Hej ! "

android : layout_width="wrap_content"

android : layout_height="wrap_content" /> <TextView android : t e xt="Jag är textview 2 . "

android : layout_width="wrap_content"

android : layout_height="wrap_content" /> </LinearLayout>

Listing 2.1: Ett exempel på en layout med LinearLayout och TextView Det går också som tidigare nämnt att implementera layout program-meringsmässigt i JAVA. Detta är dock mer omständligt och svårare att underhålla än XML-lerna och att ett eventuellt samarbete mellan graker och utvecklare försvåras. Följande exempel är precis som föregående exempel men implementerat i JAVA-kod.

p u b l i c void onCreate ( Bundle savedInst anceSt ate ) { super. onCreate ( s avedInstanceSt ate ) ;

TextView text1 = new TextView (t h i s) ; text1 . setText ("HEJ! ") ;

TextView text2 = new TextView (t h i s) ; text2 . setText ("Jag är textview 2 . ") ; text2 . s e t T ex t S i z e ( (f l o a t) 60) ;

LinearLayout l 1 = new LinearLayout (t h i s) ; l 1 . s e t O r i e n t a t i o n ( LinearLayout .VERTICAL) ; l 1 . addView ( text1 ) ;

l 1 . addView ( text2 ) ; setContentView ( l 1 ) ; }

(19)

För att kunna skapa sin layout på era olika sätt används också andra ViewGroup-objekt i APP. Nedan följer en kort beskrivning av andra som används:

• FrameLayout

Används för att placera objekt uppe på varandra. Alla View-objekt ritas högst upp i vänstra hörnet om inte annat speciceras. • RelativeLayout

Gör det möjligt att specicera hur View-objekten förhåller sig till varand-ra. Till exempel kan ett View-objekt positionera sig över, under, till vänster om och så vidare i förhållande till ett annat objekt. View-objekten kan också positionera sig i förhållande till RelativeLayout. • TableLayout

TableLayout organiserar View-objekten i ett tabellmönster. Det är möj-ligt att hoppa över kolumner samt slå ihop dem för att få ett mer anpassat utseende.

2.4 Resurser

I Android används resursreferenser för textsträngar, bilder, ikoner, ljudler, videos och annan data. Dessa används för att att slippa hårdkoda resurser in i källkoden vilket gör den lättare att underhålla. Genom att använda externa resurser blir det lättare att senare kunna anpassa APP beroende på vilken region telefonen är i eller vilken modell den har. Strängar för texten som visas i APP kan till exempel enkelt deneras upp för era olika språk i resurslerna. Resurserna deklareras under mappen res och genom att placera dem i rätt mappstruktur utnyttjas de automatisk av Android. Ett exempel på en textresurs-l strings.xml placerad i res/values kan se ut på följande sätt:

<?xml v e r s i o n=" 1 . 0 " encoding=" utf −8"?> <re s o u r c e s >

<s t r i n g name=" h e l l o ">Hello Android</s t r i n g > <s t r i n g name="app_name">Market</s t r i n g >

<s t r i n g name="button_app_detail_download">Hämta</s t r i n g > <s t r i n g name=" button_app_detail_uninstall ">A v i n s t a l l e r a </

(20)

<s t r i n g name=" button_app_detail_update ">Uppdatera</s t r i n g > <s t r i n g name="button_app_detail_open">Öppna</s t r i n g >

<s t r i n g name=" button_app_detail_download_install ">Ladda ner och i n s t a l l e r a </s t r i n g >

<s t r i n g name=" button_app_detail_share ">Dela</s t r i n g > </r es o u r c e s >

Listing 2.3: Resursl för textsträngar

I exemplet ovan ses resurslen strings.xml som innehåller olika text-strängar för att bland annat sätta texten på nedladdningsknappeb i APP. För att använda en textsträng i resursl så refereras dessa ifrån layoutler. I kommande exempel så har en TextView refererat till en resurs:

<Button android : id="@+id /button_download" android : t ex t=" @string /button_app_detail_download"

android : onClick="onDownload" android : layout_width="wrap_content"

android : layout_height="wrap_content"></Button>

Listing 2.4: Referens till en resurs

I fältet android:text ovan ses referensen sättas till en sträng som heter "button_app_detail_download" genom skrivsättet

"@string/button_app_detail_download".

2.5 Plattformsversioner

För Android existerar åtta olika plattformsversioner för telefoner. För att skapa en väl fungerande applikation APP gäller det att vara medveten om hur de olika plattformsversioner fungerar eller i alla fall de plattformar som ap-plikationen ska inriktas på. En hjälp i att identiera vilken plattformsversion som applikation framförallt ska riktas in på är att titta på distributionen av plattformsversioner. Nedanstående graf, som uppdateras kontinuerligt på developer.android.com, visar fördelningen av plattformsversioner på telefoner den 5 juli 2011.

Ett annat strategiskt val är att försöka välja en så tidig plattformsversion som möjligt då uppdateringar av API:et är designade så att det nya API:et är bakåtkompatibelt med det gamla. Det innebär exempelvis att applikationer

(21)

Figur 2.2: Plattformsfördelningen 5 juli 2011 [6]

inte API:et framåtkompatibelt så att applikationer byggda för Android 3.2 automatiskt fungerar för Android 1.5.

I videon Android Protips [6] visas också tekniken att detektera i koden vilken plattformsversion som smartphonen kör vilket gör att applikationer medvetet kan använda olika delar av API:et beroende på version på smartphonen. Detta gör att era användare kan tillfredställas på bästa sätt. Det kan till exempel se ut på följande sätt:

p r i v a t e s t a t i c boolean APIIsHigherThanHONEYCOMB = android . os . Build .VERSION.SDK_INT >=

android . os . Build .VERSION_CODES.HONEYCOMB; i f(APIisHigherThanHONEYCOMB) {

s t a r t A c t i v i t y = new Int ent (t hi s , highFashionedActivity . c l a s s)

} e l s e {

s t a r t A c t i v i t y = new Int ent (t hi s , oldFashionedActivity . c l a s s)

}

Listing 2.5: Olika Activity:s används beroende på plattformsversion

Koden ovan väljer att starta en Activity som heter highFashionedActivity som är anpassad till de nya API:erna ifall plattformsversionen på

(22)

smartpho-sionen är äldre så startar den en Activity som heter oldFashionedActivity som stödjer tidigare plattformsversioner.

Utveckling av APP har skett mot Android 1.6, detta för att stödja så många versioner som möjligt ifrån start. Android 1.6 valdes till förmån för 1.5 för att den innehöll funktionaliteter som Quick Search Box för sökning bland appar, SMSManager som ska användas för att köpa appar samt andra era viktiga komponenter. För att säkerhetsställa att APP kommer att fungera för 1.5 kommer en framtida betatestning att testa denna version explicit.

2.6 Andra marknadsplatsappar

De existerande marknadsplatser som hittats för Android är Android Market, Amazon Appstore, SlideMe, GetJar och LG SmartWorld. Då Android Market är den ledande produkten bland dessa har ödet för användaren försökt likna Android Market så mycket som möjligt. Detta för att de esta användare är vana vid hur Android Markets öde fungerar. Då all funktionalitet som nns i Android Market inte är möjlig att göra (se avsnitt 6.1.4) har Amazon Appstore fungerat som inspiration då de också saknar de möjligheter som Android Market har.

(23)

Kapitel 3

Kommunikation med WEB

Marknadsplatsapplikationen APP är designad att innehålla minimalt med statiskt innehåll. Data för att fylla startsidan, topplistor, kategorier, app-detaljvyer med mera, hämtas från WEB. Under utvecklingen av APP nns ingen riktig version av WEB, som istället ersätts av MockWEB. Hämtning av data sker med HTTP-protokollets metod GET. För att skicka data, som listor med mina appar används metoden POST. Överföring av känslig och säkerhetskritisk data som användarnamn, lösenord och sessions-id:n bör ske via en säker SSL-anslutning, vilket dock inte innefattas i examensarbetet. Problemen som behöver lösas är att implementera en kommunikation mellan APP och en provisorisk WEB med ofullständig funktionalitet. Sannolikheten är stor att kommunikationen mellan APP och WEB kommer att genomgå bety-dande förändringar, speciellt då APP benner sig i ett tidigt stadium i ut-vecklingen under examensarbetet. Förväntade ändringar i kommunikationen är att byta serialiseringsformat och typen av data som hämtas och skickas. Det bör undvikas att implementationen blir för specik mot den emularede webben, då den även ska vara giltig när den emulerade webben byts ut mot en riktig.

3.1 Angreppsätt

Android SDK:t har två klasser inkluderade för att upprätta en HTTP-anslutning, java.net.HttpURLConnection[2] och

org.apache.http.client.HttpClient[2]. Där Apache's HttpClient är mer rik i funktionalitet med stöd för kakor (eng. Cookies), justering av poolen

(24)

för anslutningar och icke blockerande läsning och skrivning [3]. Svaret från en HttpClient består av ett HttpResponse-objekt som i sin tur kapslar in strömmar för att läsa och skriva data på. HttpClientConnection är enklare uppbyggd och exponerar de underliggande strömmarna direkt utan ett mellanliggande objekt.

Både då data skickas och hämtas från WEB måste ett HTTP-anrop konstrueras och en HTTP-anrop fordrar en url-sträng. Det nns två angreppssätt för att placera ansvaret för konstruering av url-strängen. Samma sak gäller tolkning-en och strömmar erhållna från HTTP-anslutningtolkning-en. Antingtolkning-en distribueras ansvaret ut i alla delar som initerar anrop till WEB, eller så placeras ansvaret i en central modul, som kan bygga url-strängar och tolka data för alla typer av anrop.

3.2 Designval

För att separera kommunikationen med WEB från kärnan av APP ansvarar modulen WebCom för all kommunikation utåt. WebCom-modulen abstraherar bort strömmar för att hämta och skicka data. Då kärnfunktionalitet i APP behöver data från WEB är det WebCom som utför anropet och tolkar svaret, vilket illustreras i gur 3.1. Då serialiseringsformat och kommunikationspro-tokoll ändras, är det endast WebCom som påverkas.

CORE

WEBCOM

WEB

APP

(25)

För att hantera den underliggande HTTP-anslutningen, föll valet på HttpURLConnection, med sin enklare uppbyggnad. Då en riktig WEB sak-nas, anropas en lokal modul som emulerar all funktionalitet i en tänkt WEB, kallad MockWEB. Det är enklare att låta MockWEB returnera strömmar än HttpResponse-objekten som HttpClient arbetar med. Mer om MockWEB i kapitel 11.

3.3 Implementation

WebCom exponerar två huvudklasser Fetcher och Sender som hanterar all hämtning och sändning av data. Metoden fetch(Request) i Fetcher häm-tar data som specieras av Request-objektet, och returnerar ett Response-objekt som innehåller efterfrågad data. Att skicka data sker på liknande sätt, genom att anropa Sender.send(Data). För att bygga url-strängar, serialisera och avserialisera data används klasserna UrlBuilder och Parser (vilken beskrivs närmare i kapitel 4). För att upprätta en anslutning används objekt av typen ConnectionHandler.

3.3.1 Fetcher

I gur 3.2 ses ödet för Fetcher. Fetcher använder klassen UrlBuilder för att bygga en url-sträng att ansluta till för att få tillgång till sökt data. UrlBuilder bygger strängen utifrån Request-objektet som Fetcher.fetch anropades med. Givet url-strängen kan ConnectionHandler anropas för att upprätta en anslutning och returnera en ström i form av en InputStream till sökt data. Fetcher använder sedan klassen Parser för att avserialisera data på strömmen, för att slutligen returnera resultatet.

(26)

WEBCOM Parser

WEB

UrlBuilder Fetcher Connection Handler fetch(Request) Response 0 1 2 3 4 5 6 7 8 9

Figur 3.2: Flödet för att hämta data från WEB med Fetcher. Anropen mellan inblandade delar sker i tur och ordningen där (0) sker först och (9) sist.

3.3.2 Sender

I gur 3.3 ses ödet för Sender. För att skicka data till WEB, anropas UrlBuilder för att returnera en url-sträng, som går till mottagaren. Request-objektet, tillsammans med typen data som skickas, innehåller nödvändig information för att bygga strängen. Utifrån datatypen, serialiseras den av klassen Parser till en java.lang.String. Med url-strängen öppnar ConnectionHandler en ström, i form av en java.io.OutputStream till mottagern på WEB, som serialiserade data kan skrivas till. För att skriva till strömmen används en java.io.PrintWriter.

(27)

WEBCOM Parser

WEB

UriBuilder Connection Handler send(Data) Sender 0 1 2 3 4 5 6

Figur 3.3: Flödet för att skicka data med Sender. Anropen mellan inblandade delar sker i tur och ordningen där (0) sker först och (6) sist.

3.3.3 ConnectionHandler

Klasserna Fetcher och Sender använder båda strömmar för att hämta och skicka data. Dessa strömmar öppnas och skapas av ConnectionHandler med hjälp av en url-sträng från Fetcher och Sender. Domänens namn och sessions-id hanteras av ConnectionHandler och behöver inte sättas vsessions-id varje gång data skickas eller hämtas. Internt använder ConnectionHandler ett objekt av typen java.net.HttpUrlConnection för att ansluta till WEB och öppna strömmarna. Då marknadsplatsapplikationen använder MockWEB som bac-kend, används subklassen MockWEBConnectionHandler. Klassen öppnar en ström till en lokal l på telefonen istället för att göra ett HTTP-anrop. Tanken är att endast MockWEBConnectionHandler behöver bytas ut då WEB ersätter MockWEB.

(28)

Kapitel 4

Serialiseringsformat

Många applikationer i Android kommunicerar med någon slags server. Ap-plikationerna skickar samt hämtar information ifrån dessa. Ofta är kraven på hastighet hög då användaren kräver att en applikation ska ge snabba svar. Hastigheten beror dels på vilken bandbredd som nns, hur snabbt anrop och svar processas samt mängden data som skickas. De två sistnämnda påverkas av serialiseringsformatet. Serialiseringsformatet är formatet på len med in-formation som skickas mellan server och telefon. För olika serialiseringsformat varierar hur kompakt len är samt hur snabbt det går att konstruera och tolka len.

Detta kapitel kommer titta närmare på vilka serialiseringsformat som kan användas för Android, vilka fördelar respektive nackdelar som de har och försöka att identiera ett serialiseringsformat som Marknadsplatsen ska använda för att skicka data.

4.1 Angreppssätt

De format som vi tycker är intressanta när det gäller serialiseringsformat för Android är XML, JSON och Protocol Buers. Detta då Androidplatt-formen stödjer dessa tre format och de är återkommande i forumtrådar som diskuterar utbyte av information. JSON och XML är dessutom de format som i standard stöds av den implementation som kommer att göras på WEB. Serialiseringsformaten beskrivs utförligare i de kommande avsnitten och avslutas med en jämförelse av hastighet. I och med att WEB saknas vid

(29)

implementationen av APP kommer det också vägas in hur enkelt det är att manuellt konstruera lerna för de olika serialiseringsformaten.

4.1.1 XML

XML är ett taggbaserat språk (Markup Language) i textformat. Grunden för ett XML-dokument är dess element som skapas med hjälp av taggar. Ett element har en starttagg och en sluttagg och kan ha olika innehåll samt attribut. Utöver elementen nns en XML-deklaration som beskriver vilken version XML-dokumentet har samt andra attribut som kan vara av intresse. En XML-l över en adresskontakt kan se ut så här:

<?xml v e r s i o n=" 1 . 0 " encoding=" iso −8859−1"?> <contact> <firstName>John</firstName> <lastName>John</lastName> <age >25</age> <address>

<streetAddress >21 2nd Street </streetAddress > <city >New York</city >

<state >NY</state > <postalCode >10021</postalCode> </address> <phoneNumber> <type>home</type> <number>212 555−1234</number> </phoneNumber> <phoneNumber> <type>fax </type> <number>646 555−4567</number> </phoneNumber> <newSubscription>f a l s e</newSubscription> <companyName>null</companyName>

</contact>

Listing 4.1: Exempel på en XML-l

Fördelen med XML är att det är väldigt enkelt att skriva och läsa för en människa. Det är därför enkelt att skapa och börja skicka ler. Nackdelen är att det innehåller överödig information i form av avslutningstaggar som egentligen inte fyller någon funktion och därmed får en stor lstorlek.

(30)

4.1.2 JSON

JSON, Java Script Object Notation, är ett kompakt textformat för att skicka data. JSON är ett textformat som är helt språkoberoende men använder konventioner som liknar de i C och C++. JSON är uppbyggt av två kon-struktioner: en samling av namn/värde-par och en ordnad lista av värden. JSON serialiserar/avserialiserar sina ler likt XML men användningen av namn/värde-par sparar bytes i den slutgiltiga len. Nedan ses samma infor-mation som i föregående XML-l men i JSON-format:

{ " firstName ": "John", "lastName": "Smith", " age ": 25 , " address ": { " s t r e e t A d d r e s s ": "21 2nd S t r e e t ", " c i t y ": "New York", " s t a t e ": "NY", " postalCode ": " 10021 " } , "phoneNumber": [

{ " type ": "home", "number": "212 555−1234" } , { " type ": " fax ", "number": "646 555−4567" } ] ,

" newSubscription ": f a l s e ,

"companyName": n u l l }

Listing 4.2: Exempel på en JSON-l

JSON har fördelen att det är mer kompakt än vad XML är då det saknar sluttaggar samt version. Nackdelarna är att det är lite mer svårläst än vad XML.

4.1.3 Protocol Buers

Istället för att använda textformat som serialiseringsformat går det att an-vända binära format för att utbyta information. De binära formaten är ej läsbara i sin rena form utan består av tecken som är otydbara för en (vanlig) människa.

Det binära format som är standard för Androidplattformen är Protocol Buf-fers, även kallat Protobuf. Protobuf är utvecklat av Google som ett mer eektivt alternativ till XML och har stöd för många programmeringsspråk,

(31)

inklusive JAVA.

För att använda Protobuf specicerar utvecklaren en meddelandetyp i en .proto-l. Protobuf kompilerar sedan .proto-len som generear dataklasser som tillhandahåller serialisering/avserialisering av objekt till en buer/ström av bytes.

En .proto-l kan se ut på följande sätt:

package t u t o r i a l ;

option java_package = "com . example . t u t o r i a l "; option java_outer_classname = " AddressBookProtos "; message Person { r e q u i r e d s t r i n g firstName = 1 ; r e q u i r e d s t r i n g lastName = 2 ; r e q u i r e d in t 32 age = 3 ; message Address { r e q u i r e d s t r i n g s t r e e t A d d r e s s = 1 ; r e q u i r e d s t r i n g c i t y = 2 ; r e q u i r e d s t r i n g s t a t e = 3 ; r e q u i r e d s t r i n g postalCode = 4 ; } message PhoneNumber { r e q u i r e d s t r i n g home_number = 1 ; r e q u i r e d s t r i n g fax_number = 2 ; }

repeated Address address = 4 ;

repeated PhoneNumber phoneNumber = 5 ; r e q u i r e d boolean newSubscription = 6 ; o p t i o n a l s t r i n g company = 7 ;

}

message AddressBook {

repeated Person person = 1 ; }

Listing 4.3: Exempel på en .proto-l

Ifrån denna l skapas klasser i Java, eller till vilket språk som föredras, för att serialisera objekt till en ström av bytes eller avserialisera en ström av

(32)

Fördelen med Protocol Buers är att det är ett mycket kompakt format, l-storleken är betydligt mindre än för textformaten JSON och XML. Nackdelen är att det inte direkt går att utläsa ifrån en Protobuf-l vad information är då det är i binärt format.

4.1.4 Jämförelse av hastighet

Följande avsnitt syftar till att undersöka hastigheten mellan olika serialise-ringsformat, framförallt skillnaden mellan binära- och läsbara textformat. I en undersökning gjord av Christian Esposito, Domenico Cotroneo och Stefano Russo [8] jämförs hastigheten för olika serialiseringsformat. För att jämföra hastigheten tittade författarna på tre stycken områden:

1. Serialiseringstid - tiden det tar för parsern att konvertera objekt till en ström av bytes.

2. Avserialiseringtid - tiden det tar för parsern att konvertera strömmen av bytes till objekt.

3. Sändningstid - tiden det tar att sända meddelandet ifrån sändare till mottagare.

Applikation Parser RTI-PUB RTI-SUB Applikation

transmit transmit stream stream stream stream message message serialization copy desiralization T1 T2 T3 Node A Node B

(33)

I undersökningen jämförs bland annat JSON, XML och CDR. CDR är precis som Protobuf ett binärt format och de kan därför anses vara jämförba-ra. Resultaten i tabellen i gur 4.2 visar att det binära formatet CDR är överlägset snabbast när det gäller serialisering (konstruering), deserialisering (tolkning) och sändning. Till exempel i resultaten för sändning (gur 4.2, graf D) ses att CDR tar 3 443 mikrosekunder medan bästa resultatet för textformaten är hela 12 341 mikrosekunder, vilket är nästan 4 gånger så långsamt. Tendensarna återkommer i serialisering och deserialisering där textformaten återigen är ungefär 4 gånger så långsamma som det binära formatet CDR.

Utifrån Espositos undersökning kan man dra slutsatsen att binära format är betydligt snabbare än textformat.

0 2000 4000 6000 8000 10000 12000 14000 16000 0 2000 4000 6000 8000 10000 12000 14000 16000 3443 12341 15143 15322 15057 12195

CDM JSON DOM_XMLSAX_XML YAML_block YAML_flow

CDM JSON SAX_XML YAML_block YAML_flow CDM JSON SAX_XML YAML_block YAML_flow

CDM SAX_XML YAML Compact

YAML 3443 12341 15143 15322 15057 12195 370 14470 51860 26100 23230 24380 1 0,0675 0,0678 0,114 0,073 0,105

Serialization format Serialization format

Serialization format Serialization format

Delivery Time(microsec) Dissemination Time(microsec) Deserialization Time(microsec) Efficiency (seze_stream/size_content) 0 10000 20000 30000 40000 50000 60000 0 0,2 0,4 0,6 0,8 1 1,2 DOM_XML DOM_XML DOM_XML JSON (A) (B) (C) (D)

Figur 4.2: Resultat: (A) Serialiseringseektivitet, (B) Serialiseringstid, (C) Deserialiseringstid och (D) Sändningstid [8]

(34)

4.2 Designval

Enligt de jämförelser av Esposito mellan text- och binärformat är det tydligt att det binära formatet är det snabbaste. Trots detta kommer APP initialt implementeras med ett textformat istället för ett binärt format som Protobuf. Detta på grund av att APP än så länge saknar kommunikation med WEB och behöver simulera denna kommunikation genom en emulerad WEB, MockWeb. För att enkelt kunna skapa en MockWEB är ett textformat att föredra då lerna enkelt kan skrivas i klartext i en textediterare och returneras när förfrågningar görs mot MockWEB. Felsökningen av dessa ler blir också betydligt enklare än ler av binära format.

I valet mellan JSON och XML väljs XML då det är något enklare att läsa i klartext än JSON vilket anses viktigt i en prototypfas.

4.3 Implementation

XML-lerna kommer att skapas i en textediterare och läsas in av APP under körning. XML-lerna parsas med hjälp av biblioteket android.util.XML till data-objekt som kan hanteras av övrig funktionalitet i APP.

Beroende på vilken typ av data som hämtas så används olika XMLParsers. Figur 4.3 visar de olika XML-parsers som implementerats. AppListXMLPar-ser parsar en applista, AppDetailXMLParAppListXMLPar-ser parsar en detaljvy av en app, ListOfCategoriesXMLParser parsar kategorilistan och TileXMLParser parsar de olika elementen på startsidan.

(35)

Parser Response<App> parseAppList(InputStream) Response<AppDetail> parsAppDetail(InputStream) Response<Category> parseListOfCategories(InputStream) Response<Tile> parseTiles(InputStream) AppList XMLParser Response<App> parse(InputStream) AppDetail XMLParser Response<AppDetail> parse(InputStream) ListOfCategories XMLParser Response<Category> parse(InputStream) Tile XMLParser Response<Tile> parse(InputStream)

(36)

Kapitel 5

Fylla och visa applista

Att visa en lista med information är en av de mest använda funktionaliteterna i Android. Listan över kontakter, sms eller samtal är bara några av de funktionerna i Android som visar en lista. Då listorna kan innehålla tusentals poster är det av stor vikt att de är så eektiva som möjligt. För att rendera listor används, i nästan alla fall, klassen ListView som kan kongureras på många olika sätt.

I detta kapitel beskrivs olika sätt att kongurera en listvy i Android och vilka tekniker som är lämpliga att använda för att få en så snabb lista som möjligt. Exemplen kommer att utgå ifrån en applista som tänks bestå av ett godtyckligt antal appobjekt. Varje appobjekt har en titel, ett företagsnamn, ett pris, ett betyg och en appikon.

(37)

5.1 Angreppssätt

För att fylla en ListView med data så används en Adapter. Adaptern fun-gerar som en länk mellan datakällan och objektet ListView och ser till så att accessen av information för ListView är så snabb som möjligt. I gur 5.2 nedan ses en schematisk bild över hur kopplingen mellan datakälla, adapter och ListView ser ut.

Adapter

Datakälla Item id, attr_0, attr_1, ...

...

Figur 5.2: Kopplingen mellan ListView, adapter och data

I de kommande avsnitten beskrivs olika adapters och vilka tekniker som kan användas för att göra renderingen av en lista så snabb som möjligt.

5.1.1 Adapters

En Adapter fungerar som länken mellan en datakälla och en ListView och returnerar en View fylld med information till ListView-objektet som renderar upp det på skärmen. Det nns olika typer av Adapter-objekt där de vanligaste är CursorAdapter och ArrayAdapter. CursorAdapter används bäst för att hämta data ifrån en databas medan ArrayAdapter är bäst att använda för att hämta data ifrån en resursarray som har laddats in i RAM-minnet. När informationen är hämtad och laddad i Adaptern binds Adaptern till en ListView genom följande kommando:

(38)

5.1.1.1 Använda ArrayAdapter

En ArrayAdapter binder varje element av en array till ett enda View-objekt. Nedan följer ett exempel på på hur en ArrayAdapter initieras:

p r i v a t e S t r i n g [ ] items = {" apple "," orange ","tomato"} ;

ArrayAdapter adapt = new ArrayAdapter<String >(t hi s , R. layout . textview , items ) ;

Listing 5.1: Arrayadapter

I exemplet ovan nns en array av strängar kallad items som används av ArrayAdaptern som dess datakälla. Till ArrayAdaptern binds också en layoutresurs, R.layout.textview, som är den View som fylls för varje element i items. I gur 5.3 ses resultatet av ovanstående kod. Fördelen med en

Figur 5.3: En ListView med en ArrayAdapter

ArrayAdapter är att den är väldigt enkel att använda då det krävs väldigt få rader kod för att generera en lista. Nackdelen är att den enbart kan visa en View på varje rad.

5.1.1.2 Använda CursorAdapter

En CursorAdapter kan binda en eller era kolumner av data till en el-ler era Views och är på så sätt lite mer dynamisk än en ArrayAdapter. CursorAdapter kräver användandet av en Cursor som är en länk till re-sultatet ifrån en databas-fråga [2]. Följande exempel visar skapandet av en CursorAdapter genom att fråga telefonkontakternas content provider:

(39)

Cursor names = managedQuery (

Contacts . Phones .CONTENT_URI, null , null , null , n u l l) ; startManagingCursor ( names ) ;

ListAdapter adapter = new SimpleCursorAdapter ( t h i s , R. layout . two\_text ,

names , new S t r i n g [ ] {

Contacts . Phones .NAME, Comtacts . Phones .NUMBER } , new i n t [ ] {

R. id . s c r a t c h \_text1 , R. id . s c r a t c h \ _text2 }) ;

Listing 5.2: CursorAdapter

I exemplet ovan används managedQuery() för att få en Cursor till te-lefonkontakterna. SimpleCursorAdaptern ges en layoutresurs som innehåller två stycken TextViews som fylls med Cursor:n names enligt de två sista parametrarna. Fördelen med en CursorAdapter är att det går att ha era View:s på samma rad. Nackdelen är att det är tvunget att använda en Cursor för att fylla adaptern med data.

5.1.1.3 Anpassa en ArrayAdapter

För att kunna använda era Views i en ArrayAdapter och uppnå den funk-tionalitet som nns i en CursorAdapter kan en subklass av en ArrayAdapter skapas. ArrayAdaptern begränsas då inte till ett View-objekt utan det går att denera vilka View-objekt som ska fyllas med information. I ArrayAdaptern nns metoden getView() som är metoden som fyller de View-objekt som existerar på en app-rad. När en ListView initieras eller då en rad åter scrollas in i bild anropas getView()-metoden och returnerar en View för hela raden till ListView-obejktet. Genom att överskugga metoden getView() kan layouten anpassas efter egna önskemål.

För att eektivisera ArrayAdaptern används två tekniker för att snabba upp renderingen av View-objekten [10]:

• Återanvändning av convertView som skickas som inargument i getVi-ew(). convertView innehåller en cachning av View-objekt ifrån en rad om den har visats tidigare.

(40)

• Användning av ViewHolder-pattern för att undvika att använda nd-ViewById på alla Views på en rad när det inte är nödvändigt.

I följande kodsnutt från developer.android.com med översatta kommentarer visas dessa tekniker för att eektivisera getView().

p u b l i c View getView (i n t p o s i t i o n , View convertView , ViewGroup parent ) {

// ViewHolder h å l l e r en r e f e r e n s t i l l a l l a Views på en rad f ö r a t t undvika a t t

// findViewById ( ) anropas på v a r j e rad .

ViewHolder holder ;

// När convertView är s k i l j t i f r å n n u l l går det a t t återanvända och det

// behöver i n t e i n i t i e r a s igen .

i f ( convertView == n u l l) {

convertView = m I n f l a t e r . i n f l a t e (R. layout . list_item_icon_text , n u l l) ;

// Skapar en ViewHolder och sparar r e f e r e n s e r t i l l de Views som l i g g e r

// på raden .

holder = new ViewHolder ( ) ;

holder . t e xt = ( TextView ) convertView . findViewById (R. id . t e xt ) ;

holder . icon = ( ImageView ) convertView . findViewById (R. id . icon ) ;

convertView . setTag ( holder ) ; } e l s e {

// Hämtar ViewHolder som temporärt har s p a r a t s i Tag : en på View : en .

holder = ( ViewHolder ) convertView . getTag ( ) ; }

// S ä t t e r t ex t på TextView : en i f r å n datakällan

holder . t ext . setText (DATA[ p o s i t i o n ] ) ;

// Hämtar en b i l d i k o n i f r å n en URL och s ä t t e r på ImageView : en

bitmap = BitmapFactory . decodeStream ( getInputStream ( mIcon1URL) ) ;

(41)

} s t a t i c c l a s s ViewHolder { TextView t ex t ; ImageView icon ; } }

Listing 5.3: Eektivisering i getView() 5.1.1.4 Header i applistan

I vissa lägen behövs ett rubrikelement i applistan som till exempel förklarar vad det är för typ av lista som visas. För ListView-objektet nns meto-den addHeaderView(View) som sätter en godtycklig View till rubrikelement. ListView-objektet kapslar då in sin egen adapter i en HeaderViewListAdap-ter som har funktionaliteten att sätta ett rubrikelement [9].

Nackdelen med denna metod är att det inte går att komma åt referensen till rubrikelementet efter det är satt då detta element har kapslats in i HeaderVi-ewListAdaptern. Detta gör att en referens till rubrikelementet måste hållas i minnet ifall rubriken ska förändras i efterhand.

5.1.2 Cachning av bildikoner

Adaptern ritar om varje rad i listan så fort den blir synlig för användaren. Det gör att bilder hämtas för varje gång som en rad ritas om. Här följer ett utsnitt ifrån getView() som visar denna hämtning vid varje laddning av getView().

p u b l i c View getView (i n t p o s i t i o n , View convertView , ViewGroup parent ) {

. . . .

// Hämtar en b i l d i k o n i f r å n en URL och s ä t t e r på ImageView : en

bitmap = BitmapFactory . decodeStream ( getInputStream ( mIcon1URL) ) ;

holder . icon . setImageBitmap ( bitmap ) ; return convertView ;

}

(42)

För att undvika att hämta bilder vid varje omritning är det lämpligt att cacha bilderna efter första nedladdningen. Vid varje omritning laddas då istället bilden ifrån cachen. Cachningen kan sparas i arbetsminnet el-ler i en Content Provider. Om cachnigen görs i arbetsminnet försvinner cachningen när applikationen stängs av, sparas det däremot i en Content Provider existerar cachningen även efter applikationen har stängts av. Den uppenbara fördelen med att lägga cachen i en Content Provider är att alla bilder inte hämtas igen vid omstart av applikation utan det är bara de nya och förändrade bilderna som behöver laddas ned. Svårigheterna är dock att skapa ett bra sätt för att se vilka som är nya och behöver uppdateras.

5.1.3 Proxy för bildikoner

Den mest tidskrävande operationen när information hämtas till applistan är hämtningen av bildikonerna då dessa är avsevärt större än texten som hämtas. För att hantera objekt som relativt är mer tidskrävande än andra är The Proxy Pattern lämpligt att använda [11, p. 460]. The Proxy Pattern använder sig av ett proxyobjekt som är en förenklad variant av det riktiga objektet som ska användas. Proxyobjektet håller en referens till det riktiga objektet och hanterar access till det. Det riktiga objektet kan då t.ex. utföra tunga operationer så som att vid behov hämta ett bildobjekt i bakgrunden.

(43)

5.2 Designval

För att visa en lista av appar är det lämpligast att skapa en egen anpassad ArrayAdapter då raderna i ListView:en för en applista inte enbart består av en TextView. Datakällan kommer inte att bestå av en lokal databas utan laddas ifrån WEB och sparas temporärt i RAM-minnet vilket gör att en CursorAdapter inte är aktuell. För att göra applistan snabbare cachas bildikonerna. Detta görs dock enbart i arbetsminnet vilket gör att cachningen kommer att försvinna när applikationen stängs ned. Att spara cachningen i en Content Provider anses i första versionen av APP vara överödigt och ökar komplexiteten då en implementation av en Content provider måste göras. Användningen av proxy gör användaren kan interagera med applistan snab-bare, dock är detta något som inte kommer att implementeras då applistan fungerar tillfredställande snabbt utan proxy. En funktionalitet med proxy anses höra till optimeringen av APP.

För att skapa ett rubrikelement till applistan är det bättre att implementera det själv i en egen Adapter än att addera den till ListView-objektet genom metoden addHeaderView(). Detta på grund av att rubrikelementet inte är åt-komligt efter det har adderats till ListView:en samt att ListView:ens adapter blir inkapslad i en HeaderViewListAdapter och däremed inte kan refereras. Genom att implementera det i den egna adapter kapslas inte adapterobjekt in i varandra vilket är ett slöseri på resurser.

5.3 Implementation

För att fylla en lista av appar i en ListView skapas en egen ArrayAdapter, kallad AppListAdapter. Som argument till konstruktorn används datakäl-lan Response<App> som ärver ifrån ArrayList<App> och innehåller med-lemsvariabeln description för att kunna visa en beskrivning högst uppe i applistan. I gur 5.5 ses kopplingen mellan de olika objekten i APP:en.

(44)

I AppListAdapter, överskuggas metoden getView() för att fylla de Views som skapats för att visa ett app-objekts rad. Här används de två tekniker med Viewholder-pattern och återanvändning av convertView som beskrevs i avsnitt 5.1.1.3. Koden ser ut på följande sätt:

p u b l i c c l a s s AppListAdapter extends ArrayAdapter<App> { . . .

p u b l i c View getView (i n t p o s i t i o n , View convertView , ViewGroup parent ) {

. . .

ViewHolder holder ;

i f ( convertView == n u l l) {

convertView = m I n f l a t e r . i n f l a t e (R. layout . app_list , n u l l) ;

//Här hämtas Views : en som ska f y l l a s f ö r app−raden .

holder = new ViewHolder ( ) ;

holder . t i t l e = ( TextView ) v . findViewById (R. id . t i t l e ) ;

convertView . setTag ( holder ) ; } e l s e {

holder = ( ViewHolder ) convertView . getTag ( ) ; }

. . .

// S ä t t e r t e xt på TextView : en i f r å n datakällan

holder . t i t l e . setText ( apps . get ( p o s i t i o n ) ) ; . . .

// Hämtar en b i l d i k o n i f r å n en URL och s ä t t e r på ImageView : en

bitmap = BitmapFactory . decodeStream ( getInputStream ( mIcon1URL) ) ;

holder . icon . setImageBitmap ( bitmap ) ; . . . .

} }

Listing 5.5: Implementationen av getView()

I app-objektets rad ingår en bildikon. Istället för att hämta ny bildikon varje gång kan en cache användas. Bildikonen hämtas då en gång, lagras lokalt och hämtas ifrån den lokala lagringen nästa gång den ska laddas. Nedan visas implementationen med en HashMap för att lagra de redan nedladdade

(45)

p u b l i c c l a s s AppListAdapter extends ArrayAdapter<App> { p r i v a t e HashMap<String , Bitmap> cache = new HashMap<

String , Bitmap >() ; . . .

p u b l i c View getView (i n t p o s i t i o n , View convertView , ViewGroup parent ) {

. . .

// Kollar i f a l l b i l d i k o n e n redan har laddats ner och e x i s t e r a r i cachen

i f( cache . containsKey ( u r l ) ) {

imageView . setImageBitmap ( cache . get ( u r l ) ) ; } e l s e {

// Getting the icon from an e x t e r n a l s t o r a g e

bitmap = BitmapFactory . decodeStream ( getInputStream ( mIcon1URL) ) ;

holder . icon . setImageBitmap ( bitmap ) ;

// Lägger t i l l den nedladdade b i l d i k o n e n i cachen .

cache . put (mIcon1URL , bitmap ) ; }

. . . } }

Listing 5.6: Implementation av cachning för bildikoner

För att sätta rubrikelementet i applistan behöver metoden getView() förändras. I getView() ges argumentet position som säger vilken position i listan som getView() är på väg att fylla. Om positionen är 0 och om datakällan har en beskrivning kan den sättas.

p u b l i c View getView (i n t p o s i t i o n , View convertView , ViewGroup parent ) {

// Header − Om p o s i t i o n på l i s t a n är 0 och datakällan har en b e s k r i v n i n g

i f( items . h a s D es c rip t io n ( ) && 0 == p o s i t i o n ) { v = m I n f l a t e r . i n f l a t e (R. layout . header , n u l l)

;

( ( TextView ) v . findViewById (R. id . header \_text ) ) . setText ( items . g e t D e s c r i p t i o n ( ) ) ;

} e l s e {

i f ( convertView == n u l l) { . . . .

(46)

. . .

return convertView ; }

}

Listing 5.7: Implementation av rubrikelementet i ListView

Det gäller att vara uppmärksam på att heltalet position kommer att peka på fel position i datakällan när det nns en beskrivning. Position behöver sub-traheras med ett för att återge korrekt element ifrån datakällan. Metoderna getCount(), getItem(), getItemId() och getItemViewType() överskuggas för att uppnå detta:

@Override

p u b l i c App getItem (i n t p o s i t i o n ) {

i f( items . h a s D es c rip t io n ( ) && 0 == p o s i t i o n ) {

// Someone c l i c k e d the header .

return n u l l;

} e l s e i f( items . h a s D es c rip t io n ( ) ) { p o s i t i o n −= 1 ;

}

return super. getItem ( p o s i t i o n ) ; } @Override p u b l i c long getItemId (i n t p o s i t i o n ) { i f( items . h as D es c rip t io n ( ) ) { p o s i t i o n −= 1 ; }

return super. getItemId ( p o s i t i o n ) ; } @Override p u b l i c i n t getItemViewType (i n t p o s i t i o n ) { i f( items . h as D es c rip t io n ( ) ) { p o s i t i o n −= 1 ; }

return super. getItemViewType ( p o s i t i o n ) ; }

(47)

Kapitel 6

Ladda ner och installera appar

I föregående kapitel beskrevs hur en lista med appar visades för användaren. Nästa steg är att ladda ner och installera en app på telefonen. I Android innesluts en installerbar app i en l av typen .apk som påminner om Javas .jar-ler. Apk-len innehåller allt appen behöver, som körbara dex-lerna och resurser som bilder och layout.

6.1 Angreppssätt

I följande kapitel undersöks två angreppssätt för att ladda ner apk-ler och två för att installera apk-ler på telefonen. Angreppssätten för att ladda ner en apk är att antingen överlåta nedladdningen till plattformens standard-webbläsare, eller att sköta nedladdning inne i APP.

De två angreppssätten som har undersökts för installation av en apk är att antingen överlåta installationsprocessen till androidplattformens standard-program för installation, eller att sköta installationen inne i APP.

6.1.1 Nedladdning med standardwebbläsaren

Givet att adressen till en apk-l är känd, är det möjligt att ladda ner den genom att starta en webbläsare på telefonen och skriva in adressen i webb-läsarens sökfält. Beteendet för standardwebbläsaren, då en länk till en apk besöks, är att ladda ner len till telefonen och visa nedladdningsstatus.

(48)

Detta angreppssätt innebär att hela nedladdningsproceduren hanteras av webbläsaren, inklusive protokoll och felfall rörande strömmar. En fördel är att det är väldigt enkelt att implementera. Givet en url till apk-len, kan en nedladdning initieras enligt kodexemplet nedan.

Inten t i n t e n t = new Intent (" android . i n t e n t . a c t i o n .VIEW", Uri . parse (" http :/ /

a d r e s s . se /app . apk") s t a r t A c t i v i t y ( i n t e n t ) ;

Nackdelen med detta angreppssätt är avsaknaden av kontroll över webb-läsarens beteende. Även om den fungerar bra i nuläget (med WebKit version 7), är det möjligt att beteendet är annorlunda i framtida versioner och för andra webbläsare. När apk-len har blivit nedladdad av webbläsaren kan användaren starta installationen. I detta fall nns inget enkelt sätt att starta installationen automatiskt från APP, då den inte får någon information om att apk-len har blivit nedladdad och vilken lokal plats den blev lagrad på. Ytterligare en nackdel med detta angreppssätt är att användaren får utstå en omständig nedladdningsprocess och användaren behöver medverka vid initiering av installationen för apk:n.

Figur 6.1: Användargränssnittet då standardwebbläsaren används för ned-laddning av apk-ler

6.1.2 Nedladdning inne i appen

Det är möjligt att öppna en anslutning inne i APP mot apk-len om adressen är känd. Genom anslutningen kan en javaström till len öppnas. Strömmen

(49)

Fördelen med detta angreppssätt är att APP får full kontroll över nedladd-ningsprocessen. Den hämtade apk-len kan även sparas på en godtycklig plats på telefonen. Tack vare att len laddas byte för byte från strömmen, känner APP till hur många procent av len som är nedladdad, och kan visas denna information för användaren inne i APP. Då antalet nedladdade byte är kända, kan APP återuppta en anslutnigen om den skulle avbrytas i förtid. APP har även möjlighet att rensa bort nedladdad data, då platsen är känd.

Figur 6.2: Då nedladdningen sköts inne i APP, minskar antalet interaktions-steg för användaren

Nackdelen med att låta APP ladda ner en apk, är att felhanteringen kring att läsa och skriva från strömmar behöver implementeras. Om något går fel måste rätt åtgärd tas, som att ladda ner apk-len på nytt och rensa bort den gamla halvfärdiga len. Apk-len måste även lagras på telefonen innan installationen kan genomföras. Då måste fel orskade av access till sd-kortet, hanteras på ett korrekt sätt.

6.1.3 Standard android install

Androidplattformen har ett inbyggt program för att installera apk:er. Den startas exempelvis då användaren klickar på en apk-l i nedladdningslistan, eller i lutforskaren. Proceduren består av tre vyer, som ses i gur 6.3. Det första fönstret visar de privilegier applikationen i fråga kräver. Användaren kan välja mellan att installera eller avbryta (och då lämna installationen). Andra fönstret visar installationsförloppet, och ingen interaktion är möjlig. Det tredje och sista fönstret talar om att installationen har lyckats (eller

(50)

inte) och låter användaren antingen öppna den installerade applikationen eller stänga fönstret.

Figur 6.3: Användargränssnittet då Androids standardprogram för installa-tion används

Det nns era nackdelar med att använda androids standardinstallations-program. APP har ingen kontroll över ifall installationen kommer att lyckas eller inte, det är upp till användaren att godkänna stegen i installatationen. Utifrån användarens perspektiv är stegen onödiga, då beslut om att installera appen redan är taget. En till nackdel är att era samtidiga nedladdningar resulterar i att installationsrutorna läggs på varandra, vilket kan ge en rörig användarupplevelse.

Fördelen med att använda standardinstallationsprogramet är att den kan signalera trygghet. Då installationsprogrammet är en del av androidplattfor-men kan APP kännas som en integrerad del av telefonen. Om standardinstal-lationsprogrammet används är det möjligt att behovet av underhåll minskar, då det sköts av utvecklingsteamet för androidplattformen.

6.1.4 Installation inne i APP

Androids standardprogram för installation, som beskrevs i föregående av-snitt, använder sig av anrop till plattformen för att utföra själva installa-tionen. Klassen som används är PackageManger som exponerar metoden installPackage. Om APP utnyttjar denna metod behöver inte standardin-stallationsprogrammet startas, och användaren skulle kunna slippa att gå igenom överödiga installationssteg. Hela kedjan från nedladdning och

(51)

in-stallation skulle då kunna utföras med endast ett knapptryck, eller väldigt få, som i Android Market, se gur 6.4.

Figur 6.4: I Android Market installeras en apk med endast ett klick Problemet med detta angreppssätt är att metoden installPackage har gjorts oåtkomlig från och med Androidplattformsversion 4 [4]. Metoden har inte blivit borttagen, utan nns fortfararande kvar som dold metod och kan användas av Googles applikationer (eng. native applications). På detta sätt kan applikationer som Android Market kapsla in installationsprocessen. Då metoden endast är dold, skulle ett möjligt angreppssätt vara att anropa den med Java-Reections. Paketet java.lang.Reflect innehåller funktiona-litet för att erhålla information klasser och objekt, som exempelvis metoder. Ett objekt av typen java.lang.reflect.Method kan referera till metoden PackageManager.installPackage som används för att installera en apk-l. Givet adressen till en apk-l kan ett anrop göras enligt kodexemplet nedan.

java . lang . r e f l e c t . Method [ ] methods =

PackageManager .c l a s s. getDeclaredMethods ( ) ; F i l e f i l e = new F i l e ( ("/ sdcard / angrybirds . apk") ) ; Uri f i l e U r i = Uri . fromFile ( f i l e ) ;

f o r ( Method method : methods ) {

i f( method . getName ( ) . equals (" i n s t a l l P a c k a g e ") ) { method . invoke (

getPackageManager ( ) , f i l e U r i , t h is , 0 , "com . r o v i o . angrybirds ") ;

} }

(52)

tredjepartsprogram. Anledningen till att Google inte delar ut privilegiet beror på säkerhetsskäl, som uttryckt på android developer forum, ../ parts of the API may be modied or removed, although typically such changes are only needed to ensure API robustness and application or system security. [12] Fördelen med att kapsla in installationen i APP, är att nedladdning- och installationsprocessen förenklas för användaren. Nedladdning och installation skulle även kunna initeras och utföras från WEB utan att användaren behöver godkänna det inne i APP (som är möjligt med Android Market). Nackdelen är att det krävs speciell tillåtelse av Google för att utföra inkapslad och osynlig installation.

6.2 Designval

Kombinationer av angreppssätt resulterar i fyra möjliga lösningar, illustrera-de i gur 6.5. Komplexitetsnivån för implementation sträcker sig från längst ner till vänster där GetJar nns, till längst upp till höger där Android Market är ensamma med sin inkapslade installation.

Installation inne i APP Standardprogram för installation Nedladdning med webbläsaren Nedladdning inne i APP Android Market

-GetJar Amazon Appstore

Figur 6.5: Fyra möjliga lösningar utifrån angreppsätten

I valet mellan att använda standardwebbläsaren för nedladdning eller att ladda ner apk-ler inne i APP, faller valet på det sistnämnda alternativet. Om webbläsaren skulle sköta nedladdning, tappar APP för mycket kontroll över nedladdningsprocessen. Användarupplevelsen kan även göras mer strömlin-jeformad och enhetlig om nedladdning sköts inne i APP.

I valet mellan att nyttja Androids standardsprogram för installation eller att kapsla in installationen inne i APP, faller valet på standardprogrammet. Att

References

Related documents

Inom den sociokulturella läran är det viktigt att ha möjlighet till samspel, interaktion under inlärning, olika aktiviteter och en variation av verktyg som hjälp i undervisningen

Detta indikerar att konsumtionen av välfärdstjänster var högre för hushåll med lägre disponibla inkomster samt hushåll som hade behov av hälso- och sjukvård samt socialt

Android compares the information in an Intent object with the intent filter exposed by every application and finds the activity most appropriate to handle the data or action

It is normal and recommended Android practice to create your user interface in XML using the layout file created under res/layout , but it is certainly possible to write all the

Following example shows you how to define a simple Android custom component and then how to instantiate it inside activity code without using layout file.. 1 You

From a simple SharedPreferences mechanism to file storage, databases, and finally the concept of a ContentProvider, Android provides myriad ways for applications to retrieve

Make the Call Once you have your intent, you need to pass it to Android and get the child activity to launch.. You have

Dalvik [uses a] 16-bit instruction set that works directly on local variables. The local variable is commonly picked by a 4- bit 'virtual