Undervejs i udviklingen af min app har jeg brugt nogle forskellige eksterne pakker til at tage vare på forskellige opgaver. Her vil jeg kort beskrive Volley som bruges til at oprette requests, og som fanger responses.

Volley opsætning / permissions

I AndroidManifest.xml skal man tilføje nogle tilladelser som hedder:

  • android.permission.INTERNET
  • android.permission.ACCESS_NETWORK_STATE

Det skal se nogenlunde sådan her ud:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="dk.enmango.ordsomegram">
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

    <application ... >

Som bonus kan jeg fortælle at jeg også brugte propertyen usesCleartextTraffic sat til true, ellers kunne jeg ikke tilgå websiden med http-protokollen. Vær varsom for du deaktiverer egentlig noget sikkerhed her. Men så længe jeg udvikler lokalt og debugger bør det være ok.

    <application
            android:usesCleartextTraffic="true"
            ... >     

Lidt om permissions på android

På Android kan man ikke bare tilgå forskellige ting på systemet uden at have permission. Man skal fortælle systemet hvilken ressource man vil have adgang til, og alt efter ressourcen kan systemet give adgang eller spørge brugeren om programmet må få adgang til den ressource.

En ressource kan eksempelvis være netværksadgang som ovenstående opsærtning handler om. Men det kan også være adgang til kontakter i telefonen, adgang til at sende sms eller adgang til kameraet (for bare lige at nævne nogle stykker).

Se link til androids dokumentation om permissions nederst på siden.

Volley opsætning / gradle

I din build.gradle (module:app) skal linjen “implementation ‘com.android.volley:volley:1.1.1’” indsættes under dependencies:

dependencies {
  ...
  implementation 'com.android.volley:volley:1.1.1'
  ...
}

Husk at sync’e efter du har lavet ændringer i en eller flere gradle-filer.

Volley opsætning / RequestQueue

Inden man går igang med at sende og modtage forespørgsler over http, skal man opsætte en kø til at håndtere trafikken.

val queue = Volley.newRequestQueue(appContext)

Metoden newRequestQueue() er en convenience-metode som opsætter og starter en RequestQueue, hvor den bruger nogle default værdier. Hvis man følger dette link til Android developer dokumentationen kan man læse hvordan man selv konfigurerer RequestQueue.

Volley opsætning / Get-request

I dette tilfælge resulterer Requestet i at man modtager en streng:

val url = "http://10.0.2.2:58882/api/" // den url du vil hente data fra

val stringRequest = StringRequest(Request.Method.GET, url,
        Response.Listener<String> { 
            // Her er requestet succesfuldt - håndter requestet.
            // Hvis strengen er json kan den eksempelvis omdannes til en instans af en data class
            Toast.makeText(appContext, "$it", Toast.LENGHT_LONG).show()
        },
        Response.ErrorListener { 
            // Her er der opstået en fejl med requestet (eller trafikken på netværket) - håndter dette.
            Toast.makeText(appContext, "Der skete en fejl: $it", Toast.LENGHT_LONG).show()}
        )
queue.add(stringRequest)

StringRequest er en klasse som ligger i Volley. Den instantieres med:

  1. typen af Http-request der skal bruges (her er det GET)
  2. adressen på ressourcen man vil anvende
  3. Response.Listener<T> - angiver en kodeblok som kaldes hvis requestet er succesfuld gennemført, der kan eksempelvis være en form for callback hvis der er et eller flere steder i koden som har behov for at vide dette.
  4. Response.ErrorListener - angiver en kodeblok som kaldes hvis requestet ikke er succesfuldt, der kan på samme måde også være en callback her.

Til sidst tilføjes requestet til køen vi opsatte i sidste afsnit.

Volley opsætning / Post-request

Start ud med at sætte din payload i en instans af klassen JSONObject:

val jsonObject = JSONObject()
jsonObject.put("languageOrigin", model.languageOrigin)
jsonObject.put("languageTarget", model.languageTarget)
jsonObject.put("textToTranslate", model.textToTranslate)

Requestet opbygges på nogenlunde samme måde som før:

val jsonRequest = JsonObjectRequest(
  com.android.volley.Request.Method.POST,"${BASE_URL + CREATE_REQUEST}", jsonObject,
  Response.Listener<JSONObject> {
      Log.d(TAG, "/post request OK!")
  },
  Response.ErrorListener { Log.d(TAG, "That didn't work ${it.message} ||  $jsonObject") }
)
volleyQueue.add(jsonRequest)

JsonObjectRequest er en klasse som ligger i Volley. Den instantieres med:

  1. typen af Http-request der skal bruges (her er det POST)
  2. adressen på ressourcen man vil anvende
  3. payloaden
  4. Response.Listener<T> - angiver en kodeblok som kaldes hvis requestet er succesfuld gennemført.
  5. Response.ErrorListener - angiver en kodeblok som kaldes hvis requestet ikke er succesfuldt.

Til sidst tilføjes requestet til køen.

Volley, android emulator og localhost

Jeg kører en server på min udviklingsmaskine som skal forestille at være den service som min app skal tilgå. Serveren kører på ip 127.0.0.1, som er loopback adressen (også kendt som localhost). Hvis jeg prøver det samme emulator, kigger emuleringen tilbage på sit eget emulerede localhost. Android emulatoren er indstillet sådan, at hvis man vil tilgå udviklingsmaskinens loopback, så skal man bruge ip-adressen 10.0.2.2 inden i emulatoren.

Samtidig har jeg været nødt til at slå SSL fra på serveren, da jeg ikke har nogle certifikater hverken til server eller app. Med andre ord ville app og server kommunikere i klar tekst hvis de kom ud som de er nu, og det ville være en en større hovedpine ud fra et persondatasikkerhedssynspunkt. Til debugging lokalt, er det iorden for nu.

Reflektion over Volley

Jeg forsøgte oprindeligt at bruge OkHttp. Her havde jeg problemer med at få pakken korrekt konfigureret, så alle requests endte med fejl. Da Volley bliver nævnt i Androids developer dokumentation, valgte jeg at bruge min energi på denne pakke i stedet.

Jeg synes at Volley var/er besværligt at komme igang med. Dokumentationen er ikke helt opdateret så man skal enten vide at compile direktivet er udskiftet med implementation, eller man skal bruge sine søgeevner på nettet til at finde løsningen.

Volley giver mig mulighed for at lave de requests jeg har brug for, men jeg syntes ikke at håndteringen af responses er helt optimal - jeg tænker det er noget jeg kan kigge nærmere på ved lejlighed.

Når man arbejder med requests på nettet, bliver det pludseligt tydeligt at det ikke er nok at kunne lave requests. Netværkstrafikkens natur gør at man ikke kan forvente at resultaterne er tilgængelig øjeblikkeligt, og dette skal man så tage højde for i programmet.

En problemstilling kunne være:

En repræsentation af en liste i appen vises uden elementer, fordi requestet på nettet endnu ikke har givet svar når viewet instantieres.

Yderligere ressourcer