2708

I got an error while running my Android project for RssReader.

Code:

URL url = new URL(urlToRssFeed);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader xmlreader = parser.getXMLReader();
RssHandler theRSSHandler = new RssHandler();
xmlreader.setContentHandler(theRSSHandler);
InputSource is = new InputSource(url.openStream());
xmlreader.parse(is);
return theRSSHandler.getFeed();

And it shows the below error:

android.os.NetworkOnMainThreadException

How can I fix this issue?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
bejoy george
  • 29,385
  • 5
  • 19
  • 15
  • 139
    [**Read this blog post**](http://www.androiddesignpatterns.com/2012/06/app-force-close-honeycomb-ics.html) on the NetworkOnMainThreadException for more information. It explains why this occurs on Android 3.0 and above. – Adrian Monk Aug 07 '12 at 12:38
  • 6
    To be on rite track first read about the Network Requests in android then i would recommend to study "Volley". – Anuj Sharma Jan 23 '14 at 06:39
  • 3
    There are many alternative libraries that solve this issue. Many are listed [at the bottom of this page](https://github.com/octo-online/robospice/blob/release/README.md#alternatives-to-robospice-). If you got more, we take them :) – Snicolas Feb 11 '14 at 22:55
  • "Due to a bug in previous versions of Android, the system did not flag writing to a TCP socket on the main thread as a strict-mode violation. Android 7.0 fixes this bug. Apps that exhibit this behavior now throw an android.os.NetworkOnMainThreadException." - So some of us haven't hit this until recently! https://developer.android.com/about/versions/nougat/android-7.0-changes.html – Jay Nov 19 '17 at 22:51

64 Answers64

2673

NOTE : AsyncTask was deprecated in API level 30.
AsyncTask | Android Developers

This exception is thrown when an application attempts to perform a networking operation on its main thread. Run your code in AsyncTask:

class RetrieveFeedTask extends AsyncTask<String, Void, RSSFeed> {

    private Exception exception;

    protected RSSFeed doInBackground(String... urls) {
        try {
            URL url = new URL(urls[0]);
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            XMLReader xmlreader = parser.getXMLReader();
            RssHandler theRSSHandler = new RssHandler();
            xmlreader.setContentHandler(theRSSHandler);
            InputSource is = new InputSource(url.openStream());
            xmlreader.parse(is);

            return theRSSHandler.getFeed();
        } catch (Exception e) {
            this.exception = e;

            return null;
        } finally {
            is.close();
        }
    }

    protected void onPostExecute(RSSFeed feed) {
        // TODO: check this.exception
        // TODO: do something with the feed
    }
}

How to execute the task:

In MainActivity.java file you can add this line within your oncreate() method

new RetrieveFeedTask().execute(urlToRssFeed);

Don't forget to add this to AndroidManifest.xml file:

<uses-permission android:name="android.permission.INTERNET"/>
Shayan Shafiq
  • 1,447
  • 5
  • 18
  • 25
Michael Spector
  • 36,723
  • 6
  • 60
  • 88
770

You should almost always run network operations on a thread or as an asynchronous task.

But it is possible to remove this restriction and you override the default behavior, if you are willing to accept the consequences.

Add:

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();

StrictMode.setThreadPolicy(policy);

In your class,

and

Add this permission in the Android manifest.xml file:

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

Consequences:

Your app will (in areas of spotty Internet connection) become unresponsive and lock up, the user perceives slowness and has to do a force kill, and you risk the activity manager killing your app and telling the user that the app has stopped.

Android has some good tips on good programming practices to design for responsiveness: NetworkOnMainThreadException | Android Developers

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user1169115
  • 8,941
  • 1
  • 13
  • 2
  • 1
    Wow thanks for that explanation I now understand. I saw an app and it had implemented that ThreadPolicy in its java classes I was abit confused what it was doing. When network was low I was seeing the Consequence which you're talking about. – MosesK Jun 03 '21 at 09:30
518

I solved this problem using a new Thread.

Thread thread = new Thread(new Runnable() {
    
    @Override
    public void run() {
        try {
            // Your code goes here
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
});

thread.start(); 

        
Dmitriy Popov
  • 2,150
  • 3
  • 25
  • 34
Dr.Luiji
  • 6,081
  • 1
  • 15
  • 11
  • How woulod you pass paramaters to this? – Isiah Jun 03 '21 at 07:42
  • If you need to access the UI after the request, you need to return to the main thread at the end as explained [here](https://stackoverflow.com/a/5162096/4284627). – Donald Duck Aug 09 '21 at 10:43
193

The accepted answer has some significant downsides. It is not advisable to use AsyncTask for networking unless you really know what you are doing. Some of the down-sides include:

  • AsyncTask's created as non-static inner classes have an implicit reference to the enclosing Activity object, its context, and the entire View hierarchy created by that activity. This reference prevents the Activity from being garbage collected until the AsyncTask's background work completes. If the user's connection is slow, and/or the download is large, these short-term memory leaks can become a problem - for example, if the orientation changes several times (and you don't cancel the executing tasks), or the user navigates away from the Activity.
  • AsyncTask has different execution characteristics depending on the platform it executes on: prior to API level 4 AsyncTasks execute serially on a single background thread; from API level 4 through API level 10, AsyncTasks execute on a pool of up to 128 threads; from API level 11 onwards AsyncTask executes serially on a single background thread (unless you use the overloaded executeOnExecutor method and supply an alternative executor). Code that works fine when running serially on ICS may break when executed concurrently on Gingerbread, say if you have inadvertent order-of-execution dependencies.

If you want to avoid short-term memory leaks, have well-defined execution characteristics across all platforms, and have a base to build really robust network handling, you might want to consider:

  1. Using a library that does a nice job of this for you - there's a nice comparison of networking libs in this question, or
  2. Using a Service or IntentService instead, perhaps with a PendingIntent to return the result via the Activity's onActivityResult method.

IntentService approach

Downsides:

  • More code and complexity than AsyncTask, though not as much as you might think
  • Will queue requests and run them on a single background thread. You can easily control this by replacing IntentService with an equivalent Service implementation, perhaps like this one.
  • Um, I can't think of any others right now actually

Upsides:

  • Avoids the short-term memory leak problem
  • If your activity restarts while network operations are in-flight it can still receive the result of the download via its onActivityResult method
  • A better platform than AsyncTask to build and reuse robust networking code. Example: if you need to do an important upload, you could do it from AsyncTask in an Activity, but if the user context-switches out of the app to take a phone call, the system may kill the app before the upload completes. It is less likely to kill an application with an active Service.
  • If you use your own concurrent version of IntentService (like the one I linked above) you can control the level of concurrency via the Executor.

Implementation summary

You can implement an IntentService to perform downloads on a single background thread quite easily.

Step 1: Create an IntentService to perform the download. You can tell it what to download via Intent extras, and pass it a PendingIntent to use to return the result to the Activity:

import android.app.IntentService;
import android.app.PendingIntent;
import android.content.Intent;
import android.util.Log;

import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;

public class DownloadIntentService extends IntentService {

    private static final String TAG = DownloadIntentService.class.getSimpleName();

    public static final String PENDING_RESULT_EXTRA = "pending_result";
    public static final String URL_EXTRA = "url";
    public static final String RSS_RESULT_EXTRA = "url";

    public static final int RESULT_CODE = 0;
    public static final int INVALID_URL_CODE = 1;
    public static final int ERROR_CODE = 2;

    private IllustrativeRSSParser parser;

    public DownloadIntentService() {
        super(TAG);

        // make one and reuse, in the case where more than one intent is queued
        parser = new IllustrativeRSSParser();
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        PendingIntent reply = intent.getParcelableExtra(PENDING_RESULT_EXTRA);
        InputStream in = null;
        try {
            try {
                URL url = new URL(intent.getStringExtra(URL_EXTRA));
                IllustrativeRSS rss = parser.parse(in = url.openStream());

                Intent result = new Intent();
                result.putExtra(RSS_RESULT_EXTRA, rss);

                reply.send(this, RESULT_CODE, result);
            } catch (MalformedURLException exc) {
                reply.send(INVALID_URL_CODE);
            } catch (Exception exc) {
                // could do better by treating the different sax/xml exceptions individually
                reply.send(ERROR_CODE);
            }
        } catch (PendingIntent.CanceledException exc) {
            Log.i(TAG, "reply cancelled", exc);
        }
    }
}

Step 2: Register the service in the manifest:

<service
        android:name=".DownloadIntentService"
        android:exported="false"/>

Step 3: Invoke the service from the Activity, passing a PendingResult object which the Service will use to return the result:

PendingIntent pendingResult = createPendingResult(
    RSS_DOWNLOAD_REQUEST_CODE, new Intent(), 0);
Intent intent = new Intent(getApplicationContext(), DownloadIntentService.class);
intent.putExtra(DownloadIntentService.URL_EXTRA, URL);
intent.putExtra(DownloadIntentService.PENDING_RESULT_EXTRA, pendingResult);
startService(intent);

Step 4: Handle the result in onActivityResult:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == RSS_DOWNLOAD_REQUEST_CODE) {
        switch (resultCode) {
            case DownloadIntentService.INVALID_URL_CODE:
                handleInvalidURL();
                break;
            case DownloadIntentService.ERROR_CODE:
                handleError(data);
                break;
            case DownloadIntentService.RESULT_CODE:
                handleRSS(data);
                break;
        }
        handleRSS(data);
    }
    super.onActivityResult(requestCode, resultCode, data);
}

A GitHub project containing a complete working Android Studio/Gradle project is available here.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Stevie
  • 7,957
  • 3
  • 30
  • 29
152

You cannot perform network I/O on the UI thread on Honeycomb. Technically, it is possible on earlier versions of Android, but it is a really bad idea as it will cause your app to stop responding, and can result in the OS killing your app for being badly behaved. You'll need to run a background process or use AsyncTask to perform your network transaction on a background thread.

There is an article about Painless Threading on the Android developer site which is a good introduction to this, and it will provide you with a much better depth of an answer than can be realistically provided here.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Mark Allison
  • 21,839
  • 8
  • 47
  • 46
130

There are two solutions of this problem.

  1. Don't use a network call in the main UI thread. Use an async task for that.

  2. Write the below code into your MainActivity file after setContentView(R.layout.activity_main);:

    if (android.os.Build.VERSION.SDK_INT > 9) { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); }

And the below import statement into your Java file.

import android.os.StrictMode;
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dipak Keshariya
  • 22,193
  • 18
  • 76
  • 128
  • 14
    Following your second solution is a bad practice. Async is the way to do it *correctly*. You are like hiding your problem if you change the policy! – Richi González May 28 '13 at 07:47
96

Do the network actions on another thread.

For example:

new Thread(new Runnable() {
    @Override
    public void run() {
        // Do network action in this function
    }
}).start();

And add this to file AndroidManifest.xml:

<uses-permission android:name="android.permission.INTERNET"/>
Dmitriy Popov
  • 2,150
  • 3
  • 25
  • 34
henry4343
  • 3,871
  • 5
  • 22
  • 30
83
  1. Do not use strictMode (only in debug mode)
  2. Do not change SDK version
  3. Do not use a separate thread

Use Service or AsyncTask

See also Stack Overflow question:

android.os.NetworkOnMainThreadException sending an email from Android

Community
  • 1
  • 1
venergiac
  • 7,469
  • 2
  • 48
  • 70
  • 8
    Perhaps worth stressing the point that if you use a Service you will still need to create a separate thread - Service callbacks run on the main thread. An IntentService, on the other hand, runs its onHandleIntent method on a background thread. – Stevie Jan 22 '14 at 08:33
  • you should not use an AsyncTask for long running operations! Guidelines specify 2 to 3 seconds max. – Dage Feb 04 '14 at 10:41
75

You disable the strict mode using following code:

if (android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = 
        new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}

This is not recommended: use the AsyncTask interface.

Full code for both the methods

64

Network-based operations cannot be run on the main thread. You need to run all network-based tasks on a child thread or implement AsyncTask.

This is how you run a task in a child thread:

new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            // Your implementation goes here
        } 
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}).start();
Dmitriy Popov
  • 2,150
  • 3
  • 25
  • 34
