Reputation: 2317
I have the following peace of code containing network operations. Where I get the well known error Error in http connectionandroid.os.NetworkOnMainThreadException
which is pretty descriptive and explained for example here.
What I don't understand is, how can the error occur here when I clearly subscribe on Scheduler.io()
. What do I do wrong?
ReactiveLocationProvider locationProvider = new ReactiveLocationProvider(mContext);
locationProvider.getLastKnownLocation().subscribeOn(Schedulers.io()).subscribe((location -> {
// ... unrelated code
try {
this.postPing(pingResponse); // <<< this is an http post causing the error
Log.d(LOG_TAG, "trying to post response");
} catch (Exception e) {
e.printStackTrace();
}
cursor.close();
Edit: This does not seem to be entirely trivial. That's why I provide additional context.
The code above used to look like this and didn't use ReactiveLocationProvider
, but rather the FusedLocationApi
Location location = LocationServices.FusedLocationApi.getLastLocation(MainActivity.mGoogleApiClient);
// ... unrelated code
try {
this.postPing(pingResponse);
Log.d(LOG_TAG, "trying to post response");
} catch (Exception e) {
e.printStackTrace();
}
cursor.close();
And was run from within a GcmListenerService:
@Override
public void onMessageReceived(String from, Bundle data) {
Log.d("GCMListener", "onMessageReceived");
String action = data.getString("action");
switch (action) {
case "getPing":
requests.getPingObservable()
.subscribeOn(Schedulers.io()).retryWhen(
errors ->
errors
.zipWith(Observable.range(1, 3), (n, i) -> i)
.flatMap(retryCount -> Observable.timer((long) Math.pow(5, retryCount), TimeUnit.SECONDS))
).subscribe((pingsJsonObjectString) -> {
}, (error) -> error.printStackTrace());
break;
default:
break;
}
}
Unfortunately the GcmListenerService doesn't receive notifications when the app is closed. So I decided to cheat a bit and create an alarm to trigger the reciever with an alarm.
In The AndroidMainfest.xml
I added the line <category android:name="com.smilingkoala.ping.periodic_wakeup"/>
<!-- The Google Cloud Messaging receiver and services -->
<receiver
android:name="com.google.android.gms.gcm.GcmReceiver"
android:exported="true"
android:permission="com.google.android.c2dm.permission.SEND">
<intent-filter>
<action android:name="com.google.android.c2dm.intent.RECEIVE" />
<action android:name="com.google.android.c2dm.intent.REGISTRATION" />
<category android:name="com.smilingkoala.ping" />
<category android:name="com.smilingkoala.ping.periodic_wakeup"/>
</intent-filter>
</receiver>
and in MainActivity.java
I called:
public void startAlarm(Context context) {
Intent intent = new Intent("com.smilingkoala.ping.periodic_wakeup");
PendingIntent sender = PendingIntent.getService(context, 0, intent, 0);
AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP,
AlarmManager.INTERVAL_FIFTEEN_MINUTES / 3, AlarmManager.INTERVAL_FIFTEEN_MINUTES, sender);
}
To restart the listener once the application is closed.
This actually worked. I received a message. But now I didn't have access to MainActivity.mGoogleApiClient
which I used in the old code. That's why I was forced to use ReactiveLocationProvider
. However now i can't run the networking code.
I assume something I did leading up to this Error is forbidden.
Upvotes: 1
Views: 179
Reputation: 821
Ok, I am not 100% sure, but let's try to explain this (:
If you read documentation on .subscribeOn
operator, you'll see that it defines scheduler on which Observable itself (not the Subscriber!) will be executed. You need to explicitly define scheduler for subscriber with .observeOn
operator, or it will be executed on thread where it was subscribed on.
For more detailed information and examples you should check these links: http://www.grahamlea.com/2014/07/rxjava-threading-examples/ http://www.introtorx.com/Content/v1.0.10621.0/15_SchedulingAndThreading.html#SubscribeOnObserveOn
Also you can debug and experiment with threading by calling Thread.currentThread()
to check where is your code executing.
Upvotes: 2