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.

3

There are 3 answers

0
Hammad Nasir On BEST ANSWER

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();
1
Vladyslav Matviienko On

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.

0
Swetabja Hazra On

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);