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.