In order to make network operations in an Android application HTTPUrlConnection is used, which is a specialization of URLConnection with HTTP capabilities. This class manages the client-server communication.
In order to use this class we need to follow these steps:
Here is a simple example of a using HTTPUrlConnection to get the content of a webpage into a String:
URL url = new URL("http://example.com"); HttpsURLConnection connection = null; try { connection = (HttpsURLConnection) url.openConnection(); InputStream is = connection.getInputStream(); ByteArrayOutputStream result = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length; while ((length = is.read(buffer)) != -1) { result.write(buffer, 0, length); } return result.toString("UTF-8"); } catch (IOException e) { Log.e(TAG, e.toString()); } finally { if(connection != null) connection.disconnect(); }
If order for the network request to work we need to have necessary permissions:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
If your app needs to check the network's state it can use the system service ConnectivityManager - documentation examples.
If your app needs to react to connectivity changes (e.g. send a file when the network becomes available) you can use Android's job scheduling API called WorkManager, since newer Android versions removed the system broadcast for connectivity changes. Here's an example (scenario #3) of how to use it: example.
For only https connections we can use HttpsURLConnection. By default HttpUrlConnection can receive use both HTTP and HTTPS because it is a superclass of HttpsUrlConnection. When we call
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
url.openConnection() will return a HttpsUrlConnetion object that can be cast to HttpUrlConnection.
Retrofit is a type-safe HTTP Client for Android and Java. The basic functionality it is to turn the HTTP API into a Java interface.
When working with retrofit you need to consider the following:
Basic steps for using this library:
In this section's code examples we're going to create a basic HTTP GET request for a weather API service. This will receive location as a parameter and will return a Weather object that has all the data related to the current weather for that location.
As stated above in Retrofit we only need to declare our service interface. Below we declared our WeatherService which has a GET request for the location weather. Retrofit uses Annotations to show how a request will be handled. In our case we simply defined in the GET request the path to the weather endpoint and the {location} parameter using {}. In order to complete this we added the @Path(“location”) annotation before the location parameter. This way we link the method parameter to the URL parameter.
public interface WeatherService { @GET("/api/weather?location={location}") Call<Weather> getLocationWeather(@Path("location") String location); }
From here the Retrofit class generates an implementation of the WeatherService interface. When creating the Retrofit instance we need to pass our baseUrl. Using this and appending the requests path will create the complete URL.
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://my.weather.com/") .build(); WeatherService service = retrofit.create(WeatherService.class);
Using the service we can make the Call that will make synchronous or asynchronous HTTP request to the remote webserver.
Call<Weather> weatherCall = service.getLocationWeather("Bucharest");
In order to make the call and get the result in our app will need to call enqueue(). This sends asynchronously the request and notifies the application through the onResponse() callback when a response is received or through onFailure() callback if something goes wrong. This call is handled on a background thread by Retrofit.
weatherCall.enqueue(new Callback<Weather>() { @Override public void onResponse(Call<Weather> call, Response<Weather> response) { displayWeather(response.body()); } @Override public void onFailure(Call<Weather> call, Throwable t) { Toast.makeText(MainActivity.this, "Something went wrong. Please try again later!", Toast.LENGTH_SHORT).show(); } }
If the service responds with JSON objects, Retrofit can help deserialize them by using converters. A popular JSON library for Java is GSON. If you are using Kotlin we recommend Moshi.
The GSON library helps you convert JSON responses into POJOs. In order to use this we need to add a GsonConvertorFactory when creating the service:
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://my.weather.com") .addConverterFactory(GsonConverterFactory.create()) .build(); WeatherService service = retrofit.create(WeatherService.class);
In order to add the two libraries to our application we need to add them as dependencies in the app/build.gradle configuration file.
dependencies { implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.google.code.gson:gson:2.8.6' }
If you plan to use Moshi, here's a Kotlin example (although Moshi supports Java too):
val retrofit: Retrofit = Retrofit.Builder() .baseUrl("https://my.weather.com") .addConverterFactory(MoshiConverterFactory.create()) .build()
apply plugin: 'kotlin-kapt' dependencies { implementation 'com.squareup.retrofit2:retrofit:2.9.0' implementation 'com.squareup.retrofit2:converter-moshi:2.9.0' implementation 'com.squareup.moshi:moshi-kotlin:1.12.0' kapt "com.squareup.moshi:moshi-kotlin-codegen:1.11.0" }
Create a new Android application project for API version >= Oreo.
Download the lab archive and replace the content of activity_main.xml and AndroidManifest.xml with the one provided in the archive.
In this task we will download a web page content and display it.
Try different websites using http or https. Are there any differences?
Remove from the manifest inside the application tag the attribute android:usesCleartextTraffic=“true”. Run the app again and make the webpage request? What happens?
Update the code from Task 1 in order to use HttpsURLConnection. Add the WIFI connectivity check before making the call.
Try different websites using http or https. Are there any differences?
Using the code examples from the lab change the HttpURLConnection network call with a Retrofit implementation. The webpage URL will be set as a base URL for the Retrofit instance.
For this task will use the Open Notify API which gives information about the ISS. From this API will use http://api.open-notify.org/astros.json which gives us the current number of people in space. Using the lab code examples create a Retrofit service for this URL. Make a call to get the number of people in space and return a POJO matching the JSON file structure. Make the request to the API and present the current number of people in space in a TextView.
We want to have a more secure application so that our users need to log in to see their data. In this task we will implement sign up and sign in using Firebase Authentication with Email address and Password. In order to add this to the application go to Tools→Firebase and a new window will appear. Go to Authentication and follow the steps presented there. Use the activity_onboard_layout.xml file from the lab archive as a layout for the signup/signin activity.