I am making network calls from an IntentService but still receiving a NetworkOnMainThreadException. My understanding is that an IntentService always runs on a worker thread, so I'm suprised to see this. The crucial piece may be that my IntentService is calling a static helper class that performs the network calls. The static helper class is instantiated in my main Application class.
I thought this would still execute on the worker thread of the IntentService. What am I missing?
Honestly I prefer heady informative discussions over a quick code fix. But if code is required, code shall be provided:
//MyApplication.java
public class MyApplication extends Application{
private static NetworkUtils utils;
@Override
public void onCreate() {
super.onCreate();
utils = new NetworkUtils(this);
...
}
...
}
//NetworkUtils.java
public class NetworkUtils {
private static Context context;
private static final Gson gson = new Gson();
public NetworkUtils(Context context) {
this.context = context;
}
public static final DataResponse login(String email, String password) {
//*** NetworkOnMainThreadException OCCURS HERE ***
DataResponse response = HttpConnection.put(url, json);
...
return response;
}
...
}
//LoginService.java
public class LoginService extends IntentService {
public LoginService() {
super("LoginService");
}
@Override
public void onStart(Intent intent, int startId) {
onHandleIntent(intent);
}
@Override
protected void onHandleIntent(Intent intent) {
Bundle bundle = new Bundle();
DataResponse response = NetworkUtils.login(email, password);
...
bundle.putBoolean(MyConstants.ExtraKeys.LOGGED, response.success);
MainApplication.getApplicationInstance().sendBroadCast(MyConstants.Actions.LOGIN, bundle);
}
}
//LoginActivity.java
public class LoginActivity extends ActionBarActivity implements IDialogClickListener {
...
public void onLoginButtonPressed() {
Intent intent = new Intent(MainApplication.getApplicationInstance(), LoginService.class);
this.startService(intent);
}
}
Also, Logcat:
> 04-01 18:20:41.048: VERBOSE/com.foo.foo(28942):
> com.foo.foo.network.HttpConnection.execute - METHOD: PUT
> 04-01 18:20:41.068: ERROR/com.foo.foo(28942):
> com.foo.foo.social.NetworkUtils.login - class
> android.os.NetworkOnMainThreadException: null
> 04-01 18:20:41.169: DEBUG/com.foo.foo(28942):
> com.foo.foo.MainActivity$MyReceiver.onReceive - BROADCAST RECEIVED:
> com.foo.foo.MainApplication@422d81d8 - Intent { act=com.foo.foo.login
> dat=com.foo.foo.scheme://data/1364854841079 (has extras) }
> 04-01 18:20:41.169: INFO/com.foo.foo(28942):
> com.foo.foo.activity.LoginActivity.setData - ACTION: com.foo.foo.login
> - ISERROR: true
SOLUTION
The underlying issue was a bit of legacy code that was calling onHandleIntent
explicitly. In LoginService.java above:
@Override
public void onStart(Intent intent, int startId) {
onHandleIntent(intent);
}
This is causing the onHandleIntent code to run on the main thread, as it is being called from the onStart event (which apparently runs on main thread).
I have spotted the issue. Check out this baffling override in LoginService.java above:
@Override
public void onStart(Intent intent, int startId) {
onHandleIntent(intent);
}
This is causing the onHandleIntent
code to run on the main thread, as it is being called from the onStart event (which apparently runs on main thread). I would love to read the mind of the developer who put that in!
Your suspicions are correct. You're instantiating the NetworkUtils class from your application class. That's not going to run in a background thread no matter how you call it.
Strictly speaking, it's a class that contains static variables. I strongly suggest you avoid static variables. Instead, use the Android API to persist state in objects such as SharedPreferences or Bundles.
The Android object environment is transitory by design. Instead of persisting state in memory, persist it in objects and constructs that are specifically designed for it, such as Bundles and SharedPreferences. You'll be much happier. Try anything else, and you'll end up trying to squeeze a large mass of worms back into a very small can.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With