Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

android.os.NetworkOnMainThreadException using rxjava on android

i'm having trouble implementing rxJava in order to check if there is internet connection on android i'm doing it like this:

on my launcher activity i have this in onCreate:

AndroidObservable.bindActivity(this,
            Observable.just(Utils.isActiveInternetConnection(Launcher.this)))
            .subscribeOn(Schedulers.newThread())
            .subscribe(new Action1<Boolean>() {
                @Override
                public void call(Boolean aBoolean) {
                    if (aBoolean) {
                        Toast.makeText(Launcher.this, "There is internet connection", Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(Launcher.this, "There is no internet connection", Toast.LENGTH_SHORT).show();
                    }
                }
            });

i have an Utils class it is a final class with static methods the methods in that the observable is using are this ones:

    public static boolean isActiveInternetConnection(Context context) {
    if (isNetworkAvailable(context)) {
        try {
            HttpURLConnection urlc = (HttpURLConnection) (new URL("http://www.google.com").openConnection());
            urlc.setRequestProperty("User-Agent", "Test");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(1500);
            urlc.connect();
            return (urlc.getResponseCode() == 200);
        } catch (IOException e) {
            Log.e("network", "Error checking internet connection", e);
        }
    } else {
        Log.d("network", "No network available!");
    }
    return false;
}

private static boolean isNetworkAvailable(Context context){
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    if (null != activeNetwork) {
        return true;
    }
    else {
        return false;
    }
}

i'm receiving android.os.NetworkOnMainThreadException and i can't find why, thanks in advance.

like image 473
Baniares Avatar asked Dec 29 '14 11:12

Baniares


2 Answers

Observable.just(...) is called immediately on the calling thread (the main thread, in this case). Your code is effectively just an inlined version of this:

boolean activeConn = Utils.isActiveInternetConnection(Launcher.this);
AndroidObservable.bindActivity(this, 
        Observable.just(activeConn))
        .subscribeOn(...)
        ...

You've tried to move it off the main thread by calling subscribeOn() - but the call has already happened.

The way we handle this (and I'm not sure that this is the best way, but it works) is to defer the network or blocking call until subscription happens, set up the observable to run on the correct threads, and then subscribe:

AndroidObservable.bindActivity(this,
        Observable.defer(new Func0<Boolean>() {
            @Override
            public Observable<Observable<Boolean>> call() {
                return Observable.just(Utils.isActiveInternetConnection(Launcher.this));
            }
        })
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Action1<Boolean>() {
            @Override
            public void call(Boolean aBoolean) {
                if (aBoolean) {
                    Toast.makeText(Launcher.this, "There is internet connection", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(Launcher.this, "There is no internet connection", Toast.LENGTH_SHORT).show();
                }
            }
        });
like image 53
Adam S Avatar answered Sep 30 '22 22:09

Adam S


I guess just just calls the method synchronously as it expects the boolean value and it tries to get it.

I am rather bad at RxJava but you may try something like this:

Observable<Boolean> onlineObservable = Observable.create(new Observable.OnSubscribe<Boolean>() {
    @Override
    public void call(Subscriber subscriber) {
        subscriber.onNext(Utils.isActiveInternetConnection(context));
    }
});
onlineObservable.subscribeOn(Schedulers.newThread()).subscribe(result -> {...});
like image 28
cliffroot Avatar answered Sep 30 '22 22:09

cliffroot