Open menu with table of contents Android Networking
Logo of Stuttgart Media University for light theme Logo of Stuttgart Media University for dark theme
Android Development

Android Networking

Stuttgart Media University

1 Agenda

  • Movie Tracker App
    • REST API Basics
    • JSON
    • Retrofit API client
    • GSON JSON converter
    • Retrofit Example
    • Image loading with Glide

2 REST API Basic

  • Representational state transfer
  • HTTP based
  • Predefined set of operations GET, POST, PUT, DELETE, PATCH, HEAD, CONNECT, OPTIONS and TRACE.
  • Formatted payload HTML, XML, JSON
  • Textual representation of web resources
  • Communication between client and server is stateless

3 Relationship between URI and HTTP methods

HTTP METHODS Collection resource, such as https://api.example.com/collection/ Member resource, such as https://api.example.com/collection/item3
GET Retrieve the URIs of the member resources of the collection resource in the response body. Retrieve representation of the member resource in the response body.
POST Create a member resource in the collection resource using the instructions in the request body. The URI of the created member resource is automatically assigned and returned in the response Location header field. Create a member resource in the member resource using the instructions in the request body. The URI of the created member resource is automatically assigned and returned in the response Location header field.
PUT Replace all the representations of the member resources of the collection resource with the representation in the request body, or create the collection resource if it does not exist. Replace all the representations of the member resource or create the member resource if it does not exist, with the representation in the request body.
PATCH Update all the representations of the member resources of the collection resource using the instructions in the request body, or may create the collection resource if it does not exist. Update all the representations of the member resource, or may create the member resource if it does not exist, using the instructions in the request body.
DELETE Delete all the representations of the member resources of the collection resource. Delete all the representations of the member resource.

Source: https://en.wikipedia.org/wiki/Representational_state_transfer (11/2019)

4 HTTP response status codes

  • Indicates what happen with a specific http request
  • 100–199 Informational responses
  • 200–299 Successful responses
  • 300–399 Redirects
  • 400–499 Client errors
  • 500–599 Server errors

5 JSON Basics

  • JavaScript Object Notation
  • Human readable
  • Standard data format
  • "Replacement of XML"
  • media type: application/json

6 JSON Data Types

  • object
  • array
  • null
  • string
  • boolean
  • number

For examples visit https://restfulapi.net/json-data-types/

7 JSON Example

{
   "Search":[
      {
         "Title":"I, Robot",
         "Year":"2004",
         "imdbID":"tt0343818",
         "Type":"movie",
         "Poster":"https://m.media-amazon.com/images/M/MV5BNmE1OWI2ZGItMDUyOS00MmU5LWE0MzUtYTQ0YzA1YTE5MGYxXkEyXkFqcGdeQXVyMDM5ODIyNw@@._V1_SX300.jpg"
      },
      {
         "Title":"Robot Revolution: The Making of 'I, Robot'",
         "Year":"2004",
         "imdbID":"tt0427788",
         "Type":"movie",
         "Poster":"N/A"
      },
      {
         "Title":"Day Out of Days: The 'I, Robot' Production Diaries",
         "Year":"2004",
         "imdbID":"tt0457853",
         "Type":"movie",
         "Poster":"N/A"
      },
   ],
   "totalResults":"3",
   "Response":"True"
}

8 REST API Clients

  • Best practice: Don't start implementing APIs before you understand them
  • It´s hard to test and debug API calls on Android (Multithreading, Log Cat, Debugger, Permissions, etc.)
  • Use API clients to understand how an API works
    • Browser
    • Browser Extensions like JSON Formatter
    • Broken JSON structure can and will break your client
    • Desktop Apps like POSTMAN

9 Retrofit

Link: https://square.github.io/retrofit/

  • Converts a HTTP API into a Java Interface
  • Minimum Requirements: Android 2.3.
  • Extensible via interceptors
  • Offers converters for all kind of API formats (JSON, XML, etc.)
  • Licensed under the Apache License, Version 2.0
  • Helps you with:
    • API definition
    • API parameters
    • Multithreading
    • Success and error handling
    • Converting JSON <--> Java

10 GSON

Link: https://github.com/google/gson

Gson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object. Gson can work with arbitrary Java objects including pre-existing objects that you do not have source-code of. There are a few open-source projects that can convert Java objects to JSON. However, most of them require that you place Java annotations in your classes; something that you can not do if you do not have access to the source-code. Most also do not fully support the use of Java Generics. Gson considers both of these as very important design goals.

10.1 Goals

  • Provide simple toJson() and fromJson() methods to convert Java objects to JSON and vice-versa
  • Allow pre-existing unmodifiable objects to be converted to and from JSON
  • Extensive support of Java Generics
  • Allow custom representations for objects
  • Support arbitrarily complex objects (with deep inheritance hierarchies and extensive use of generic types)

Source: https://github.com/google/gson (11/2019)

11 Retrofit Example

  1. Setup project Gradle dependency

Add mavenCentral() to your project build.gradle (the one located next to app folder, not inside)

allprojects {
    repositories {
        google()
        mavenCentral()
        jcenter()
        
    }
}

12 Retrofit Example

  1. Setup app Gradle dependency

Add retrofit and gson converter dependency to Gradle

implementation "com.squareup.retrofit2:converter-gson:2.6.1" 
implementation "com.squareup.retrofit2:retrofit:2.6.1"

