Fixing the NetworkOnMainThread exception in your Android app with AsyncTask

As soon as you start doing long-running operations such as network calls or anything else that can take more than a few seconds in your Android application, you’ll come across one of the following problems:

  • The [Application] not responding (ANR) popup is shown while you run your application, and the The application may be doing too much work on its main thread. warning is shown in your Logcat traces.
  • The NetworkOnMainThreadException exception is launched as soon as you call anything over the network like an API, regardless of the duration of the call.

Why does the Android SDK complains when one of those things happens? Why does code that seems to be correct doesn’t work? Well, if your application stays frozen, your users could think it crashed. A few seconds is an eternity when you don’t have any feedback about what’s going on, and users are probably going to keep pressing buttons as a response, or close your application and never return. So, to prevent this, the Android SDK enforces minimum standards for responsiveness and display errors if those standards are not respected.

To understand why the application freezes, we must take a look at the architecture of the application. By default, your Android application has only one thread, called the main thread. All you code execute on this single thread, and a thread can only do one thing at a time.

So, if you call the network and there is a delay, everything stops while the application waits for an answer, freezing your UI completely. You won’t even be able to display a progress bar because nothing else can run. The timeline looks like:

Fortunately, you can create new threads, which allow you to do more than one thing at once:

For one-time operations that only takes a few seconds, the easiest way to manage this is to use the AsyncTask class available in the Android SDK. It will create a new thread for you that will do a specific task, and then notify you when that task is over so you can update your UI.

Here is an example of an AsycTask that calls the GitHub API to calculate the number of repository that contains the “Android” string. While the query is running, a progress bar is shown in the UI.

private class GithubAndroidRepositoryQueryTask extends AsyncTask<String, Integer, String> {

@Override
protected void onPreExecute() {
   super.onPreExecute();
   // Prepare the UI in the main UI thread before executing the task.
   mGitRepositoryProgressBar.setVisibility(View.VISIBLE);
}

@Override
protected String doInBackground(String... params) {
   // Do the operation on a new thread and returns the result. It calls the GitHub API to 
   // calculate the number of repository that contains the Android string
   return getAndroidRepositoryCountFromGitHub();
}

@Override
protected void onProgressUpdate(Integer... progress) {
   // Could be used to update the main UI thread with the progress of the background
   // operation.
}

@Override
protected void onPostExecute(String result) {
   // Receive the result of the operation done in the new thread in the main UI thread and
   // use it to update the UI.
   super.onPostExecute(result);
   mGitRepositoryProgressBar.setVisibility(View.INVISIBLE);
   mGitRepositoryTextView.setText(result);
}
}

And here is how you execute that task. In that case, it’s launched onCreate event of the Activity so the response is visible immediately in the layout, but it could be launched from anywhere else:

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.activity_main);
   mGitRepositoryTextView = (TextView) this.findViewById(R.id.github_repositories_tv);
   mGitRepositoryProgressBar = (ProgressBar) this.findViewById(R.id.github_repositories_pb);

   // Fires off an AsyncTask to get the number of Android repositories on GitHub and displays
   // it in the application.
   new GithubAndroidRepositoryQueryTask().execute();
}

Subscribe to my newsletter and get the executable code sample to use AsyncTask as shown in this post by entering your email address here :

Powered by ConvertKit

When you’re working with threads of any kinds, remember that updating the UI should only be done on the main thread. The Android SDK doesn’t support updating the UI from other threads, so you’ll likely have random crashes and weird behavior if you attempt it.

Also, as a caveat, Google doesn’t recommend relying on showing a progress bar exclusively for long-running operations. They believe that users should be able to keep working in the application and that you should manage what’s going on in the backend.

If you have a simple application that has only a few simple cases it may work, but if you have complex interactions between your data you can sink a lot of time trying to make everything work nicely together and handling what happens if an operation fails.

Still, you can start with a simple AsyncTask and optimize as you go along. In most cases, it’s going to be a good starting point, but as soon you need to execute many tasks at once it won’t be enough. When you’re ready to go further with this, you should take a look at libraries such as RxJava to help you manage your tasks.

How to get started with Android development – Layout Managers

At the end of my last article, I left you hanging after describing activities, without telling you how to build a UI, so here we go. In the Android SDK, layouts are separate from the Java code that defines how an activity behaves. Using this separation of concern, it’s easier to modify the layout without having to worry about the code.

Android layouts are in XML, and are located in the res\layout folder. You can have multiple versions of a layout for various orientations, screen size or culture and the Android SDK will choose the right one according to the device. We won’t worry about this right now; for simple layouts one version is enough.

In this article, I’m going to show you how to use a layout manager to position a widget, called a View in the Android SDK, using XML and Java. Next time, I’ll complete this explanation with more details about views themselves, and how they can be controlled in the layout or programmatically.

There is also a designer tool in Android Studio to help build your layouts. I’ll stick to the code for now since I believe it’s best to understand how things are built manually first, and then you’ll know enough to be able to explore it on your own.

Your First Layout

Here is a simple layout with two TextView views, each showing a text string, inside a LinearLayout layout manager in the res\layout\activity_main.xml file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:text="My first textview"/>
    <TextView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:text="My second textview"/>
</LinearLayout>

Each layout has a least one view as a root, but it’s usually a layout manager such as the LinearLayout, RelativeLayout or ConstraintLayout since those views are built to position other views. I used the linear layout in this example since it’s simple to understand: if the property android:orientation is set to vertical, all the views will be aligned one over the other, and if set to horizontal they will be side by side.

