7.2: Connect to the Internet


Most Android applications have some data that the user interacts with; it might be news articles, weather information, contacts, game data, user information, and more. Often, this data is provided over the network by a web API.

In this lesson you learn about network security and how to make network calls, which involves these tasks:

  1. Include permissions in your AndroidManifest.xml file.
  2. On a worker thread, make an HTTP client connection that connects to the network and downloads (or uploads) data.
  3. Parse the results, which are usually in JSON format.
  4. Check the state of the network and respond accordingly.

Network security

Network transactions are inherently risky, because they involve transmitting data that could be private to the user. People are increasingly aware of these risks, especially when their devices perform network transactions, so it's very important that your app implement best practices for keeping user data secure at all times.

Security best practices for network operations:

  • Use appropriate protocols for sensitive data. For example for secure web traffic, use the HttpsURLConnection subclass of HttpURLConnection.
  • Use HTTPS instead of HTTP anywhere that HTTPS is supported on the server, because mobile devices frequently connect on insecure networks such as public Wi-Fi hotspots. Consider using SSLSocketClass to implement authenticated, encrypted socket-level communication.
  • Don't use localhost network ports to handle sensitive interprocess communication (IPC), because other applications on the device can access these local ports. Instead, use a mechanism that lets you use authentication, for example a Service.
  • Don't trust data downloaded from HTTP or other insecure protocols. Validate input that's entered into a WebView and responses to intents that you issue against HTTP.

For more best practices and security tips, take a look at the Security Tips article.

Including permissions in the manifest

Before your app can make network calls, you need to include a permission in your AndroidManifest.xml file. Add the following tag inside the <manifest> tag:

<uses-permission android:name="android.permission.INTERNET" />

When using the network, it's a best practice to monitor the network state of the device so that you don't attempt to make network calls when the network is unavailable. To access the network state of the device, your app needs an additional permission:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

Performing network operations on a worker thread

Always perform network operations on a worker thread, separate from the UI. For example, in your Java code you could create an AsyncTask (or AsyncTaskLoader) implementation that opens a network connection and queries an API. Your main code checks whether a network connection is active. If so, it runs the AsyncTask in a separate thread, then displays the results in the UI.

Note: If you run network operations on the main thread instead of on a worker thread, you receive an error.

Making an HTTP connection

Most network-connected Android apps use HTTP and HTTPS to send and receive data over the network. For a refresher on HTTP, visit this Learn HTTP tutorial.

Note: If a web server offers HTTPS, you should use it instead of HTTP for improved security.

