4

I am fetching the list of friends who use the my android application and show them in listview. The response we get from the call:

 GraphRequestAsyncTask graphRequest = new GraphRequest(
                AccessToken.getCurrentAccessToken(),
                "/me/friends",
                null,
                HttpMethod.GET,
                new GraphRequest.Callback() {
                    public void onCompleted(GraphResponse response) {



                    }
                }
        ).executeAsync();

is

 {
  "data": [
    {
      "name": "Sanjeev Sharma",
      "id": "10XXXXXXXXXX40"
    },
    {
      "name": "Avninder Singh",
      "id": "1XXXXX30"
    },
    {
      "name": "Saikrishna Tipparapu",
      "id": "17XXXXXX98"
    },
    {
      "name": "Perfekt Archer",
      "id": "100XXXXX29"
    },
    {
      "name": "Shathyan Raja",
      "id": "10XXXXX0"
    },
    {
      "name": "Kenny Tran",
      "id": "10XXXXX36164"
    },
    {
      "name": "Lahaul Seth",
      "id": "100XXXXX161"
    },
    {
      "name": "Bappa Dittya",
      "id": "10XXXXX24"
    },
    {
      "name": "Rahul",
      "id": "10XXXXX
    },
    {
      "name": "Suruchi ",
      "id": "7XXXXXXXX11"
    }
  ],
  "paging": {
    "next": "https://graph.facebook.com/76XXXXXXXX28/friends?limit=25&offset=25&__after_id=enc_AdAXXXXX5L8nqEymMrXXXXoYWaK8BXXHrvpXp03gc1eAaVaj7Q"
  },
  "summary": {
    "total_count": 382
  }
}

Now how can we parse the next page of the result in android as it is a link for next page? The next page api call will be done through graph api or facebook only?

