Arvutiteaduse instituut
  1. Kursused
  2. 2020/21 sügis
  3. Mobiiliarvutus ja asjade internet (LTAT.06.009)
EN
Logi sisse

Mobiiliarvutus ja asjade internet 2020/21 sügis

  • Main
  • Lectures
  • Labs
  • Homeworks & Home Assignments
  • Quizes
  • Task submission
  • Extra Materials
  • Projects
    • Teams & Topics
    • Presentations & Report
    • Grading & Submission

Lab 8 - Invoking web services and parsing JSON, Cloud Messaging

Table of contents

  • Introduction - HTTP requests with Ion
  • Base Project
  • 1. Basic HTTP request
  • 2. Weather Service
    • 2.1 Getting the API key
    • 2.2 Making the request
    • 2.3 Handling the JSON response
  • 3. Firebase Cloud Messaging
  • 4. Bonus task: Wikipedia 'nearby' API

Introduction - HTTP requests with Ion

In this lab we'll create an app which is a HTTP client to some web servers accessible identified by their URLs. The data is returned by the server in a specific format, which the client has to parse before it can do something useful with it.

We will use the Ion library to make HTTP requests. Ion is a 3rd-party library which:

  • performs the requests in the background for you
  • provides some helper methods which map the HTTP response into different types: String, JsonObject, Bitmap, etc.
  • invokes code specified by a callback function once the response is received

Take a look at the Ion Github page to see examples of how requests are made.

Alternatives to Ion include Volley and OkHTTP. Android also has built-in capabilities for HTTP requests but they are generally more verbose to use.

0. Base project

Download and open the base Android Studio Project. The project has some simple UI definitions (2 activities) to speed up the lab for you.

1. Basic HTTP Request - List of Cities

The first task is to get a text file which lists cities along the coast of the Baltic Sea. The file is hosted on the UT network, at https://kodu.ut.ee/~jaks/baltic_sea/cities.txt

  1. Refer to the Ion documentation & examples and perform the request to load the above URL with Ion, using asString() as the return format.
    • To add Ion to your project: implementation 'com.koushikdutta.ion:ion:3.0.9'
  2. Split the response String into a list using \n character as the separator. You don't have to separate the city from the country name.
  3. Using the existing addToListView() method, add a Button for each individual city to your Apps UI
    • addToListView() sets up a click listener, which opens the 2nd Activity, passing city name as an intent extra.

2. Getting Current Weather for a City using a JSON weather API

2.1 WeatherStack API

  • We will use a Weather API service called WeatherStack. Please sign up for the free version of the service https://weatherstack.com/signup/free .
  • When your account is created, you will see your personal API Access Key at the dashboard. Note it down somewhere, we will need it to make requests to WeatherStack.

2.2 HTTP GET request parameters

For simple HTTP GET requests, query parameters can be passed like so:

  • http://www.example.com?param1=foo&param2=bar , where a list of key-value pairs with format key=value are separated with a &, and the ? symbol separates the base URL from the parameters

In part 1, we did not use any request parameters. For WeatherStack, we will need to add our API key as a parameter, for example. To know the exact parameters and their names the web service expects, we should study their documentation.

WeatherStack API documentation can be found here. Note how the access_key and query parameters are expected to be passed to the request URL.

  • Because secure HTTPS requests are not supported by free WeatherStack plan, we have to enable plainText HTTP traffic for our app by adding android:usesCleartextTraffic="true" to AndroidManifest (within the <application> tag)
  1. In onCreate of CityDetailsActivity, perform a request to fetch that city's current weather (API endpoint URL: http://api.weatherstack.com/current).
    • You can directly use the city name along with country in the same format you got it from part 1.
    • Specify Ion to handle the result as a Json with asJsonObject(), instead of asString()

2.3 Parsing Json response

  • Now, we want to extract certain information from the result (temperature, wind information, weather descriptions (e.g. "Mist"), humidity etc). Ion uses the Gson library for working with the Json format.
    • You can parse with Gson by using MyJsonObject.get(<<memberName>>) and then calling asJsonObject, asJsonArray, asString, asLong, etc, based on the structure of the Json that has been returned.
  • Example: By knowing the response structure (study the example response of WeatherStack documentation), we can assemble code to extract temperature value as a float, like so:
<<myResponseJson>>.get("current").asJsonObject.get("temperature").asFloat

3. Firebase Cloud Messaging

