Connectivity in Android

Connect to the network

To perform network operations in your application, your manifest must include the following permissions:
 <uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Note: Both the Internet and ACCESS_NETWORK_STATE permissions are normal permissions, which means they're granted at install time and don't need to be requested runtime.
  • Best practices for secure network communication
    • Minimize the amount of sensitive or personal user data that you transmit over the network.
    • Send all network traffic from your app over SSL.
    • Consider creating a network security configuration, which lets your app trust custom certificate authorities (CAs) or restrict the set of system CAs that it trusts for secure communication.
    • Follow networking security tips
  • Choose an HTTP client
    • Most network-connected apps use HTTP to send and receive data.
    • The Android platform includes the HttpsURLConnection client.
    • Retrofit is also an HTTP client library which supports automatic serialization of request bodies and deserialization of response bodies.
  • Resolve DNS queries
    • The DnsResolver API provides generic, asynchronous resolution, which lets you look up SRV, NAPTR and other record types.
    • Note that parsing the response is left to the app to perform.
    • For NDK-based apps, see android_res_nsend.
  • Encapsulate network operations with a repository
    • You can use the repository design pattern to simplify the process of performing network operations.
    • A repository is a class that handles data operations and provides a clean API abstraction over some specific data or resource.
    • Within a repository class, functions can encapsulate network operations and expose their results. This encapsulation ensures that the components that call the repository don't need to know how the data is stored.
    • To avoid creating an unresponsive UI, don't perform network operations on the main thread. By default, Android requires you to perform network operations on a thread other than the main UI thread; it you don't, a NetworkOnMainThreadException is thrown.
  • Survive configuration changes
    • When a configuration change occurs, such as screen rotation, your fragment or activity is destroyed and recreated.
    • You can use a ViewModel to ensure that your data survives configuration changes. The ViewModel can make the necessary network requests and provide the result to your fragment or activity using LiveData.
    • For implementation use the link of the header.

Manage network usage

If your application performs a lot of network operations, you should provide user settings that allow users to control your application's data habits, such as how often your app syncs data, whether to perform uploads/downloads only when on Wi-Fi, whether to use data while roaming, and so on.

  • Check a device's network connection
    • A device can have various types of network connections. For the full list of possible network types see ConnectivityManager.
    • ConnectivityManager has the following responsibilities
      • Monitor network connections
      • Send broadcast intents when network connectivity changes
      • Attempt to "fail over" to another network when connectivity to a network is lost.
      • Provide an API that allows applications to query the coarse-grained or fine-grained state of the available networks.
      • Provide an API that allows applications to request and select network for their data traffic
      • It is a synchronous method.
    • Wi-Fi is typically faster. Also, mobile data is often metered. A common strategy for apps is to only fetch large data if a Wi-Fi network is available.
    • Before you perform network operations, it's a good practice to check the state of network connectivity.
    • To check the network connection, you typically use the following classes
    • For implementation click the link of the header.
    • Note that you should not base decisions on whether a network is "available". You should always check isConnected() before performing network operations.
    • A more concise way of checking whether a network interface is available is by using getActiveNetworkInfo() method, which returns NetworkInfo instance representing the first connected network interface it can find, or null if none of the interfaces is connected.