Abhishek Balani
  • 3,827
  • 2
  • 24
  • 34
  • There’s a dedicated method for that, [getRequestForPagedResults](https://developers.facebook.com/docs/reference/android/current/class/GraphResponse/#getRequestForPagedResults) – CBroe Jul 14 '15 at 07:48
  • @CBroe Can you please share a piece of code parsing data using this function. – Abhishek Balani Jul 14 '15 at 08:31
  • You don’t “parse” any data using that method – you simply use it to get a new `GraphRequest` instance that can be used to fetch the results for the next or previous page. – CBroe Jul 14 '15 at 10:09
  • @TheOddAbhi, hey can u take a look at http://stackoverflow.com/questions/34679376/facebook-graph-api-me-friends-not-returns-all-friends-who-authorized-app ? – Stella Jan 08 '16 at 16:33

2 Answers2

10

ifaour has the right idea of how to use pagination with the next, though i think he is right i just wanted to add a recursive way to fetch all results page after page into one nice list object, this is from a project requesting user photos but its the same idea and syntax as the likes (note that this whole thing is using the execute and wait so you'll have to run this from a separate thread or you will effectively block your UI thread and eventually make the app shut itself down.

Bundle param = new Bundle();
param.putString("fields", "id,picture");
param.putInt("limit", 100);

//setup a general callback for each graph request sent, this callback will launch the next request if exists.
final GraphRequest.Callback graphCallback = new GraphRequest.Callback(){
    @Override
    public void onCompleted(GraphResponse response) {                       
        try {
            JSONArray rawPhotosData = response.getJSONObject().getJSONArray("data");
            for(int j=0; j<rawPhotosData.length();j++){
                /*save whatever data you want from the result
                JSONObject photo = new JSONObject();
                photo.put("id", ((JSONObject)rawPhotosData.get(j)).get("id"));
                photo.put("icon", ((JSONObject)rawPhotosData.get(j)).get("picture"));

                boolean isUnique = true;

                for(JSONObject item : photos){  
                    if(item.toString().equals(photo.toString())){
                        isUnique = false;
                        break;
                    }
                }

                if(isUnique) photos.add(photo);*/
            }

            //get next batch of results of exists
            GraphRequest nextRequest = response.getRequestForPagedResults(GraphResponse.PagingDirection.NEXT);
            if(nextRequest != null){
                nextRequest.setCallback(this);
                nextRequest.executeAndWait();
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
};

Now all you need to do is simply make the initial request and set the callback you've made in previous step, the callback will handle all the dirty work of calling the rest of the items, this will eventually give you all the items from your request.

//send first request, the rest should be called by the callback
new GraphRequest(AccessToken.getCurrentAccessToken(), 
        "me/photos",param, HttpMethod.GET, graphCallback).executeAndWait();
almightyGOSU
  • 3,731
  • 6
  • 31
  • 41
Liran Cohen
  • 1,190
  • 1
  • 9
  • 16
  • This is perfect. The only problem is, it give JSONException on the last page as the JSON key is not found on last page. Any workaround for that? – Abhishek Balani Aug 01 '15 at 07:02
  • getRequestForPagedResults call returns null for me. Others have same problem apparently - http://stackoverflow.com/questions/34584877/android-facebook-sdk-getrequestforpagedresults-always-null Is this call still working for anyone? If so, can you post your code snippet please? Note that I see the paging items in the returned JSON. Its just this call that returns null. – GreenBee Nov 25 '16 at 20:14
  • This line `nextRequest.executeAndWait()` will through an exception: `android.os.NetworkOnMainThreadException`. Use this `nextRequest.executeAsync();` instead to execute request on main thread. – blueware Oct 15 '18 at 11:55
2

As mentioned by @CBroe, you use the getRequestForPagedResults method. As for an example, check the Scrumptious sample project.

I extended the HelloFacebookSample and added two buttons that will load the initial user liked pages and the other will load the next result if available:

loadAndLogLikesButton = (Button) findViewById(R.id.loadAndLogLikesButton);
loadAndLogLikesButton.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
    pendingAction = PendingAction.LOAD_LIKES;
    if (!hasUserLikesPermission()) {
      LoginManager.getInstance().logInWithReadPermissions(HelloFacebookSampleActivity.this, Arrays.asList("public_profile", "user_likes"));
    } else {
      handlePendingAction();
    }
  }
});

Now the handlePendingAction() is being called from the LoginManager success callback. As you can see, I have an extra action LOAD_LIKES that will trigger a method that will do the following:

GraphRequest request = GraphRequest.newGraphPathRequest(
  accessToken,
  "me/likes",
  new GraphRequest.Callback() {
      @Override
      public void onCompleted(GraphResponse response) {
          Log.d("HelloFacebook", response.getRawResponse());
          JSONArray data = response.getJSONObject().optJSONArray("data");

          boolean haveData = data.length() > 0;
          if (haveData) {
              loadNextLikesButton.setEnabled(true);
              nextRequest = response.getRequestForPagedResults(GraphResponse.PagingDirection.NEXT);
          }
      }
  }
);

Bundle parameters = new Bundle();
parameters.putString("fields", "id");
parameters.putString("limit", "100");
request.setParameters(parameters);

Now my loadNextLikesButton's callback looks like this:

if (nextRequest != null) {
  nextRequest.setCallback(new GraphRequest.Callback() {
    @Override
    public void onCompleted(GraphResponse response) {
      Log.d("HelloFacebook", response.getRawResponse());

      JSONArray data = response.getJSONObject().optJSONArray("data");

      boolean haveData = data.length() > 0;
      if (haveData) {
        loadNextLikesButton.setEnabled(true);
        nextRequest = response.getRequestForPagedResults(GraphResponse.PagingDirection.NEXT);
      } else {
        loadNextLikesButton.setEnabled(false);
      }
    }
  });
  nextRequest.executeAsync();
} else {
  Log.d("HelloFacebook", "We are done!");
  return;
}

Not pretty but you get the idea.

ifaour
  • 38,035
  • 12
  • 72
  • 79