Firebase Cloud Messaging is a service which allows to send messages & notifications to your app from the internet, even if its not running. In addition to such downstream messages (from cloud to the mobile), it also supports upstream messages (client to cloud), which then may be further forward to other mobiles, and so forth.

  • Set up Firebase for your project. The process is the same as we did for Firebase cloud storage.
    • The easy way of setting it up is to use Firebase Assistant within Android Studio (Tools -> Firebase -> Cloud Messaging )
  • Before proceeding, make sure you have the correct google-services.json file to your project and the additional entries in build.gradle file, such as classpath 'com.google.gms:google-services:4.3.4'
  • Once you have the basic Firebase project set up and linked to you Android Studio project, add the Cloud Messaging dependency:
    • implementation 'com.google.firebase:firebase-messaging:20.3.0'

We can now follow the official firebase guide for getting started, but we will not be focusing on all steps.

3.1 Getting a registration token

  • Start by acquiring the registration token, you only need to log the token, so you may simplify the code snippet provided in the exmaple.
    • You can add the code to Activity onCreate().
    • When you launch your app, you should be able to see the Token value being logged, mark it down
  • Now close your application / put it in the background. We will try to send a notification to our app from FCM using the token.
    • Go to Firebase Console / Cloud Messaging, select "Send your first message".
    • Fill in a title (and description), then on the right you should see a button "Send Test Message).
    • In the modal window, enter your Token, then hit send
    • If you app was in the background, a notification should now appear. Clicking the notification takes you to your app.

Handling foreground messages

To handle messages while our app is running, we have to create a new Service that extends FirebaseMessagingService.

  • Create the Kotlin class, override its' onMessageReceived method
  • If you manually created the class (instead of Android Studio new Service wizard), add it to the manifest file.
  • Add an intent filter to the service definition in manifest
            <intent-filter>
                <action android:name="com.google.firebase.MESSAGING_EVENT" />
            </intent-filter>
  • Try to log the message contents, using the token-based test message as we did above.
  • The Notification - related data can be obtained with remoteMessage.notification.XXXX
  • The extra key-value data attached to the notification can be obtained with remoteMessage.data

4. Bonus: Wikipedia 'nearby' API

  • The Weather API response contains among other things, coordinates for each queried location.
  • MediaWiki has a Geosearch module, which allows to query for Wikipedia entries based on coordinates.
  • The base URL for this API is https://en.wikipedia.org/w/api.php
  • This following example makes a request for nearby wikipedia pages and their images with coordinates of Riga:

https://en.wikipedia.org/w/api.php?action=query&generator=geosearch&prop=pageimages|description&pithumbsize=400&inprop=url&ggsradius=1000&ggslimit=5&format=json&ggscoord=56.950|24.100 Here's a breakdown of the request:

URL ParamDescription
generator=geosearchuse the geosearch module
prop=pageimages|descriptionInclude page images and description texts in response
pithumbsize=400set page image thumbnail size to 400 pixels
inprop=urlinclude URLs in the attached properties (such as pageimages)
ggsradius=1000geosearch within 1000 meters
ggslimit=5return max 5 results
format=jsonproduce json output
ggscoord=56.950|24.100the geosearch coordinates

Based on the above example, try to update the app, so that based on the coordinates from the weather API, you pull also data about nearby Wiki pages. When you get the response from the wiki API, you can further make more requests to download the image URLs contained in the Wikipedia response.

  • displayAttraction( .. ) method in CityActivity.kt will help you show results in UI once you have parsed them.

Troubleshooting

If you are getting an exception like java.lang.ClassNotFoundException: Didn't find class com.google.android.gms.security.ProviderInstaller" on path: DexPathList

try adding the following to your Activity onCreate(): Ion.getDefault(applicationContext).getConscryptMiddleware().enable(false)

Bonus: Weather Service Units

Based on the supported query parameters, ( https://weatherstack.com/documentation ), see if you can update the query so that the user can choose the units (imperial vs metric)

  • Arvutiteaduse instituut
  • Loodus- ja täppisteaduste valdkond
  • Tartu Ülikool
Tehniliste probleemide või küsimuste korral kirjuta:

Kursuse sisu ja korralduslike küsimustega pöörduge kursuse korraldajate poole.
Õppematerjalide varalised autoriõigused kuuluvad Tartu Ülikoolile. Õppematerjalide kasutamine on lubatud autoriõiguse seaduses ettenähtud teose vaba kasutamise eesmärkidel ja tingimustel. Õppematerjalide kasutamisel on kasutaja kohustatud viitama õppematerjalide autorile.
Õppematerjalide kasutamine muudel eesmärkidel on lubatud ainult Tartu Ülikooli eelneval kirjalikul nõusolekul.
Courses’i keskkonna kasutustingimused