13 Retrofit Example

  1. Create POJO to represent API model

JSON:

{
    "Title": "Ghost in the Shell",
    "Year": "1995",
    "imdbID": "tt0113568",
    "Type": "movie",
    "Poster": "https://m.media-amazon.com/images/M/MV5BYWRiYjQyOGItNzQ1Mi00MGI1LWE3NjItNTg1ZDQwNjUwNDM2XkEyXkFqcGdeQXVyNTAyODkwOQ@@._V1_SX300.jpg"
}

Java Class:

public class Movie {
    public String Title;
    public String Year;
    public String imdbID;
    public String Type;
    public String Poster;
}

14 Retrofit Example

  1. Create POJO to represent API array

JSON:

{
"Search": [
    {
        "Title": "Ghost in the Shell",
        "Year": "2017",
        "imdbID": "tt1219827",
        "Type": "movie",
        "Poster": "https://m.media-amazon.com/images/M/MV5BMzJiNTI3MjItMGJiMy00YzA1LTg2MTItZmE1ZmRhOWQ0NGY1XkEyXkFqcGdeQXVyOTk4MTM0NQ@@._V1_SX300.jpg"
    },
    {
        "Title": "Ghost in the Shell",
        "Year": "1995",
        "imdbID": "tt0113568",
        "Type": "movie",
        "Poster": "https://m.media-amazon.com/images/M/MV5BYWRiYjQyOGItNzQ1Mi00MGI1LWE3NjItNTg1ZDQwNjUwNDM2XkEyXkFqcGdeQXVyNTAyODkwOQ@@._V1_SX300.jpg"
    }
    ]
}

Java Class:

public class SearchResponse {
    List<Movie> Search;
}

15 Retrofit Example

  1. Create API Interface for Retrofit
public interface MovieApi {
    @GET(".")
    Call<SearchResponse> getSearchResult(@Query("s") String movieSearch, @Query("apikey") String apiKey);
}

16 Retrofit Example

  1. Initialize GSON + Retrofit and make an API call
List<Movie> movieList = new ArrayList<>();

Gson gson = new GsonBuilder()
        .setLenient()
        .create();

Retrofit retrofit = new Retrofit.Builder()
        .baseUrl("https://www.omdbapi.com/")
        .addConverterFactory(GsonConverterFactory.create(gson))
        .build();

MovieApi movieApi = retrofit.create(MovieApi.class);

String searchString = "Ghost in the Shell";

Call<SearchResponse> call = movieApi.getSearchResult(searchString, "MySecretApiKey");

call.enqueue(new Callback<SearchResponse>() {
    @Override
    public void onResponse(Call<SearchResponse> call, Response<SearchResponse> response) {
        movieList = response.body().Search;
    }

    @Override
    public void onFailure(Call<SearchResponse> call, Throwable t) {
        Log.e("Oh noo.", t.getMessage());
    }
});

We use the public free API from OMDb API for this example. You need to put in your email to get a private API key.

17 Image loading with Glide

  • Glide helps you to downlaod, cache and display images via standard Android ImageView.
  • Covers UI and background thread handling.
  • Allows to listen for success and error handling.
  • Extensible to allow usage of transformation (ex. round corners) and animations.
  • Glide v4 requires a minimum API level of 14.
  • Glide v4 requires you to compile against API 26 or later.
  • Allows integration into OkHttp. This is helpful if you hare authentication cookies between API calls and image loading calls.
  • Very important for using image loading with RecyclerViews since user can scroll while images are loaded.

18 Glide gradle dependencies

Add this dependency to your app build.gradle

implementation 'com.github.bumptech.glide:glide:4.10.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'

19 Glide basic usage

Load an remote image into a ImageView.

  • Create a new activty with a ImageView.

Layout XML

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/imgView"
        android:layout_width="200dp"
        android:layout_height="wrap_content" />
</LinearLayout>

20 Glide basic usage

Load an remote image into a ImageView.

  • Implement Glide

Activity

import android.os.Bundle;
import android.widget.ImageView;

import androidx.appcompat.app.AppCompatActivity;

import com.bumptech.glide.Glide;

public class GlideActivty extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_glide_activty);

        String imgUrl = "https://m.media-amazon.com/images/M/MV5BOTlhYTVkMDktYzIyNC00NzlkLTlmN2ItOGEyMWQ4OTA2NDdmXkEyXkFqcGdeQXVyNTAyODkwOQ@@._V1_SX300.jpg";

        ImageView imageView = findViewById(R.id.imgView);

        Glide.with(this).load(imgUrl).into(imageView);
    }
}

21 Glide basic usage

Load an remote image into a ImageView.

  • Implement Glide

center

22 Glide error & success handling

Glide allows for listening to success and error states. This allows you to handle broken urls or to post process images.

Example show Toast if Glide is unable to show image

String imgUrl = "https://example.com/image.jpg"; //invalid image url
Glide.with(this)
        .load(imgUrl)
        .listener(new RequestListener() {
            @Override
            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) {
                Toast.makeText(GlideActivty.this, "Unable to load image", Toast.LENGTH_SHORT).show();
                //TODO show fallback image
                return false;
            }

            @Override
            public boolean onResourceReady(Object resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) {
                return false;
            }
        })
        .into(imageView);