To use your layout with your activity, you must set the layout in the onCreate() event of the activity using the setContentView() method :

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
} 

Views and Layout Managers Properties

All views, including layout managers, have proprieties that can be added to their XML declaration to control their size and padding. For example, you can specify an android:layout_height and android:layout_width in dp (density-independent pixels) like the layout above, or use the wrap_content and match_parent values:

  • wrap_content: The size (width or height) of the view will be the size required to display its content. For example, if you have a very long view showing text, you’ll use wrap_content as the height so it doesn’t get truncated at the bottom.
  • match_parent: The size (width or height) of the view will be the same as the size of its parent layout element. This used to be called fill_parent in API level 7 and less, so you’ll still see that name from time to time.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
              android:layout_width="match_parent" 
              android:layout_height="match_parent" 
              android:orientation="vertical">
    <TextView android:layout_width="match_parent" 
              android:layout_height="wrap_content" 
              android:text="My first textview"/>
    <TextView android:layout_width="match_parent" 
              android:layout_height="wrap_content" 
              android:text="My second textview"/>
</LinearLayout>

Each layout manager also has properties to control the positioning of the views they contain, such as the android:orientation for the LinearLayout described previously.

Layout managers can be nested to create complex layouts: for example, you can add a vertical linear layout inside a horizontal linear layout or a grid layout. Still, to make rendering more efficient, you should be careful to avoid nesting too many layouts.

So next time, we’ll take a look at how to use complex views that requires an interaction from the user, and how control those views from your Java code.

See the other articles in the series here

How to get started with Android development

andro02Learning how to build a mobile application is a good project to improve your programming skills while learning to work in a different environment than the desktop or a web browser. You can get started without worrying about a large stack, making it easy for a beginner to pick it up and start playing with quickly.

Building applications with the Android SDK is self-contained if you stick with the standard libraries. You only need to download the package from Google containing all the tools and you’re ready to go. If you know object-oriented programming and how layouts are done for the web, many patterns and practices will feel familiar to you. The barrier to entry is low: all the tools are free, so you only need an Android device and your computer to get started.

Also, the open philosophy of Android means that you can do as you wish with your applications and your device. As long as you have an installer file (.apk), you can distribute your application to any device. It’s easy to send a copy of your application to your friends so they can test it out. This is great if you have a small project that you only want to deploy on a few machines such as a kiosk an art project. Once you have more experience, there are many open source libraries that improve on what is available in the SDK, and the open source community is active and welcoming.

The following will teach you how to get up and running with the samples included with the Android SDK.

Setting up an Android development environment

You don’t need much to get started with Android. Any decent PC, Mac or Linux box will do the job. All the tools are free, and you can install them as a single package from the Google Android Developers site at https://developer.android.com/sdk/.

There are two main tools you need to know about: the Android SDK Manager and the Android Studio IDE.

The Android SDK Manager is used to download the libraries, tools, system images and code samples for the platform (version) of the Android OS you want to develop for. By default, the package contains the latest version of the SDK Platform (6.0/API level 23 as I’m writing this). When a new version comes out or a new developer kit is available, you must download it using the SDK Manager.

The Android Studio IDE is where you’re going to spend most of your time. It is based on IntelliJ and includes a code editor, a layout editor and all the tools you need to compile your application and debug it on an emulator or on your Android device. Eclipse was previously available as an IDE so you’re going to see some references to it online, but Android Studio is now the official IDE for Android and everybody is now using it.

Installing the drivers for your tablet

By default, when you plug in an Android device in your computer, you’ll see the content of the external storage like you would see the content of a USB key. It’s enough to upload data, but if you want to debug an application on your device, you must install the drivers. You could develop applications using the emulator, but it’s a lot slower and it’s going to be hard to see if the touch interactions work as you intended.

If you have a Nexus device, the drivers are available from the Android SDK Manager. For other manufacturers like Samsung or ASUS, you can find the driver on their website. It’s not always clear what you should download, since the driver is often packaged with other software such as synchronization tools.

To be able to attach a debugger, you must also enable the debugging mode on your device by navigating to the About option in the Settings menu. Click 10 times on About and the Developers Options menu will appear, allowing you to set the debugging mode.

Running the sample projects from the Android SDK

The language used with the Android SDK is Java, but Android has its own virtual machine, Dalvik, that uses a subset of the standard Java classes. Since it’s such a small subset of Java, you don’t need experience in Java to get started. If you have a good basis in any object-oriented language, you should be able to pick it up pretty fast. The rest of the files, such as language files and layouts, are in XML.

To get started quickly, I’m going to show you how to run one of the sample projects. Those samples are from Google and they are a good starting point to learn what you can do in an Android application and how to do it. Google regularly adds new samples as new APIs becomes available, so check them before trying to do something.

When you start Android Studio for the first time, you’ll see the following screen. To get started running an application right now, just select Import an Android code sample to create a project.

AndroidStudioWelcome

In the following screen, choose the Borderless button example and click Next to create the project:

Once the project is loaded, select Debug… from the Run menu to launch the application in debugging mode on your device. A Device Chooser window will pop up, allowing you to select your device (if the driver has been properly installed) or to launch the emulator. Press OK and the sample will run on your device.

You can now play with the sample and add breakpoints in the source code (located in the Application\src\ folder) to see how it behaves. For example, you can put a breakpoint in the onCreate method of the MainActivity.js file, and try to understand how it behaves when you rotate your device.

Follow up articles:
Basic structure of an Android application
Layout of an activity using a layout manager