Chapters

Hide chapters

Android Debugging by Tutorials

First Edition · Android 12 · Kotlin 1.6 · Android Studio Chipmunk (2021.2.1)

Section I: Debugging Basics

Section 1: 8 chapters
Show chapters Hide chapters

11. Profile Network Activity
Written by Zahidur Rahman Faisal

You’ve previously learned how to look into memory footprint using the Android Studio Memory Profiler as a part of your debugging process. In this chapter, you’ll continue your quest and learn to inspect network traffic using the Network Inspector bundled with Android Studio.

Your smartphone performs plenty of network operations every day. From uploading a selfie to your social media account to chatting with someone, all of these tasks are some sort of network operation. Smartphone apps like PodPlay let you subscribe to your favorite podcasts and download the latest updates from your subscribed channel, making network calls, all for your convenience.

This is cool but can be overwhelming for your device if the app performs frequent, unnecessary network operations. To minimize your network data usage and resource consumption, you need to inspect your network activity to keep it optimal.

In this chapter, you’ll learn how to:

  • List the network operations your app performs over a timeline.
  • Find states of a network operation from the aspect of connection status or threading.
  • View details of network requests and responses.

The Network Inspector

The Network Inspector is your one-stop solution to spy on network operations executed by PodPlay. It lets you examine how and when the app transferred data with a timeline in real time.

Follow these steps to bring up the Network Inspector:

  1. Open the Podplay starter project and run the app on an emulator or connected device using API level 26 or higher.
  2. Select View ▸ Tool Windows ▸ App Inspection from the menu bar.

  1. In the App Inspection toolbar, choose your device. Then, select com.yourcompany.podplay from the running app process in the dropdown menu.

  1. Select Network Inspector from the tabs.

You won’t see much at this point apart from a blank timeline moving at the bottom of the Network Inspector panel. That’s your network timeline, and soon you’ll be able to make the most out of it.

Using the Network Timeline

The network timeline is a real-time representation of network activities from your app. It starts from the moment you launch the app and moves as time passes. To see it in action, search for a podcast channel following these steps:

  1. Tap the search icon.
  2. Put “RW” for the search input and press Return.

You’ll see a spike in the network timeline as above. Click the Pause button in the top-right corner of the Network Inspector panel. This will stop your network request (this spike) from moving away with time.

Now, take a moment to analyze what’s going on with the network request to get a deeper understanding.

The Network Inspector displays a few more buttons that give you control over the timeline. The utility of these buttons is as follows:

  1. Zoom Out: Zooms out the timeline, and displays a longer period of time to allocate more requests, if there are any, in the timeline view.

  2. Zoom In: Zooms in the timeline displaying a shorter period of time in the timeline view.

  3. Reset Zoom: Resets any zoom-out or zoom-in over the timeline view and reverts to the default zoom state.

  4. Zoom to Selection: This allows you to zoom into any selected interval from the timeline. This is helpful to focus on a specific time frame you select to identify a network request which occurred within that period.

As you can see, your network request has been made in a period between 5 to 10 seconds after launching the app, select that interval from the timeline and click Zoom to Selection. This will reveal another panel below the timeline, with two tabs — Connection View and Thread View.

These tabs expose detailed information about the network requests you’ve made within the selected interval.

Note: Put your cursor over any point on the network request to view sent and received data at that moment in the timeline.

Connection View

The Connection View tab displays files or network requests sent or received during the selected period in the network timeline, irrespective of threads. You can inspect each request’s name or query, size, type, status and transmission duration.

Here is the summary:

  1. Name of the network request. This column shows the request URL except for the hostname part. Hover the cursor over the request name to see the full request URL.

  2. Size of total data transferred for this network operation.

  3. The type of content received from the request. In this case, it’s Javascript in JSON format.

  4. HTTP Status Code for this request. It indicates whether a specific HTTP request has been completed successfully or had any errors. The selected request was successful and returned with a proper response; hence it’s showing 200. You can learn more about HTTP Status Code in different scenarios here.

  5. The time taken for the whole network operation to complete. According to this, it took a total of 413 milliseconds to execute the request and receive a response from the server.

  6. Duration for the selected request in the timeline. You can see the network operation occurred for less than a second, 413 milliseconds to be specific, sometime between the 5th and 6th second of launching your app.

  7. The range in the top-right corner denotes the selection time frame from the network timeline. In this case, you displayed network operations executed from the 4th to the 7th second in the timeline.