public class Utility {
public static boolean isOnline(Context context) {
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
return (networkInfo != null && networkInfo.isConnected());
}
}
  • Manage network usage
    • To write an app that supports network access and managing network usage, your manifest must have the right permissions and intent filters.
    • You can declare the intent filter for the ACTION_MANAGE_NETWORK_USAGE action to indicate that your application defines an activity that offers to control data usage. This intent filter shows settings for managing the network data usage of a specific application. When your app has a settings activity that allows users to control network usage, you should declare this intent filter for that activity.
    • For implementation click the link of the header.
    • To reduce the chances of data leak you can click the link of the header.
  • Implement a preference activity
    • For implementation click the link of the header.
  • Respond to preference changes
    • When the user changes preferences in the settings screen, it typically has consequences for  the app's behavior.
    • For implementation click the link of the header.
  • Detect connection changes
    • You need to setup a BroadcastReciever if the device's network changes.
    • CONNECTIVITY_ACTION, determines what the network connection status is and sets the flags accordingly.
    • Setting up a BroadcastReciever that gets called unnecessarily can be a drain on system resources. You should register a BroadcastReciever in onCreate() and unregister it in onDestroy(). This is more lightweight than declaring a <receiver> in the manifest. When you declare a <receiver> in the manifest, it can wake up your app at any time, even if you haven't run it for weeks. By registering and unregistering within the main activity, you ensure that the app won't be woken up after the user leaves the app. If you do declare a <receiver> in the manifest and you know exactly where you need it, you can use setComponentEnabledSetting() to enable and disable it as appropriate.
    • For implementation click the link of the header.

Reading network state

Use the following classes to track and respond to connectivity changes
  • ConnectivityManager
    • Tells your app about the state of connectivity in the system.
  • Network
    • Represents one of the networks that the device is currently connected to. You can use the Network object as a key to gather information about the network with ConnectivityManager or to bind sockets on the network. When the network disconnects, the Network object stops being usable; even if the device later reconnects to the same appliance, a new Network object will represent the new network.
  • LinkProperties
    • Contains information about the link for a network, such as the list of DNS servers, local IP addresses, and network routes installed for the network.
  • NetworkCapabilities
    • Contains information about properties of a network, such as the transports (Wi-Fi, cellular, Bluetooth) and what the network is capable of.
Apps interested in the immediate state of connectivity at any given time can call ConnectivityManager methods to find out what kind of network is available. The synchronous ConnectivityManager methods do not tell your application about anything happening after a call, so they don't enable you to update your UI nor adjust app behavior based on the network disconnecting or when the network capabilities change.
Using the callback which you registered for ConnectivityManager, you application can react immediately to any relevant change in connectivity without having to resort to expensive polling that may miss fast updates.
  • Getting instantaneous state
    • An Android device may maintain many connections at the same time. First obtain an instance of ConnectivityManager.
    • Use this instance to get a reference to the current default network of your app.
    • With a reference to a network, your app can query information about it.
    • For implementation use the link of the header.
  • NetworkCapabilities and LinkProperties
    • The NetworkCapabilities and LinkProperties objects provide information about all attributes that the system knows about a network.
    • LinkProperties object knows about the routes, link addresses, interface name, proxy info (if any), and DNS servers.
    • NetworkCapabilities object encapsulates information about the network transports and their capabilities.
    • A transport is an abstraction of a physical medium over which a network operates. In Android, a network can have multiple transports at the same time.
    • To find out if a network has a particular transport, use NetworkCapabilities.hasTransport(int) with one of the NetworkCapabilities.Transport_* constants.
    • Your application can check for appropriate capabilities by using NetworkCapabilities.hasCapability(int) method with one of the NetworkCapabilities.NET_CAPABILITY_* constants.
    • Capabilities of a network can change at any time. Likewise, the transports of a network can change dynamically. 
    • To understand the above concept read the corresponding examples given in the link of the header.
  • Listening to network events
  • Additional networks
  • An example
    • This section describes the sequence of callbacks can application might get if it registers both a default callback and a regular callback on a device that currently has mobile connectivity.
    • For implementation use the link of the header.
  • Restrictions on the use of the network for data transfer
    • Being able to see a network with a network callback does not mean your app can use the network for data transfer.
    • Some networks do not provide internet connectivity and some networks may be restricted to privileged apps.
    • If your app wants to use a background network, it needs the CHANGE_NETWORK_STATE permission. Apps with this permission are also allowed to ask the system to try to bring up a network that is not currently up, such as the cellular network when the device is connected to a Wi-Fi network.
    • Such an application would call ConnectivyManager.requestNetwork() with a NetworkCallback to be called when the network is brought up.