Dhruv Jindal
  • 1,056
  • 10
  • 17
  • 1
    Anonymous Runnable is NOT the best way, since it has an implicit reference to the enclosing class and preventing it from being GC ed until the thread completes! Also this thread will run at the Same Priority as the main/US thread, contending with lifecycle methods and UI frame rates! – Yousha Aleayoub Mar 12 '16 at 13:18
  • @YoushaAleayoub so, what to use instead? – Sujith S Manjavana Jul 28 '22 at 16:25
53

Put your code inside:

new Thread(new Runnable() {
    @Override
    public void run() {
        try {
            // Your implementation
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}).start();

Or:

class DemoTask extends AsyncTask<Void, Void, Void> {

    protected Void doInBackground(Void... arg0) {
        // Your implementation
    }

    protected void onPostExecute(Void result) {
        // TODO: do something with the feed
    }
}
Dmitriy Popov
  • 2,150
  • 3
  • 25
  • 34
Vaishali Sutariya
  • 5,093
  • 30
  • 32
51

This happens in Android 3.0 and above. From Android 3.0 and above, they have restricted using network operations (functions that access the Internet) from running in the main thread/UI thread (what spawns from your on create and on resume methods in the activity).

This is to encourage using separate threads for network operations. See AsyncTask for more details on how to perform network activities the right way.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
raihan ahmed
  • 541
  • 4
  • 3
50

Using Android Annotations is an option. It will allow you to simply run any method in a background thread:

// normal method
private void normal() {
    doSomething(); // do something in background
}

@Background
protected void doSomething() 
    // run your networking code here
}

Note, that although it provides benefits of simplicity and readability, it has its disadvantages.

Oleksiy
  • 37,477
  • 22
  • 74
  • 122
  • 6
    @Gavriel it creates duplicates of everything you annotate, whether it's a method, activity, fragment, singleton etc, so there is twice as much code and it takes longer to compile it. It may also have some issues due to bugs in the library. Debugging and finding errors would become more difficult. – Oleksiy Aug 19 '15 at 01:30
46

The error is due to executing long running operations in main thread,You can easily rectify the problem by using AsynTask or Thread. You can checkout this library AsyncHTTPClient for better handling.

AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new AsyncHttpResponseHandler() {

    @Override
    public void onStart() {
        // Called before a request is started
    }

    @Override
    public void onSuccess(int statusCode, Header[] headers, byte[] response) {
        // Called when response HTTP status is "200 OK"
    }

    @Override
    public void onFailure(int statusCode, Header[] headers, byte[] errorResponse, Throwable e) {
        // Called when response HTTP status is "4XX" (for example, 401, 403, 404)
    }

    @Override
    public void onRetry(int retryNo) {
        // Called when request is retried
    }
});
Ashwin S Ashok
  • 3,623
  • 2
  • 29
  • 36