The HttpURLConnection Android client supports HTTPS, streaming uploads and downloads, configurable timeouts, IPv6, and connection pooling. To use the HttpURLConnection client, build a URI (the request's destination). Then obtain a connection, send the request and any request headers, download and read the response and any response headers, and disconnect.

Building your URI

To open an HTTP connection, you need to build a request URI. A URI is usually made up of a base URL and a collection of query parameters that specify the resource in question. For example to search for the first five book results for "Pride and Prejudice" in the Google Books API, use the following URI:


To construct a request URI programmatically, use the URI.parse() method with the buildUpon() and appendQueryParameter() methods. The following code builds the complete URI shown above:

// Base URL for the Books API.
final String BOOK_BASE_URL =  "https://www.googleapis.com/books/v1/volumes?";

final String QUERY_PARAM = "q"; // Parameter for the search string
final String MAX_RESULTS = "maxResults"; // Parameter to limit search results.
final String PRINT_TYPE = "printType"; // Parameter to filter by print type

// Build up the query URI, limiting results to 5 items and printed books.
Uri builtURI = Uri.parse(BOOK_BASE_URL).buildUpon()
       .appendQueryParameter(QUERY_PARAM, "pride+prejudice")
       .appendQueryParameter(MAX_RESULTS, "5")
       .appendQueryParameter(PRINT_TYPE, "books")

To convert the URI to a string, use the toString() method:

String myurl = builtURI.toString();

Connect and download data

In the worker thread that performs your network transactions, for example within your override of the doInBackground() method in an AsyncTask, use the HttpURLConnection class to perform an HTTP GET request and download the data your app needs. Here's how:

  1. To obtain a new HttpURLConnection, call URL.openConnection() using the URI that you've built. Cast the result to HttpURLConnection.

    The URI is the primary property of the request, but request headers can also include metadata such as credentials, preferred content types, and session cookies.

  2. Set optional parameters:
    • For a slow connection, you might want a long connection timeout (the time to make the initial connection to the resource) or read timeout (the time to actually read the data).
    • To change the request method to something other than GET, use setRequestMethod().
    • If you won't use the network for input, set setDoInput to false. (Its default is true.)
    • For more methods you can set, see the HttpURLConnection and URLConnection reference documentation.
  3. Open an input stream using getInputStream(), then read the response and convert it into a string. Response headers typically include metadata such as the response body's content type and length, modification dates, and session cookies. If the response has no body, getInputStream() returns an empty stream.
  4. Call disconnect() to close the connection. Disconnecting releases the resources held by a connection so they can be closed or reused.

These steps are shown in the Request example, below.

If you're posting data over the network and not just receiving data, you need to upload a request body, which holds the data to be posted. To do this:

  1. Configure the connection so that output is possible by calling setDoOutput(true). (By default, HttpURLConnection uses HTTP GET requests. When setDoOutput is true, HttpURLConnection uses HTTP POST requests by default.)
  2. Open an output stream by calling getOutputStream().

For more about posting data to the network, see "Posting Content" in the HttpURLConnection documentation.

Note: All network calls must be performed in a worker thread and not on the UI thread.

Request example

The following example sends a request to the URL built in the Building your URI section, above. The request obtains a new HttpURLConnection, opens an input stream, reads the response, converts the response into a string, and closes the connection.

private String downloadUrl(String myurl) throws IOException {
    InputStream inputStream = null;
    // Only display the first 500 characters of the retrieved
    // web page content.
    int len = 500;

    try {
        URL url = new URL(myurl);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setReadTimeout(10000 /* milliseconds */);
        conn.setConnectTimeout(15000 /* milliseconds */);
        // Start the query
        int response = conn.getResponseCode();
        Log.d(DEBUG_TAG, "The response is: " + response);
        inputStream = conn.getInputStream();

        // Convert the InputStream into a string
        String contentAsString = convertInputToString(inputStream, len);
        return contentAsString;

    // Close the InputStream and connection
    } finally {
        if (inputStream != null) {

Converting the InputStream to a string

An InputStream is a readable source of bytes. Once you get an InputStream, it's common to decode or convert it into the data type you need. In the example above, the InputStream represents plain text from the web page located at https://www.googleapis.com/books/v1/volumes?q=pride+prejudice&maxResults=5&printType=books.

The convertInputToString method defined below converts the InputStream to a string so that the activity can display it in the UI. The method uses an InputStreamReader instance to read bytes and decode them into characters:

// Reads an InputStream and converts it to a String.
public String convertInputToString(InputStream stream, int len)
           throws IOException, UnsupportedEncodingException {
    Reader reader = null;
    reader = new InputStreamReader(stream, "UTF-8");
    char[] buffer = new char[len];
    return new String(buffer);
Note: If you expect a long response, wrap your InputStreamReader inside a BufferedReader for more efficient reading of characters, arrays, and lines. For example:
reader = new BufferedReader(new InputStreamReader(stream, "UTF-8"));

Parsing the results

When you make web API queries, the results are often in JSON format.

Below is an example of a JSON response from an HTTP request. It shows the names of three menu items in a popup menu and the methods that are triggered when the menu items are clicked:

{"menu": {
  "id": "file",
  "value": "File",
  "popup": {
    "menuitem": [
      {"value": "New", "onclick": "CreateNewDoc()"},
      {"value": "Open", "onclick": "OpenDoc()"},
      {"value": "Close", "onclick": "CloseDoc()"}

To find the value of an item in the response, use methods from the JSONObject and JSONArray classes. For example, here's how to find the "onclick" value of the third item in the "menuitem" array:

JSONObject data = new JSONObject(responseString);
JSONArray menuItemArray = data.getJSONArray("menuitem");
JSONObject thirdItem = menuItemArray.getJSONObject(2);
String onClick = thirdItem.getString("onclick");

Managing the network state

Making network calls can be expensive and slow, especially if the device has little connectivity. Being aware of the network connection state can prevent your app from attempting to make network calls when the network isn't available.

Sometimes it's also important for your app to know what kind of connectivity the device has: Wi-Fi networks are typically faster than data networks, and data networks are often metered and expensive. To control when certain tasks are performed, monitor the network state and respond appropriately. For example, you may want to wait until the device is connected to Wi-Fi to perform a large file download.

To check the network connection, use the following classes:

  • ConnectivityManager answers queries about the state of network connectivity. It also notifies applications when network connectivity changes.
  • NetworkInfo describes the status of a network interface of a given type (currently either mobile or Wi-Fi).

The following code snippet tests whether Wi-Fi and mobile are connected. In the code:

  • The getSystemService method gets an instance of ConnectivityManager.
  • The getNetworkInfo method gets the status of the device's Wi-Fi connection, then its mobile connection. The getNetworkInfo method returns a NetworkInfo object, which contains information about the given network's connection status (whether it's idle, connecting, and so on).
  • The networkInfo.isConnected() method returns true if the given network is connected. If the network is connected, it can be used to establish sockets and pass data.
    private static final String DEBUG_TAG = "NetworkStatusExample";
    ConnectivityManager connMgr = (ConnectivityManager)
    NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    boolean isWifiConn = networkInfo.isConnected();
    networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
    boolean isMobileConn = networkInfo.isConnected();
    Log.d(DEBUG_TAG, "Wifi connected: " + isWifiConn);
    Log.d(DEBUG_TAG, "Mobile connected: " + isMobileConn);

The related exercises and practical documentation is in Android Developer Fundamentals: Practicals.

Learn more

results matching ""

    No results matching ""