Optimize network access

To minimize the battery drain associated with network activity, it's critical that you understand how your connectivity model will affect the underlying radio hardware.
  • The radio state machine
    • The wireless radio on your user's device has built-in power-saving feature that help minimize the amount of battery power it consumes.
    • When full active, the wireless radio consumes significant power but when inactive or in standby, the radio consumes very little power.
    • One important factor to remember is that the radio cannot move from standby to fully active instantaneously. There is a latency period associated with "powering up" the radio.
    • The radio state machine on each device, particularly the associated transition delay ("tail time) and startup latency, will vary based on the wireless radio technology employed (3G, LTE, 5G, and so on) and is defined and configured by the carrier network over which the device is operating.
  • How apps impact the radio state machine
    • Every time you create a new network connection, the radio transitions to the full power state. 
    • In a 3G device, an app which makes a one second data transfer, three times a minute, will keep the wireless radio perpetually active, moving it back to high power just as it is entering standby mode.
    • In this above image, relative wireless radio power use for one-second transfer running three times every minute. Means, for every data transfer session of 1 second, causes the radio to draw energy for at least 18 seconds.
    • If the same app bundled its data transfers, running a single three-second transfer every minute, this would keep the radio in the high-power state for only 20 seconds each minute. This would allow the radio to be standby for 40 seconds of every minute, resulting in a significant reduction in battery consumption.
  • Optimization techniques
    • Follow these steps to reduce battery drain when your app is using a network
      • Bundle data transfers
        • You should bundle your data transfers so that you're transferring more data less often is one of the best ways to improve battery efficiency.
        • This is not always possible if your app needs to receive or send data immediately in response to a user action.
        • You can mitigate this by anticipating and prefetching data.
        • See Optimizing app-initiated tasks for tips on scheduling background network transfers.
      • Prefetch data
        • Prefetching data is another effective way to reduce the number of independent data transfer sessions that your app runs.
        • With prefetching, when the user performs an action in your app, the app anticipates which data will most likely be needed for the next series of user actions and fetches that data in a single burst, over a single connection.
        • Prefetching also provides an improved user experience by minimizing in-app latency caused by waiting for downloads to complete before performing an action or viewing data.
        • A better approach would be to prefetch a reasonable amount of data at startup.
      • A news reader
        • For example of prefetching use the link of the header.
      • Additional considerations
        • While prefetching data carries a lot of benefits, used too aggressively prefetching also introduces the risk of increasing battery drain and bandwidth use. 
        • It is also important to ensure that prefetching doesn't delay application startup while the app waits for the prefetch to complete.
        • It's a good practice to prefetch data such that you will only need to initiate another download every 2 to 5 minutes, and in the order of 1 to 5 MBs. The WorkManager API supports exactly this use case.
      • Check for connectivity before making requests
        • Searching for a cell signal is one of the most power-draining operations on a mobile device.
        • You should use ConnectivityManager to first check for a connection as show in Monitor connectivity status and connection monitoring.
        • If there's no network, the app can save battery by not forcing the mobile radio to search. 
        • The request can then be scheduled and performed in a batch with other requests when a connection is made.
      • Pool connections
        • You must pool your app's connection.
        • Reusing connections also allows the network to more-intelligently react to congestion and related network data issues.
        • HttpURLConnection and most HTTP clients, such as OkHttp, enable connection-pooling by default and reusing the same connection for multiple requests.

Optimize network data usage

When a user enables Data Saver in Settings and the device is on a metered network, the system blocks background data usage and signals apps to use less data in the foreground wherever possible. ConnectivityManager API provides an application a way to retrieve the user's Data Saver preferences and monitor preference changes. It is considered good practice for apps to check whether the user has enabled Data Saver and make an effort to limit foreground and background data usage.

Monitoring connectivity status and connection metering

The ConnectivityManager provides an API that enables you to request that the device connect to a network based on various conditions that include device capabilities and data transport options.

Parse XML data

Uploading and parsing XML data is a common task for network-connected apps.
  • Choose a parser
    • We recommend XmlPullParser, which is an efficient and maintainable way to parse XML on Android.
  • Analyze the feed
    • The first step in parsing a feed is to decide which fields you are interested in.
    • For example use the link of the header.
  • Instantiate the parser
    • To kick off the parsing process, you will need an InputStream in XmlPullParser.setInput()
    • For implementation use the link of the header.
  • Read the feed
    • Write a method to look for elements tagged as a starting point for recursively processing the feed.
    • For implementation use the link of the header.
  • Parse XML
    • For implementation use the link of the header.
    • Note: The link has complete implementation with best practices.
  • Skip tags you don't care about
    • Write a method to skip tags you are not interested in.
    • For implementation use the link of the header.
  • Consume XML data
    • For implementation use the link of the header.
    • Note: The link has complete implementation with best practices.

Perform network operations using Cronet

Cronet is the Chromium network stack made available as a library for you to use in your apps.
  • Features
    • Protocol Support
    • Request prioritization
      • The library allows you to set a priority tag for the requests. The server can use the priority tag to determine the order in which to handle the requests.
    • Resource caching
      • Cronet can use an in-memory or disk cache to store resources retrieved in network requests. Subsequent requests are served from the cache automatically.
    • Asynchronous requests
      • Network requests is issued using the Cronet library are asynchronous by default. Your worker threads aren't blocked while waiting for the request to come back.
    • Data compression

Send a simple request

Cronet request lifecycle

  • Lifecycle overview
    • Network requests created using the Cronet Library are represented by the UrlRequest class. These are the following concepts of UrlRequest lifecycle
      • States
        • A state is the particular condition that the request is in at a specific time. UrlRequest objects move through different states in their lifecycle (initial state, and multiple transitional and final states).
      • UrlRequest methods
        • Clients can call specific method of UrlRequest objects depending on the state. The methods move the request from one state to another.
      • Callback methods
        • By implementing the methods of the UrlRequest.Callback class, your app can receive updates about the progress of the request. You can implement the callback methods to call methods of the UrlRequest object that take the lifecycle from a state to another.
    • For complete explanation use the link of the header.

Enhance your apps with 5G

Do's and Don'ts

  • To avoid creating an unresponsive UI, don't perform network operations on the main thread.
  • Before you perform network operations, it's a good practice to check the state of network connectivity.
  • Note that you should not base decisions on whether a network is "available".
  • You should register a BroadcastReciever in onCreate() and unregister it in onDestroy(). This is more lightweight than declaring a <receiver> in the manifest. When you declare a <receiver> in the manifest, it can wake up your app at any time, even if you haven't run it for weeks. By registering and unregistering within the main activity, you ensure that the app won't be woken up after the user leaves the app. If you do declare a <receiver> in the manifest and you know exactly where you need it, you can use setComponentEnabledSetting() to enable and disable it as appropriate.
  • If your app wants to use a background network, it needs the CHANGE_NETWORK_STATE permission.
  • Capabilities of network can change at any time. Likewise, the transports of a network can change dynamically.
  • If it is important for the app to know when the default network changes, it should register a default network callback.
  • To specify the transport type of the network and the currently connected network's capabilities, you must configure a network request.
  • When you register the NetworkRequest with the ConnectivityManager, you must implement a NetworkCallback to receive notifications about changes in the connection status and network capabilities.
  • After you declare the NetworkRequest and NetworkCallback, use the requestNetwork() or registerNetworkCallback() functions to search for a network to connect from the device that satisfies the NetworkRequest.

References




Comments

Popular posts from this blog

SSLSocketFactory in Android

Dagger-Hilt in Android

How to write files in Android?