45

You should not do any time-consuming task on the main thread (UI thread), like any network operation, file I/O, or SQLite database operations. So for this kind of operation, you should create a worker thread, but the problem is that you can not directly perform any UI related operation from your worker thread. For that, you have to use Handler and pass the Message.

To simplify all these things, Android provides various ways, like AsyncTask, AsyncTaskLoader, CursorLoader or IntentService. So you can use any of these according to your requirements.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kapil Vats
  • 5,485
  • 1
  • 27
  • 30
44

The top answer of spektom works perfect.

If you are writing the AsyncTask inline and not extending as a class, and on top of this, if there is a need to get a response out of the AsyncTask, one can use the get() method as below.

RSSFeed feed = new RetreiveFeedTask().execute(urlToRssFeed).get();

(From his example.)

Community
  • 1
  • 1
sivag1
  • 4,734
  • 3
  • 32
  • 35
31

This is only thrown for applications targeting the Honeycomb SDK or higher. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads.

The error is the SDK warning!

General Grievance
  • 4,555
  • 31
  • 31
  • 45
perry
  • 856
  • 1
  • 10
  • 22
28

For me it was this:

<uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="10" />

The device I was testing my app on was 4.1.2 which is SDK Version 16!

Make the sure the target version is the same as your Android Target Library. If you are unsure what your target library is, right click your Project -> Build Path -> Android, and it should be the one that is ticked.

Also, as others have mentioned, include the correct permissions to access the Internet:

<uses-permission android:name="android.permission.INTERNET"/>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
rharvey
  • 1,987
  • 1
  • 28
  • 23
  • 11
    Let me explain you what you are doing here: `NetworkOnMainThreadException` is the Guardian which is telling you: do not shoot at your own foot ... your solution is: let's go back to the past when there was no Guardian - now i can shoot at my foot freely – Selvin Sep 17 '13 at 15:36
  • 1
    I took this approach, too, and didn't have any problems. Guardian is too fussy sometimes. – FractalBob Oct 25 '13 at 19:36
26

Use this in Your Activity

    btnsub.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    // TODO Auto-generated method stub

                    //Initialize soap request + add parameters
                    SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME1);

                    //Use this to add parameters
                    request.addProperty("pincode", txtpincode.getText().toString());
                    request.addProperty("bg", bloodgroup.getSelectedItem().toString());

                    //Declare the version of the SOAP request
                    SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);

                    envelope.setOutputSoapObject(request);
                    envelope.dotNet = true;

                    try {
                        HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);

                        //this is the actual part that will call the webservice
                        androidHttpTransport.call(SOAP_ACTION1, envelope);

                        // Get the SoapResult from the envelope body.
                        SoapObject result = (SoapObject) envelope.getResponse();
                        Log.e("result data", "data" + result);
                        SoapObject root = (SoapObject) result.getProperty(0);
                        // SoapObject s_deals = (SoapObject) root.getProperty(0);
                        // SoapObject s_deals_1 = (SoapObject) s_deals.getProperty(0);
                        //

                        System.out.println("********Count : " + root.getPropertyCount());

                        value = new ArrayList<Detailinfo>();

                        for (int i = 0; i < root.getPropertyCount(); i++) {
                            SoapObject s_deals = (SoapObject) root.getProperty(i);
                            Detailinfo info = new Detailinfo();

                            info.setFirstName(s_deals.getProperty("Firstname").toString());
                            info.setLastName(s_deals.getProperty("Lastname").toString());
                            info.setDOB(s_deals.getProperty("DOB").toString());
                            info.setGender(s_deals.getProperty("Gender").toString());
                            info.setAddress(s_deals.getProperty("Address").toString());
                            info.setCity(s_deals.getProperty("City").toString());
                            info.setState(s_deals.getProperty("State").toString());
                            info.setPinecode(s_deals.getProperty("Pinecode").toString());
                            info.setMobile(s_deals.getProperty("Mobile").toString());
                            info.setEmail(s_deals.getProperty("Email").toString());
                            info.setBloodgroup(s_deals.getProperty("Bloodgroup").toString());
                            info.setAdddate(s_deals.getProperty("Adddate").toString());
                            info.setWaight(s_deals.getProperty("waight").toString());
                            value.add(info);
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    Intent intent = new Intent(getApplicationContext(), ComposeMail.class);
                    //intent.putParcelableArrayListExtra("valuesList", value);

                    startActivity(intent);
                }
            }).start();
        }
    });
Catalina T.
  • 3,456
  • 19
  • 29
dhiraj kakran
  • 467
  • 2
  • 6
  • 19
24

Just to spell out something explicitly:

The main thread is basically the UI thread.

