Hammad Nasir
Hammad Nasir

Reputation: 2959

Getting 'android.os.NetworkOnMainThreadException' while performing GraphRequest.executeAndWait() in doInBackground() of AsyncTask

I'm using Facebook GraphAPI and I'm trying to load results from next page using GraphRequest.executeAndWait() as demonstrated here, but the app is crashing giving android.os.NetworkOnMainThreadException.

Here's my code:

    class RetrieveF extends AsyncTask<Void, Integer, String> {

            GraphRequest request;

            protected String doInBackground(Void...args0) {
                new GraphRequest(
                        AccessToken.getCurrentAccessToken(), "/me/friends", null, HttpMethod.GET,
                        new GraphRequest.Callback() {
                            public void onCompleted(GraphResponse response) {
                                JSONObject innerJson = response.getJSONObject();
                                try {
                                    JSONArray data = innerJson.getJSONArray("data");
                                    for (int i = 0; i<data.length(); i++){

                                        String id = data.getJSONObject(i).getString("id");

                                        request = new GraphRequest(AccessToken.getCurrentAccessToken(), id+"/feed", null, HttpMethod.GET,
                                                new GraphRequest.Callback() {
                                                    @Override
                                                    public void onCompleted(GraphResponse response) {

                                                        JSONObject innerJson = response.getJSONObject();
                                                        try {
                                                            JSONArray data = innerJson.getJSONArray("data");
                                                            for (int i = 0; i<data.length(); i++) {
                                                                JSONObject obj = data.getJSONObject(i);}
                                                        } catch (JSONException e) {
                                                            Log.d("innerFacebookException", e.getMessage());
                                                        }

                                                        GraphRequest nextResultsRequests = response.getRequestForPagedResults(GraphResponse.PagingDirection.NEXT);
                                                        if (nextResultsRequests != null) {
                                                            nextResultsRequests.setCallback(request.getCallback());
                                                            // error on this line
                                                            response = nextResultsRequests.executeAndWait();
                                                            //
                                                        }
                                                    }
                                                }
                                        );
                                        request.executeAsync();
                                    }
                                } catch (JSONException e) {
                                    Log.d("facebookException", e.getMessage());
                                }
                            }
                        }
                ).executeAsync();
                return "success";
            }

            @Override
            protected void onPostExecute(String s) {
                super.onPostExecute(s);
            }
        }

Here's the stacktrace:

android.os.NetworkOnMainThreadException
                                                                       at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1273)
                                                                       at com.android.org.conscrypt.OpenSSLSocketImpl.shutdownAndFreeSslNative(OpenSSLSocketImpl.java:1131)
                                                                       at com.android.org.conscrypt.OpenSSLSocketImpl.close(OpenSSLSocketImpl.java:1126)
                                                                       at com.android.okhttp.Connection.closeIfOwnedBy(Connection.java:132)
                                                                       at com.android.okhttp.OkHttpClient$1.closeIfOwnedBy(OkHttpClient.java:75)
                                                                       at com.android.okhttp.internal.http.HttpConnection.closeIfOwnedBy(HttpConnection.java:137)
                                                                       at com.android.okhttp.internal.http.HttpTransport.disconnect(HttpTransport.java:135)
                                                                       at com.android.okhttp.internal.http.HttpEngine.disconnect(HttpEngine.java:578)
                                                                       at com.android.okhttp.internal.huc.HttpURLConnectionImpl.disconnect(HttpURLConnectionImpl.java:122)
                                                                       at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.disconnect(DelegatingHttpsURLConnection.java:93)
                                                                       at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.disconnect(HttpsURLConnectionImpl.java)
                                                                       at com.facebook.internal.Utility.disconnectQuietly(Utility.java:416)
                                                                       at com.facebook.GraphRequest.executeConnectionAndWait(GraphRequest.java:1272)
                                                                       at com.facebook.GraphRequest.executeBatchAndWait(GraphRequest.java:1168)
                                                                       at com.facebook.GraphRequest.executeBatchAndWait(GraphRequest.java:1134)
                                                                       at com.facebook.GraphRequest.executeBatchAndWait(GraphRequest.java:1118)
                                                                       at com.facebook.GraphRequest.executeAndWait(GraphRequest.java:1093)
                                                                       at com.facebook.GraphRequest.executeAndWait(GraphRequest.java:987)
                                                                       at com.qbc.xxx.MainActivity$RetrieveFacebookPosts$1$1.onCompleted(MainActivity.java:398)
                                                                       at com.facebook.GraphRequest$5.run(GraphRequest.java:1383)
                                                                       at android.os.Handler.handleCallback(Handler.java:739)
                                                                       at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                       at android.os.Looper.loop(Looper.java:148)
                                                                       at android.app.ActivityThread.main(ActivityThread.java:5417)
                                                                       at java.lang.reflect.Method.invoke(Native Method)
                                                                       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726)
                                                                       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)               

I'm unable to figure out what's causing this error as such errors are usually caused when this sort of code is not handled in AsyncTask but that is not the case here.

Please let me know what's causing this error and how to get rid of it.

Upvotes: 0

Views: 874

Answers (3)

Swetabja Hazra
Swetabja Hazra

Reputation: 673

This is not the right approach

Thread t = new Thread() {
@Override
public void run() {
    GraphRequest nextResultsRequests = lastGraphResponse.getRequestForPagedResults(GraphResponse.PagingDirection.NEXT);
    if (nextResultsRequests != null) {
        nextResultsRequests.setCallback(request.getCallback());
        lastGraphResponse = nextResultsRequests.executeAndWait();
    }
}

}.start();

You are doing that by creating a new thread. All network operations should be done in the background thread which already exists, not by creating a new thread.

The way to do this is using a handler object to run the code on main thread.

Handler handler = new Handler();
    handler.post(new Runnable() {
        @Override
        public void run() {
            GraphRequest nextResultsRequests = lastGraphResponse.getRequestForPagedResults(GraphResponse.PagingDirection.NEXT);
            if (nextResultsRequests != null) {
                nextResultsRequests.setCallback(request.getCallback());
                lastGraphResponse = nextResultsRequests.executeAndWait();
            }
        }
    });

Or you can do the operation after some delay, by using postDelayed

handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            GraphRequest nextResultsRequests = lastGraphResponse.getRequestForPagedResults(GraphResponse.PagingDirection.NEXT);
            if (nextResultsRequests != null) {
                nextResultsRequests.setCallback(request.getCallback());
                lastGraphResponse = nextResultsRequests.executeAndWait();
            }
        }
    }, DELAY_IN MILLISECONDS);

Upvotes: 1

Hammad Nasir
Hammad Nasir

Reputation: 2959

After a few google searches I got the solution.

I just wrapped the GraphRequest.executeAndWait() code in a Thread like this:

Thread t = new Thread() {
    @Override
    public void run() {
        GraphRequest nextResultsRequests = lastGraphResponse.getRequestForPagedResults(GraphResponse.PagingDirection.NEXT);
        if (nextResultsRequests != null) {
            nextResultsRequests.setCallback(request.getCallback());
            lastGraphResponse = nextResultsRequests.executeAndWait();
        }
    }
};
t.start();

Upvotes: 0

Vladyslav Matviienko
Vladyslav Matviienko

Reputation: 10881

public void onCompleted() is run on the UI thread regardless of which thread called this request. So if you want to perform another request inside public void onCompleted(), you will have to wrap it into another AsyncTask, or other async mechanism.

Upvotes: 1

Related Questions