Note: You can sort the list in Connection View by selecting any of the column headers. For example, to sort the network requests based on the size of data transferred, select the Size column.

Thread View

The Thread View lists all CPU threads that have initiated a network activity from your app. Switch the tab from Connection View to Thread View, and you’ll see a panel like this one below:

In the Thread View, you can see the OkHttp framework has been used to create and manage network requests from PodPlay. OkHttp handled the threading mechanism and concurrency for all network operations from within the app. You’ll get more details on threading later in this chapter.

The Thread View contains the timeline column as well. With this cool feature, it’s easy to visualize what happened on the thread for network operations between the 5th and 6th seconds.

Again, hovering your cursor over the selected network thread will display the request parameters and duration for that operation, as shown above.

Inspecting Details

The Network Inspector offers even more details about the Request, Response and Threads for each individual network operation.

Overview

Switch back to the Connection View tab, then select the first row. You’ll see a new panel on the right side:

This is the Overview which holds a lot of interesting details about your network request. It contains 3 main sections:

  1. Displays the response received from the server for this particular network operation. In this case, it’s a JSON object holding an array of podcasts that include your search query “RW”.

  2. Presents details about the request made from the app. Looking at this section, you can extract info such as the full URL, the request method, whether it’s a GET, POST, PUT or another type of request, the status code, content type or size of data exchanged for the request.

  3. Shows a bar with an overview of exchanged data for this network operation. Don’t let the name confuse you, this bar explains that the network operation initially sent a small amount of data to make the request, then received a larger portion of data over the time of execution. The orange segment is sent data and the blue segment is received data proportionally.

Response

Now, switch to the Response tab. The Response tab presents the response headers and the full response body. The response headers hold additional information about the server or how the response is cached:

That’s a lot of information! You might want to focus on a few important areas highlighted above:

  1. Cache: The max-age in the cache-control header indicates that the response will be cached for 86400 seconds. Caching the response reduces server load and bandwidth transmitted, as well as improving loading times.

  2. Content: Content headers contain the size, type or encoding info of the response object. You can see content-length is 9551 bytes. This is especially useful when you’re downloading a file. The content-type is the MIME type of the content. It indicates text is the type and javascript is the subtype of the response.

  3. Status: In most of the cases, you’ll just need to check the date or response-status-code to verify the time you’ve received the response and if you’ve received it successfully. Status code 200 means it was successful.

Scroll down a bit to find another detail:

Body is the most important section here, which displays the complete response. It receives the response as a JSON object in this case. The panel displaying it allows you to scroll down and check the full object.

Request

In the Request tab, you don’t get as many details as in the Response tab. This tab has two sections: Application Headers and Body.

These 2 sections reveal the following information:

  • Encoding: Accept-Encoding tells the server that the app can accept compressed output like gzip for the response.

  • Connection: A default HTTP connection is usually closed after completing each request. Keep-Alive header, also known as HTTP persistent connection, is kind of a communication message between the app and server that says: “You may grab many files as long as the connection is alive.” This configuration is handy if you request something that includes multiple files, such as a web page. Setting Keep-Alive transfers all the necessary files through a single connection request instead of creating and closing multiple connections.

  • Host: The domain name or the server’s hostname you’ve requested. In this case, it’s itunes.apple.com.

  • Agent: user-agent represents a software or framework that retrieves, renders and facilitates interaction with the web content on behalf of the user, the PodPlay app. You can see PodPlay relies on the OkHttp library to create and manage network requests for you. It also displays that the version code of OkHttp library is 4.8.1.

  • Body: Since it was a GET request, the request body isn’t available in this case. You could see the request body submitted to the server in this section if it was a POST or PUT request. The pane is useful to verify if the request body submitted is what the server expects when creating a POST or PUT request.

Call Stack