So saying that you cannot do networking operations in the main thread means you cannot do networking operations in the UI thread, which means you cannot do networking operations in a *runOnUiThread(new Runnable() { ... }* block inside some other thread, either.

(I just had a long head-scratching moment trying to figure out why I was getting that error somewhere other than my main thread. This was why; this thread helped; and hopefully this comment will help someone else.)

Novak
  • 4,687
  • 2
  • 26
  • 64
24

This exception occurs due to any heavy task performed on the main thread if that performing task takes too much time.

To avoid this, we can handle it using threads or executers

Executors.newSingleThreadExecutor().submit(new Runnable() {
    @Override
    public void run() {
        // You can perform your task here.
    }
});
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
amardeep
  • 492
  • 4
  • 19
21

There are many great answers already on this question, but a lot of great libraries have come out since those answers were posted. This is intended as a kind of newbie-guide.

I will cover several use cases for performing network operations and a solution or two for each.

REST over HTTP

Typically JSON, but it can be XML or something else.

Full API Access

Let's say you are writing an app that lets users track stock prices, interest rates and currency exchange rates. You find an JSON API that looks something like this:

http://api.example.com/stocks                       // ResponseWrapper<String> object containing a
                                                    // list of strings with ticker symbols
http://api.example.com/stocks/$symbol               // Stock object
http://api.example.com/stocks/$symbol/prices        // PriceHistory<Stock> object
http://api.example.com/currencies                   // ResponseWrapper<String> object containing a
                                                    // list of currency abbreviation
http://api.example.com/currencies/$currency         // Currency object
http://api.example.com/currencies/$id1/values/$id2  // PriceHistory<Currency> object comparing the prices
                                                    // of the first currency (id1) to the second (id2)

Retrofit from Square

This is an excellent choice for an API with multiple endpoints and allows you to declare the REST endpoints instead of having to code them individually as with other libraries like Amazon Ion Java or Volley (website: Retrofit).

How do you use it with the finances API?

File build.gradle

Add these lines to your module level build.gradle file:

implementation 'com.squareup.retrofit2:retrofit:2.3.0' // Retrofit library, current as of September 21, 2017
implementation 'com.squareup.retrofit2:converter-gson:2.3.0' // Gson serialization and deserialization support for retrofit, version must match retrofit version

File FinancesApi.java

public interface FinancesApi {
    @GET("stocks")
    Call<ResponseWrapper<String>> listStocks();
    @GET("stocks/{symbol}")
    Call<Stock> getStock(@Path("symbol")String tickerSymbol);
    @GET("stocks/{symbol}/prices")
    Call<PriceHistory<Stock>> getPriceHistory(@Path("symbol")String tickerSymbol);

    @GET("currencies")
    Call<ResponseWrapper<String>> listCurrencies();
    @GET("currencies/{symbol}")
    Call<Currency> getCurrency(@Path("symbol")String currencySymbol);
    @GET("currencies/{symbol}/values/{compare_symbol}")
    Call<PriceHistory<Currency>> getComparativeHistory(@Path("symbol")String currency, @Path("compare_symbol")String currencyToPriceAgainst);
}

Class FinancesApiBuilder

public class FinancesApiBuilder {
    public static FinancesApi build(String baseUrl){
        return new Retrofit.Builder()
                    .baseUrl(baseUrl)
                    .addConverterFactory(GsonConverterFactory.create())
                    .build()
                    .create(FinancesApi.class);
    }
}

Class FinancesFragment snippet

FinancesApi api = FinancesApiBuilder.build("http://api.example.com/"); //trailing '/' required for predictable behavior
api.getStock("INTC").enqueue(new Callback<Stock>(){
    @Override
    public void onResponse(Call<Stock> stockCall, Response<Stock> stockResponse){
        Stock stock = stockCall.body();
        // Do something with the stock
    }
    @Override
    public void onResponse(Call<Stock> stockCall, Throwable t){
        // Something bad happened
    }
}

If your API requires an API key or other header, like a user token, etc. to be sent, Retrofit makes this easy (see this awesome answer to Add Header Parameter in Retrofit for details).

One-off REST API access

Let's say you're building a "mood weather" app that looks up the user's GPS location and checks the current temperature in that area and tells them the mood. This type of app doesn't need to declare API endpoints; it just needs to be able to access one API endpoint.

Ion

This is a great library for this type of access.

Please read msysmilu's great answer to How can I fix 'android.os.NetworkOnMainThreadException'?.

Load images via HTTP

Volley

Volley can also be used for REST APIs, but due to the more complicated setup required, I prefer to use Retrofit from Square as above.

Let's say you are building a social networking app and want to load profile pictures of friends.

File build.gradle

Add this line to your module level build.gradle file:

implementation 'com.android.volley:volley:1.0.0'

File ImageFetch.java

Volley requires more setup than Retrofit. You will need to create a class like this to setup a RequestQueue, an ImageLoader and an ImageCache, but it's not too bad:

public class ImageFetch {
    private static ImageLoader imageLoader = null;
    private static RequestQueue imageQueue = null;

    public static ImageLoader getImageLoader(Context ctx){
        if(imageLoader == null){
            if(imageQueue == null){
                imageQueue = Volley.newRequestQueue(ctx.getApplicationContext());
            }
            imageLoader = new ImageLoader(imageQueue, new ImageLoader.ImageCache() {
                Map<String, Bitmap> cache = new HashMap<String, Bitmap>();
                @Override
                public Bitmap getBitmap(String url) {
                    return cache.get(url);
                }
                @Override
                public void putBitmap(String url, Bitmap bitmap) {
                    cache.put(url, bitmap);
                }
            });
        }
        return imageLoader;
    }
}

File user_view_dialog.xml

Add the following to your layout XML file to add an image:

<com.android.volley.toolbox.NetworkImageView
    android:id="@+id/profile_picture"
    android:layout_width="32dp"
    android:layout_height="32dp"
    android:layout_alignParentTop="true"
    android:layout_centerHorizontal="true"
    app:srcCompat="@android:drawable/spinner_background"/>

File UserViewDialog.java

Add the following code to the onCreate method (Fragment, Activity) or the constructor (Dialog):

NetworkImageView profilePicture = view.findViewById(R.id.profile_picture);
profilePicture.setImageUrl("http://example.com/users/images/profile.jpg", ImageFetch.getImageLoader(getContext());

Picasso

Picasso is another excellent library from Square. Please see the website for some great examples.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
KG6ZVP
  • 3,610
  • 4
  • 26
  • 45
16

In simple words,

Do not do network work in the UI thread

For example, if you do an HTTP request, that is a network action.

Solution:

  1. You have to create a new Thread
  2. Or use the AsyncTask class

Way:

Put all your works inside

  1. The run() method of the new thread
  2. Or the doInBackground() method of the AsyncTask class.

But:

When you get something from a network response and want to show it on your view (like display response message in TextView), you need to return back to the UI thread.

If you don't do it, you will get ViewRootImpl$CalledFromWrongThreadException.

How-to

  1. While using AsyncTask, update the view from the onPostExecute() method
  2. Or call the runOnUiThread() method and update the view inside the run() method.
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Nabin
  • 11,216
  • 8
  • 63
  • 98
14

You are able to move a part of your code into another thread to offload the main thread and avoid getting ANR, NetworkOnMainThreadException, IllegalStateException (e.g., cannot access database on the main thread since it may potentially lock the UI for a long period of time).

There are some approaches that you should choose depends on the situation

Java Thread or Android HandlerThread:

Java threads are one-time use only and die after executing its run method.

HandlerThread is a handy class for starting a new thread that has a looper.

AsyncTask (deprecated in API level 30)

AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask.

Since the main thread monopolizes UI components, it is not possible to access to some View, and that is why Handler comes to the rescue

[Executor framework]

ThreadPoolExecutor class that implements ExecutorService which gives fine control on the thread pool (E.g., core pool size, max pool size, keep alive time, etc.)

ScheduledThreadPoolExecutor - a class that extends ThreadPoolExecutor. It can schedule tasks after a given delay or periodically.

FutureTask

FutureTask performs asynchronous processing, however, if the result is not ready yet or processing has not complete, calling get() will be block the thread

AsyncTaskLoaders

AsyncTaskLoaders as they solve a lot of problems that are inherent to AsyncTask

IntentService

This is the de facto choice for long running processing on Android, a good example would be to upload or download large files. The upload and download may continue even if the user exits the app and you certainly do not want to block the user from being able to use the app while these tasks are going on.

JobScheduler

Effectively, you have to create a Service and create a job using JobInfo.Builder that specifies your criteria for when to run the service.

RxJava

Library for composing asynchronous and event-based programs by using observable sequences.

Coroutines (Kotlin)

The main gist of it is, it makes asynchronous code looks so much like synchronous

Read more here, here, here, and here.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
yoAlex5
  • 29,217
  • 8
  • 193
  • 205
14

Kotlin

If you are using Kotlin, you can use a coroutine:

fun doSomeNetworkStuff() {
    GlobalScope.launch(Dispatchers.IO) {
        // ...
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
El Sushiboi
  • 428
  • 7
  • 19
11

New Thread and AsyncTask solutions have been explained already.

AsyncTask should ideally be used for short operations. Normal Thread is not preferable for Android.

Have a look at alternate solution using HandlerThread and Handler

HandlerThread

Handy class for starting a new thread that has a looper. The looper can then be used to create handler classes. Note that start() must still be called.

Handler:

A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.

Solution:

  1. Create HandlerThread

  2. Call start() on HandlerThread

  3. Create Handler by getting Looper from HanlerThread

  4. Embed your Network operation related code in Runnable object

  5. Submit Runnable task to Handler

Sample code snippet, which address NetworkOnMainThreadException

HandlerThread handlerThread = new HandlerThread("URLConnection");
handlerThread.start();
handler mainHandler = new Handler(handlerThread.getLooper());

Runnable myRunnable = new Runnable() {
    @Override
    public void run() {
        try {
            Log.d("Ravi", "Before IO call");
            URL page = new URL("http://www.google.com");
            StringBuffer text = new StringBuffer();
            HttpURLConnection conn = (HttpURLConnection) page.openConnection();
            conn.connect();
            InputStreamReader in = new InputStreamReader((InputStream) conn.getContent());
            BufferedReader buff = new BufferedReader(in);
            String line;
            while ( (line =  buff.readLine()) != null) {
                text.append(line + "\n");
            }
            Log.d("Ravi", "After IO call");
            Log.d("Ravi",text.toString());

        } catch (Exception err) {
            err.printStackTrace();
        }
    }
};
mainHandler.post(myRunnable);

Pros of using this approach:

  1. Creating a new Thread/AsyncTask for each network operation is expensive. The Thread/AsyncTask will be destroyed and re-created for the next Network operations. But with Handler and HandlerThread approach, you can submit many network operations (as Runnable tasks) to single HandlerThread by using Handler.
Dmitriy Popov
  • 2,150
  • 3
  • 25
  • 34
Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
10

This works. I just made Dr.Luiji's answer a little simpler.

new Thread() {
    @Override
    public void run() {
        try {
            //Your code goes here
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}.start();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kacy
  • 3,330
  • 4
  • 29
  • 57
10

Although above there is a huge solution pool, no one mentioned com.koushikdutta.ion: https://github.com/koush/ion

It's also asynchronous and very simple to use:

Ion.with(context)
.load("http://example.com/thing.json")
.asJsonObject()
.setCallback(new FutureCallback<JsonObject>() {
   @Override
    public void onCompleted(Exception e, JsonObject result) {
        // do stuff with the result or error
    }
});
msysmilu
  • 2,015
  • 23
  • 24
9

The main thread is the UI thread, and you cannot do an operation in the main thread which may block the user interaction. You can solve this in two ways:

Force to do the task in the main thread like this

StrictMode.ThreadPolicy threadPolicy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(threadPolicy);

Or create a simple handler and update the main thread if you want.

Runnable runnable;
Handler newHandler;

newHandler = new Handler();
runnable = new Runnable() {
    @Override
    public void run() {
         try {
            //update UI
        } catch (Exception e) {
            e.printStackTrace();
        } 
    }
};
newHandler.post(runnable);

And to stop the thread use:

newHandler.removeCallbacks(runnable);

For more information check this out: Painless threading

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sharath kumar
  • 4,064
  • 1
  • 14
  • 20
8

There is another very convenient way for tackling this issue - use RxJava's concurrency capabilities. You can execute any task in the background and post results to the main thread in a very convenient way, so these results will be handed to the processing chain.

The first verified answer advice is to use AsynTask. Yes, this is a solution, but it is obsolete nowadays, because there are new tools around.

String getUrl() {
    return "SomeUrl";
}

private Object makeCallParseResponse(String url) {
    return null;
    //
}

private void processResponse(Object o) {

}

The getUrl method provides the URL address, and it will be executed on the main thread.

makeCallParseResponse(..) - does the actual work

processResponse(..) - will handle the result on the main thread.

The code for asynchronous execution will look like:

rx.Observable.defer(new Func0<rx.Observable<String>>() {
    @Override
    public rx.Observable<String> call() {
        return rx.Observable.just(getUrl());
    }
})
    .subscribeOn(Schedulers.io())
    .observeOn(Schedulers.io())
    .map(new Func1<String, Object>() {
        @Override
        public Object call(final String s) {
            return makeCallParseResponse(s);
        }
    })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Action1<Object>() {
        @Override
        public void call(Object o) {
             processResponse(o);
        }
    },
    new Action1<Throwable>() {
        @Override
        public void call(Throwable throwable) {
            // Process error here, it will be posted on
            // the main thread
        }
    });

Compared to AsyncTask, this method allows to switch schedulers an arbitrary number of times (say, fetch data on one scheduler and process those data on another (say, Scheduler.computation()). You can also define your own schedulers.

In order to use this library, include following lines into your build.gradle file:

   compile 'io.reactivex:rxjava:1.1.5'
   compile 'io.reactivex:rxandroid:1.2.0'

The last dependency includes support for the .mainThread() scheduler.

There is an excellent e-book for RxJava.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Alex Shutov
  • 3,217
  • 2
  • 13
  • 11
8

RxAndroid is another better alternative to this problem and it saves us from hassles of creating threads and then posting results on Android UI thread.

We just need to specify threads on which tasks need to be executed and everything is handled internally.

Observable<List<String>> musicShowsObservable = Observable.fromCallable(new Callable<List<String>>() {

  @Override
  public List<String> call() {
    return mRestClient.getFavoriteMusicShows();
  }

});

mMusicShowSubscription = musicShowsObservable
  .subscribeOn(Schedulers.io())
  .observeOn(AndroidSchedulers.mainThread())
  .subscribe(new Observer<List<String>>() {

    @Override
    public void onCompleted() { }

    @Override
    public void onError(Throwable e) { }

    @Override
    public void onNext(List<String> musicShows) {
        listMusicShows(musicShows);
    }
});
  1. By specifiying (Schedulers.io()), RxAndroid will run getFavoriteMusicShows() on a different thread.

  2. By using AndroidSchedulers.mainThread() we want to observe this Observable on the UI thread, i.e., we want our onNext() callback to be called on the UI thread.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Shinoo Goyal
  • 601
  • 8
  • 10
8

Android does not allow to run long-running operations on the main thread.

So just use a different thread and post the result to the main thread when needed.

new Thread(new Runnable() {
        @Override
        public void run() {
            /*
            // Run operation here
            */
            // After getting the result
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    // Post the result to the main thread
                }
            });
        }
    }).start();
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Sunny Gupta
  • 719
  • 8
  • 7
7

On Android, network operations cannot be run on the main thread. You can use Thread, AsyncTask (short-running tasks), Service (long-running tasks) to do network operations.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ponsuyambu
  • 7,876
  • 5
  • 27
  • 41
7

Accessing network resources from the main (UI) thread cause this exception. Use a separate thread or AsyncTask for accessing a network resource to avoid this problem.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
RevanthKrishnaKumar V.
  • 1,855
  • 1
  • 21
  • 34
6

You are not allowed to implement network operations on the UI thread on Android. You will have to use AsyncTask class to perform network-related operations like sending API requests, downloading an image from a URL, etc., and using callback methods of AsyncTask, you can get your result in onPostExecute method and you will be in the UI thread and you can populate UI with data from web service or something like that.

Example: Suppose you want to download an image from an URL: https://www.samplewebsite.com/sampleimage.jpg

Solution using AsyncTask: <String, Void, Bitmap> are <Params, Progress, Result> respectively.

    public class MyDownloader extends AsyncTask<String, Void, Bitmap>
    {
        @Override
        protected void onPreExecute() {
            // Show progress dialog
            super.onPreExecute();
        }

        @Override
        protected void onPostExecute(Bitmap bitmap) {
            //Populate Ui
            super.onPostExecute(bitmap);
        }

        @Override
        protected Bitmap doInBackground(String... params) {
            // Open URL connection read bitmaps and return form here
            return result;
        }

        @Override
        protected void onProgressUpdate(Void... values) {
            // Show progress update
            super.onProgressUpdate(values);
        }
    }
}

Note: Do not forget to add the Internet permission in the Android manifest file. It will work like a charm. :)

Dmitriy Popov
  • 2,150
  • 3
  • 25
  • 34
6

You can either use Kotlin and Anko.

Kotlin is a new official language for Android. You can find more about it here: Kotlin for Android.

Anko is a supported library for Kotlin in Android. Some documentation is on the GitHub page.

The solution which is really useful and has only a few lines of code written by @AntonioLeiva: Using Anko to run background tasks with Kotlin in Android (KAD 09).

doAsync {
    var result = runLongTask()
    uiThread {
        toast(result)
    }
}

Simple as it is, NetworkOnMainThread occurs when you run a background job on the UI thread, so one thing you have to do is to run your longTask job in the background. You can do this using this method and Kotlin with Anko in your Android app.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
J.D.1731
  • 385
  • 3
  • 14
  • 2
    From the GitHub page: *"Anko is deprecated. Please see [this page](https://github.com/Kotlin/anko/blob/master/GOODBYE.md) for more information."* – Peter Mortensen Jul 22 '21 at 18:01
6

Google deprecated the Android AsyncTask API in Android 11.

Even if you create a thread class outside the main activity, just by calling it in main, you will get the same error. The calls must be inside a runnable thread, but if you need some asynchronous code to execute in the background or some on post afterwards here, you can check out some alternatives for both Kotlin and Java:

*https://stackoverflow.com/questions/58767733/android-asynctask-api-deprecating-in-android-11-what-are-the-alternatives*

The one that worked for me specifically was an answer by mayank1513 for a Java 8 implementation of a runnable thread found on the above link. The code is as follows:

new Thread(() -> {
    // do background stuff here
    runOnUiThread(() -> {
        // OnPostExecute stuff here
    });
}).start();

However, you can define the thread first in some part of your code and start it somewhere else like this:

Thread definition

Thread thread = new Thread(() -> {
    // do background stuff here
    runOnUiThread(() -> {
        // OnPostExecute stuff here
    });
});

Thread call

thread.start();

I hope this saves someone the headache of seeing the deprecated AsyncTask.

Dmitriy Popov
  • 2,150
  • 3
  • 25
  • 34
Shay Ribera
  • 359
  • 4
  • 18
5

This exception is thrown when an application attempts to perform a networking operation on its main thread. If your task took above five seconds, it takes a force close.

Run your code in AsyncTask:

class RetrieveFeedTask extends AsyncTask<String, Void, Boolean> {

    protected RSSFeed doInBackground(String... urls) {
       // TODO: Connect
    }

    protected void onPostExecute(RSSFeed feed) {
        // TODO: Check this.exception
        // TODO: Do something with the feed
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Adnan Abdollah Zaki
  • 4,328
  • 6
  • 52
  • 58
5

We can also use RxJava to move network operations to a background thread. And it's fairly simple as well.

webService.doSomething(someData)
          .subscribeOn(Schedulers.newThread())-- This for background thread
          .observeOn(AndroidSchedulers.mainThread()) -- for callback on UI
          .subscribe(result -> resultText.setText("It worked!"),
              e -> handleError(e));

You can do a lot more stuff with RxJava. Here are some links for RxJava. Feel free to dig in.

RxJava async task in Android

http://blog.stablekernel.com/replace-asynctask-asynctaskloader-rx-observable-rxjava-android-patterns/

bpr10
  • 1,086
  • 8
  • 14
5

You can also resolve this issue by using Strict Mode using the below code. It's also an alternative to resolving this issue.

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

But the best practice would be to use AsyncTask.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Himanshu
  • 117
  • 2
  • 5
5

On Android, network operations cannot be run on the main thread. You can use Thread, AsyncTask (short-running tasks), Service (long-running tasks) to do network operations. android.os.NetworkOnMainThreadException is thrown when an application attempts to perform a networking operation on its main thread. If your task took above five seconds, it takes a force close.

Run your code in AsyncTask:

class FeedTask extends AsyncTask<String, Void, Boolean> {

    protected RSSFeed doInBackground(String... urls) {
       // TODO: Connect
    }

    protected void onPostExecute(RSSFeed feed) {
        // TODO: Check this.exception
        // TODO: Do something with the feed
    }
}

Or

new Thread(new Runnable(){
    @Override
    public void run() {
        try {
            // Your implementation
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}).start();

This is not recommended.

But for debugging purposes, you can disable the strict mode as well using the following code:

if (android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy =
        new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rahul
  • 3,293
  • 2
  • 31
  • 43
4

How to fix android.os.NetworkOnMainThreadException

What is NetworkOnMainThreadException:

In Android all the UI operations we have to do on the UI thread (main thread). If we perform background operations or some network operation on the main thread then we risk this exception will occur and the app will not respond.

How to fix it:

To avoid this problem, you have to use another thread for background operations or network operations, like using asyncTask and use some library for network operations like Volley, AsyncHttp, etc.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Lovekush Vishwakarma
  • 3,035
  • 23
  • 25
4

android.os.NetworkOnMainThreadException is thrown when network operations are performed on the main thread. You better do this in AsyncTask to remove this Exception. Write it this way:

    new AsyncTask<Void, String, String>() {

        @Override
        protected Void doInBackground(Void... params) {
            // Perform your network operation.
            // Get JSON or XML string from the server.
            // Store in a local variable (say response) and return.
            return response;
        }

        protected void onPostExecute(String results) {
            // Response returned by doInBackGround() will be received
            // by onPostExecute(String results).
            // Now manipulate your jason/xml String(results).
        }

    }.execute();
}
Dmitriy Popov
  • 2,150
  • 3
  • 25
  • 34
Mansuu....
  • 1,206
  • 14
  • 27
4

Do this in Background Thread using AsycTask

Java

class NetworkThread extends AsyncTask<String, Void, String> {

    protected Void doInBackground(String... arg0) {
        //Your implementation
    }

    protected void onPostExecute(String result) {
        // TODO: do something with the feed
    }
}

Call wherever you need

new NetworkThread().execute("Your URL here");

Kotlin

internal class MyNetworkTask : AsyncTask<String, Void, RSSFeed>() {

    override fun doInBackground(vararg urls: String): RSSFeed? {
        try {
             // download
             // prepare RSSFeeds
             return RSSFeeds
         } catch (e: Exception) {
            //handle exception
            return null
        }
    }

    override fun onPostExecute(feed: RSSFeed) {
        // TODO: check this.exception
        // TODO: do something with the feed
    }
}

Call in kotlin

MyNetworkTask().execute(url)
Vipul Prajapati
  • 1,183
  • 9
  • 11
3

I solved this problem in a simple way...

I added after oncreate StrictMode.enableDefaults(); and solved this.

Or

use Service or AsyncTask to solve this

Note:

Do not change SDK version
Do not use a separate thread

For more, check this.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Subhalaxmi
  • 5,687
  • 3
  • 26
  • 42
3

I had a similar problem. I just used the following in the oncreate method of your activity.

// Allow strict mode
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);

And it worked well.

The caveat is that using this for a network request that takes more than 100 milliseconds will cause noticeable UI freeze and potentially ANRs (Application Not Responding), so keep that in mind.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Richard Kamere
  • 749
  • 12
  • 10
  • 1
    @RichardKamere from the official documentation for `StrictMode` you can check that 'StrictMode is a developer tool which detects things you might be doing by accident and brings them to your attention so you can fix them' and 'you should never leave StrictMode enabled in applications distributed on Google Play.' [Check Here](https://developer.android.com/reference/android/os/StrictMode.html) – Shubham Suryavanshi Sep 13 '19 at 07:41
  • 1
    This will help for testing purposes but cannot be considered as solution, use an asynctask instead. – Jorgesys Oct 28 '19 at 21:04
  • @Zun what if i want ot check internet connection on API server? – shareef Mar 10 '20 at 08:42
3

From developer-android:

AsyncTasks should ideally be used for short operations (a few seconds at the most.)

Using newCachedThreadPool is the good one. also you can consider other options like newSingleThreadExecutor, newFixedThreadPool

    ExecutorService myExecutor = Executors.newCachedThreadPool();
    myExecutor.execute(new Runnable() {
        @Override
        public void run() {
            URL url = new URL(urls[0]);
            SAXParserFactory factory = SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            XMLReader xmlreader = parser.getXMLReader();
            RssHandler theRSSHandler = new RssHandler();
            xmlreader.setContentHandler(theRSSHandler);
            InputSource is = new InputSource(url.openStream());
            xmlreader.parse(is);
        }
    });

ThreadPoolExecutor is a helper class to make this process easier. This class manages the creation of a group of threads, sets their priorities, and manages how work is distributed among those threads. As workload increases or decreases, the class spins up or destroys more threads to adjust to the workload.

See this for more information about Android threads.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
majurageerthan
  • 2,169
  • 3
  • 17
  • 30
2

As Android is working on a single thread, you should not do any network operation on the main thread. There are various ways to avoid this.

Use the following way to perform a network operation

  • Asysnctask: For small operations which don't take much time.
  • Intent Service: For network operation which take a big amount of time.
  • Use a custom library like Volley and Retrofit for handling complex network operations

Never use StrictMode.setThreadPolicy(policy), as it will freeze your UI and is not at all a good idea.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
aks
  • 83
  • 9
2

You can not call network on the main thread or UI thread. On Android if you want to call network there are two options -

  1. Call asynctask, which will run one background thread to handle the network operation.
  2. You can create your own runnable thread to handle the network operation.

Personally I prefer asynctask. For further information you can refer this link.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Hossain Ahamed
  • 119
  • 1
  • 7
2

You can use Kotlin coroutines:

 class YoutActivity : AppCompatActivity, CoroutineScope {
      
      override fun onCreate(...) {
         launch {  yourHeavyMethod() }
      }

      suspend fun yourHeavyMethod() {
         with(Dispatchers.IO){ yourNetworkCall() }
         ...
         ...
      }
 } 

You can follow this guide.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Santanu Sur
  • 10,997
  • 7
  • 33
  • 52
1

The NetworkOnMainThread exception occurs because you have called some network operation on the default thread, that is, the UI thread. As per Android version Android 3 (Honeycomb) which is not allowed, you should call network operation outside the main thread.

You can use AsyncTask, IntentService, or creating your own thread and calling inside the run method. For more information, visit Connecting to the Network.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
BalaramNayak
  • 1,295
  • 13
  • 16
1

If you are working in Kotlin and Anko you can add:

doAsync {
    method()
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Devix
  • 432
  • 5
  • 16
1

These answers need to be updated to use more contemporary way to connect to servers on the Internet and to process asynchronous tasks in general.

For example, you can find examples where Tasks are used in a Google Drive API sample. The same should be used in this case. I'll use the OP's original code to demonstrate this approach.

First, you'll need to define an off-main thread executor and you need to do it only once:

private val mExecutor: Executor = Executors.newSingleThreadExecutor()

Then process your logic in that executor, which will be running off main thread

Tasks.call (mExecutor, Callable<String> {

        val url = URL(urlToRssFeed)
        val factory = SAXParserFactory.newInstance()
        val parser = factory.newSAXParser()
        val xmlreader = parser.getXMLReader()
        val theRSSHandler = RssHandler()
        xmlreader.setContentHandler(theRSSHandler)
        val is = InputSource(url.openStream())
        xmlreader.parse(is)
        theRSSHandler.getFeed()

        // Complete processing and return a String or other object.
        // E.g., you could return Boolean indicating a success or failure.
        return@Callable someResult
}).continueWith{
    // it.result here is what your asynchronous task has returned
    processResult(it.result)
}

continueWith clause will be executed after your asynchronous task is completed and you will have an access to a value that has been returned by the task through it.result.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Oleg Gryb
  • 5,122
  • 1
  • 28
  • 40
1

I solved using Thread in Kotlin. There are many examples using Java, so I wanted to add a solution that worked for me in Kotlin.

 Thread {
     println("NEW THREAD")
     callAPI() // add your own task
 }.start()

So, as many others greatly explained, you cannot block the main thread with you call, so it is necessary to create a new thread.

programandoconro
  • 2,378
  • 2
  • 18
  • 33
0

You can actually start a new Thread. I had this problem before and solved it by this way.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
RobotCharlie
  • 1,180
  • 15
  • 19
0

Kotlin version

internal class RetrieveFeedTask : AsyncTask<String, Void, RSSFeed>() {

    override fun doInBackground(vararg urls: String): RSSFeed? {

        try {
             // download
             // prepare RSSFeeds
             return RSSFeeds

         } catch (e: Exception) {

            //handle exception
            return null
        }
    }

    override fun onPostExecute(feed: RSSFeed) {
        // TODO: check this.exception
        // TODO: do something with the feed
    }
}

Call example,

RetrieveFeedTask().execute(url)
Community
  • 1
  • 1
Sazzad Hissain Khan
  • 37,929
  • 33
  • 189
  • 256
0

Here's a simple solution using OkHttp, Future, ExecutorService and Callable:

final OkHttpClient httpClient = new OkHttpClient();
final ExecutorService executor = newFixedThreadPool(3);

final Request request = new Request.Builder().url("http://example.com").build();

Response response = executor.submit(new Callable<Response>() {
   public Response call() throws IOException {
      return httpClient.newCall(request).execute();
   }
}).get();
neu242
  • 15,796
  • 20
  • 79
  • 114
  • Getting error : System.err: java.util.concurrent.ExecutionException: javax.net.ssl.SSLException: Unable to parse TLS packet header – Arpan Saini Feb 06 '21 at 11:54
  • @ArpanSaini Does your exact URL work with curl or in a browser? Maybe switch from https to http (or vice versa) and see if it works? – neu242 Feb 08 '21 at 10:48
0

I converted the network access function returning a value into a suspend function like so:


suspend fun isInternetReachable(): Boolean {
  ...
  ...
  return result
}

Then I modified where I was using the function to fit into this:

...
Globalscope.async{
  ...
  result = isInternetReachable()
  ...
}
...
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
nyxee
  • 2,773
  • 26
  • 22
-1

As of 2018, I would recommend to use RxJava in Kotlin for network fetching. A simple example is below.

Single.fromCallable {
        // Your Network Fetching Code
        Network.fetchHttp(url) 
    }
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe {
        // What you need to do with your result on the view 
        result -> view.updateScreen(result) 
    }
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Elye
  • 53,639
  • 54
  • 212
  • 474
  • You could find the complete code from https://github.com/elye/demo_android_network_evolution – Elye Jan 17 '18 at 21:56
  • If you like to look at the overall trend of network access in Android historically to present, check out https://medium.com/@elye.project/the-evolution-of-android-network-access-1e199fc6e9a2 – Elye Jan 17 '18 at 21:56
-1

Different options:

  1. Use a normal Java runnable thread to process the network task and one can use runOnUIThread() to update the UI

  2. intentservice/ async task can be used in case you want to update the UI after getting a network response

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ashok Kumar
  • 1,226
  • 1
  • 10
  • 14
-2
Executors.newFixedThreadPool(3).execute(() -> {
      //DO Task;        
 });
-3

Use the below code to perform heavy tasks.

// Your package here


import java.util.List;
import org.apache.http.NameValuePair;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.os.AsyncTask;
import android.view.View.OnSystemUiVisibilityChangeListener;

public class AsyncRequest extends AsyncTask<String, Integer, String> {

    Context context;
    ProgressDialog pDialog;

    // Three Constructors
    public AsyncRequest(Activity a, String m, List<NameValuePair> p) {
        context = a;
        method = m;
        parameters = p;
    }

    public AsyncRequest(Activity a) {
        this.caller = (OnAsyncRequestComplete) a;
        context = a;
    }

    public String doInBackground(String... urls) {

        //Perform your task here
        return result;
    }

    public void onPreExecute() {
        pDialog = new ProgressDialog(context);
        pDialog.setMessage("Please wait..");
        pDialog.setCancelable(false);
        pDialog.show();
    }

    public void onProgressUpdate(Integer... progress) {
        // You can implement some progressBar and update it in this record.
        //   setProgressPercent(progress[0]);
    }

    public void onPostExecute(String response) {
        if (pDialog != null && pDialog.isShowing()) {
            pDialog.dismiss();
        }
        // Get the result here
    }

    protected void onCancelled(String response) {

        if (pDialog != null && pDialog.isShowing()) {
            pDialog.dismiss();
        }
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Gurpreet singh
  • 123
  • 2
  • 11
-3

You have to simply add the following line in file manifest.xml after the manifest tag

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

And in the activity file, add the following code after the binding statement:

if (android.os.Build.VERSION.SDK_INT > 9) {
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
prat3ik-patel
  • 1,205
  • 9
  • 5
  • 2
    Bypassing the detection of network code on the UI thread is really bad advice, there is a reason it's there to begin with. – ci_ Mar 20 '15 at 10:00
  • Don't understand the hate on this answer, even if not usually optimal. Good to have options – netsplit Oct 13 '21 at 02:43
-5

Android does not allow a separate process into the main activity thread, and the HTTP connection is an independent thread here. That is the reason you are getting the "android.os.NetworkOnMainThreadException".

There can be a need where you want to check the actual Internet connection before showing webview to the user, because if there is not Internet the web view will show the page not found error to the user, which normally you don't what to show.

For checking Internet availability, the ping command can be used, but in case of Wi-Fi pinging can be disabled at the Wi-Fi server, so in this case you use an HTTP connection to check the status of the request.

This can be the right approach if you are checking your own webview URL link before showing a webview to the user. In this case, you can use the strict mode of Android, but don't permit all the policy because you don't need it.

You should only give network allow policy for the strict mode. Just add the below line into your code, and you will not get this error.

StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitNetwork().build();
StrictMode.setThreadPolicy(policy);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Kumarsunil
  • 151
  • 2
  • 7