The fourth and final tab in the network details panel is Call Stack. Switch to that tab, and you’ll see a stack of threads that corresponds to the network operation as follows:

As you already know the OkHttp library is handling threading for the network operations. You can see it’s running a Worker Thread using ThreadPoolExecutor. This ensures concurrency when there are multiple requests.

By inspecting the call stack, you can also tell that the threads for network operations, and worker thread, are running on top of the Java main thread, also known as the UI Thread. This isolates the network process from the main thread. That’s the trick that keeps your app responsive while running an expensive network request in the background!

Tracing Unusual Network Traffic

Now you know how to inspect network operations using the tool-set offered by Network Inspector. Relaunch the PodPlay app, hold on and do nothing for 10 - 20 seconds, and you’ll notice something odd in the network timeline:

What, a spike!? But you did nothing… right?

Apparently, there’s some unwanted network operation made from PodPlay. Select the spiked segment from the timeline, and you’ll be surprised to see that there’s no information available:

That’s strange, but this situation occurs when the Network Inspector detects traffic values yet can’t identify any supported network requests. In such cases, you might want to log your network operations to see what’s happening.

Logging Network Operations

Open ItunesService.kt and add these imports on top:

import com.yourcompany.podplay.BuildConfig
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import java.util.concurrent.TimeUnit

Then replace the companion object as follows:

companion object {
 val instance: ItunesService by lazy {
   // 1
   val client = OkHttpClient().newBuilder()
       .connectTimeout(30, TimeUnit.SECONDS)
       .writeTimeout(30, TimeUnit.SECONDS)
       .readTimeout(30, TimeUnit.SECONDS)
   // 2
   if (BuildConfig.DEBUG) {
       val interceptor = HttpLoggingInterceptor()
       interceptor.level = HttpLoggingInterceptor.Level.BODY
       client.addInterceptor(interceptor)
   }
   // 3
   val retrofit = Retrofit.Builder()
       .client(client.build())
       .baseUrl("https://itunes.apple.com")
       .addConverterFactory(GsonConverterFactory.create())
       .build()
   retrofit.create(ItunesService::class.java)
 }
}

The above code has three changes to the previous implementation, it:

  1. Creates an OkHttpClient to send HTTP requests and read responses.
  2. Attaches a HttpLoggingInterceptor for logging HTTP request and response data when your app is in debug mode.
  3. Uses the OkHttpClient object with your Retrofit builder, which is responsible for communicating with the server.

Relaunch PodPlay and look into the Logcat from the IDE. Search for the term “OkHttpClient”.

Now you’ll be able to see the request and response made from the app getting logged:

Highlight the request from the logs you have. You can clearly see the GET request ends with term=, which means the request has been made with no search term, with an empty string!

Scroll a bit down to find the response body.

Since there’s no search term provided in the request query, you can see that the response also returned as an empty array instead of a proper response.

This certainly looks like a programming error, but it gives you a clue! Look for places where a network has been made with an empty input.

If you look back, this unusual network request was executed shortly after you launched the app. So look for onCreate() inside PodcastActivity.kt, which is the entry point when you launch PodPlay.

Voilà, there’s a call for performSearch(term = "") - that seems to be responsible for this unusual network activity!

Remove performSearch(term = "") and launch the app again. Observe the network timeline and Logcat and notice there is no weird network call anymore.

Congratulations! You successfully eliminated the unnecessary network call.

Key Points

  • Network Inspector offers a set of tools showing all the details available on network operations.
  • Network timeline is the key to looking for network activity at any point since you launch the app.
  • You can leverage Connection View and Thread View to look into different aspects of a network operation.
  • Logging HTTP request and response data helps if you still can’t find enough information through Network Inspector.

Where to Go From Here?

Your debugging skills have reached the next level as you’ve mastered the art of debugging network operations! To learn more on this topic, check out the tutorials and videos below:

Don’t stop here! In the next chapter, you’ll learn to use Energy Profiler to optimize your app for minimizing resource consumption. Good luck on your next adventure!

Have a technical question? Want to report a bug? You can ask questions and report bugs to the book authors in our official book forum here.
© 2026 Kodeco Inc.