Facebook Graph API v2.0 + – / me / friends vuelve vacío, o solo amigos que también usan mi aplicación

Estoy tratando de obtener el nombre y los id de mi amigo con Graph API v2.0, pero los datos se vuelven vacíos:

{ "data": [ ] } 

Cuando estaba usando v1.0, todo estaba bien con la siguiente solicitud:

 FBRequest* friendsRequest = [FBRequest requestForMyFriends]; [friendsRequest startWithCompletionHandler: ^(FBRequestConnection *connection, NSDictionary* result, NSError *error) { NSArray* friends = [result objectForKey:@"data"]; NSLog(@"Found: %i friends", friends.count); for (NSDictionary* friend in friends) { NSLog(@"I have a friend named %@ with id %@", friend.name, friend.id); } }]; 

¡Pero ahora no puedo hacer amigos!

En la v2.0 de Graph API, la llamada /me/friends devuelve los /me/friends la persona que también usan la aplicación.

Además, en v2.0, debe solicitar el permiso user_friends de cada usuario. user_friends ya no está incluido de manera predeterminada en cada inicio de sesión. Cada usuario debe otorgar el permiso user_friends para aparecer en la respuesta a /me/friends . Consulte la guía de actualización de Facebook para obtener información más detallada o revise el resumen a continuación.

Si desea acceder a una lista de amigos que no usan aplicaciones, hay dos opciones:

  1. Si desea que su gente etiquete a sus amigos en las historias que publican en Facebook con su aplicación, puede usar la API /me/taggable_friends . El uso de este punto final requiere una revisión por parte de Facebook y solo se debe usar para el caso en el que esté presentando una lista de amigos para permitir que el usuario los etiquete en una publicación.

  2. Si su aplicación es un juego Y su juego es compatible con el canvas de Facebook , puede usar el punto final /me/invitable_friends para generar un cuadro de diálogo de invitación personalizado , luego pase los tokens devueltos por esta API al cuadro de diálogo de solicitudes estándar.

En otros casos, las aplicaciones ya no pueden recuperar la lista completa de amigos de un usuario (solo aquellos amigos que han autorizado específicamente su aplicación con el permiso user_friends ). Esto ha sido confirmado por Facebook como ‘por diseño’.

Para las aplicaciones que desean permitir que las personas inviten a sus amigos a usar una aplicación, igual puede usar el cuadro de diálogo Enviar en la Web o el nuevo cuadro de diálogo de mensajes en iOS y Android .

ACTUALIZACIÓN: Facebook ha publicado una Pregunta frecuente sobre estos cambios aquí: https://developers.facebook.com/docs/apps/faq que explican todas las opciones disponibles para los desarrolladores para invitar a amigos, etc.

Aunque la respuesta de Simon Cross es correcta y aceptada, pensé que iba a reforzarla un poco con un ejemplo (Android) de lo que hay que hacer. Lo mantendré tan general como pueda y me concentraré solo en la pregunta. Personalmente, terminé almacenando cosas en una base de datos para que la carga fuera fluida, pero eso requiere un CursorAdapter y ContentProvider que está un poco fuera de scope aquí.

Vine aquí y luego pensé, ¿y ahora qué?

La cuestión

Al igual que user3594351 , estaba notando que los datos del amigo estaban en blanco. Descubrí esto usando FriendPickerFragment. Lo que funcionó hace tres meses, ya no funciona. Incluso los ejemplos de Facebook se rompieron. Entonces mi problema era ‘¿Cómo creo FriendPickerFragment a mano?

Lo que no funcionó

La opción n. ° 1 de Simon Cross no fue lo suficientemente fuerte como para invitar a amigos a la aplicación. Simon Cross también recomendó el Diálogo de Solicitudes pero eso solo permitía 5 solicitudes a la vez. El diálogo de solicitudes también mostró a los mismos amigos durante cualquier sesión de sesión de Facebook. Inútil.

Qué funcionó (resumen)

Opción # 2 con un poco de trabajo duro. Debes asegurarte de cumplir las nuevas reglas de Facebook: 1.) Eres un juego 2.) Tienes una aplicación de Canvas (Presencia web) 3.) Tu aplicación está registrada en Facebook. Todo hecho en el sitio web de desarrolladores de Facebook en la configuración.

Para emular el selector de amigos a mano dentro de mi aplicación, hice lo siguiente:

  1. Crea una actividad de tabs que muestra dos fragmentos. Cada fragmento muestra una lista. Un fragmento para amigo disponible (/ me / friends) y otro para amigos inviables (/ me / invitable_friends). Use el mismo código de fragmento para representar ambas tabs.
  2. Crea una AsyncTask que obtendrá los datos de amigos de Facebook. Una vez que se carguen los datos, agréguelos al adaptador que mostrará los valores en la pantalla.

Detalles

The AsynchTask

 private class DownloadFacebookFriendsTask extends AsyncTask { private final String TAG = DownloadFacebookFriendsTask.class.getSimpleName(); GraphObject graphObject; ArrayList myList = new ArrayList(); @Override protected Boolean doInBackground(FacebookFriend.Type... pickType) { // //Determine Type // String facebookRequest; if (pickType[0] == FacebookFriend.Type.AVAILABLE) { facebookRequest = "/me/friends"; } else { facebookRequest = "/me/invitable_friends"; } // //Launch Facebook request and WAIT. // new Request( Session.getActiveSession(), facebookRequest, null, HttpMethod.GET, new Request.Callback() { public void onCompleted(Response response) { FacebookRequestError error = response.getError(); if (error != null && response != null) { Log.e(TAG, error.toString()); } else { graphObject = response.getGraphObject(); } } } ).executeAndWait(); // //Process Facebook response // // if (graphObject == null) { return false; } int numberOfRecords = 0; JSONArray dataArray = (JSONArray) graphObject.getProperty("data"); if (dataArray.length() > 0) { // Ensure the user has at least one friend ... for (int i = 0; i < dataArray.length(); i++) { JSONObject jsonObject = dataArray.optJSONObject(i); FacebookFriend facebookFriend = new FacebookFriend(jsonObject, pickType[0]); if (facebookFriend.isValid()) { numberOfRecords++; myList.add(facebookFriend); } } } //make sure there are records to process if (numberOfRecords > 0){ return true; } else { return false; } } @Override protected void onProgressUpdate(Boolean... booleans) { //no need to update this, wait until the whole thread finishes. } @Override protected void onPostExecute(Boolean result) { if (result) { /* User the array "myList" to create the adapter which will control showing items in the list. */ } else { Log.i(TAG, "Facebook Thread unable to Get/Parse friend data. Type = " + pickType); } } } 

La clase de FacebookFriend que creé

 public class FacebookFriend { String facebookId; String name; String pictureUrl; boolean invitable; boolean available; boolean isValid; public enum Type {AVAILABLE, INVITABLE}; public FacebookFriend(JSONObject jsonObject, Type type) { // //Parse the Facebook Data from the JSON object. // try { if (type == Type.INVITABLE) { //parse /me/invitable_friend this.facebookId = jsonObject.getString("id"); this.name = jsonObject.getString("name"); //Handle the picture data. JSONObject pictureJsonObject = jsonObject.getJSONObject("picture").getJSONObject("data"); boolean isSilhouette = pictureJsonObject.getBoolean("is_silhouette"); if (!isSilhouette) { this.pictureUrl = pictureJsonObject.getString("url"); } else { this.pictureUrl = ""; } this.invitable = true; } else { //parse /me/friends this.facebookId = jsonObject.getString("id"); this.name = jsonObject.getString("name"); this.available = true; this.pictureUrl = ""; } isValid = true; } catch (JSONException e) { Log.w("#", "Warnings - unable to process FB JSON: " + e.getLocalizedMessage()); } } } 

Facebook ha revisado sus políticas ahora. No puede obtener toda la lista de amigos de todos modos si su aplicación no tiene una implementación Canvas y si su aplicación no es un juego. Por supuesto, también hay taggable_friends, pero ese es solo para etiquetar.

Podrás obtener la lista de amigos que han autorizado la aplicación solamente.

Las aplicaciones que usan Graph API 1.0 funcionarán hasta el 30 de abril de 2015 y, a partir de ese momento, quedarán obsoletas.

Vea el enlace a continuación para obtener más detalles sobre este

https://developers.facebook.com/docs/graph-api/reference/v2.2/user/friends

https://developers.facebook.com/docs/apps/faq#invite_to_app

Espero que esto ayude

Como mencionó Simon, esto no es posible en la nueva API de Facebook. Puro técnicamente hablando , puedes hacerlo a través de la automatización del navegador.

  • esto va en contra de la política de Facebook, por lo que dependiendo del país donde vives, puede que esto no sea legal
  • tendrá que usar sus credenciales / solicitar credenciales al usuario y, posiblemente, almacenarlas (almacenar contraseñas cifradas simétricamente no es una buena idea)
  • cuando Facebook cambie su API, también deberá actualizar el código de automatización del navegador (si no puede forzar las actualizaciones de su aplicación, debe poner la pieza de automatización del navegador como servicio web)
  • esto está pasando por alto el concepto de OAuth
  • por otro lado, mi sensación es que soy el propietario de mis datos, incluida la lista de mis amigos, y FB no debería restringirme el acceso a esos a través de API

Implementación de muestra usando WatiN

 class FacebookUser { public string Name { get; set; } public long Id { get; set; } } public IList GetFacebookFriends(string email, string password, int? maxTimeoutInMilliseconds) { var users = new List(); Settings.Instance.MakeNewIeInstanceVisible = false; using (var browser = new IE("https://www.facebook.com")) { try { browser.TextField(Find.ByName("email")).Value = email; browser.TextField(Find.ByName("pass")).Value = password; browser.Form(Find.ById("login_form")).Submit(); browser.WaitForComplete(); } catch (ElementNotFoundException) { // we're already logged in } browser.GoTo("https://www.facebook.com/friends"); var watch = new Stopwatch(); watch.Start(); Link previousLastLink = null; while (maxTimeoutInMilliseconds.HasValue && watch.Elapsed.TotalMilliseconds < maxTimeoutInMilliseconds.Value) { var lastLink = browser.Links.Where(l => l.GetAttributeValue("data-hovercard") != null && l.GetAttributeValue("data-hovercard").Contains("user.php") && l.Text != null ).LastOrDefault(); if (lastLink == null || previousLastLink == lastLink) { break; } var ieElement = lastLink.NativeElement as IEElement; if (ieElement != null) { var htmlElement = ieElement.AsHtmlElement; htmlElement.scrollIntoView(); browser.WaitForComplete(); } previousLastLink = lastLink; } var links = browser.Links.Where(l => l.GetAttributeValue("data-hovercard") != null && l.GetAttributeValue("data-hovercard").Contains("user.php") && l.Text != null ).ToList(); var idRegex = new Regex("id=(?([0-9]+))"); foreach (var link in links) { string hovercard = link.GetAttributeValue("data-hovercard"); var match = idRegex.Match(hovercard); long id = 0; if (match.Success) { id = long.Parse(match.Groups["id"].Value); } users.Add(new FacebookUser { Name = link.Text, Id = id }); } } return users; } 

Prototipo con la implementación de este enfoque (utilizando C # / Watin), consulte https://github.com/svejdo1/ShadowApi. También permite la actualización dinámica del conector de Facebook que está recuperando la lista de sus contactos.

Pruebe / me / taggable_friends? Limit = 5000 usando su código de JavaScript

O

prueba el gráfico API

https://graph.facebook.com/v2.3/user_id_here/taggable_friends?access_token=

Que te diviertas

en FBSDKGraphAPI v2.0 o superior, debe solicitar el permiso user_friends de cada usuario en el momento del inicio de sesión de FB. Ya que user_friends ya no está incluido de manera predeterminada en cada inicio de sesión, tenemos que agregar eso. Cada usuario debe otorgar el permiso user_friends para aparecer en la respuesta a / me / friends

  let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager() fbLoginManager.loginBehavior = FBSDKLoginBehavior.web fbLoginManager.logIn(withReadPermissions: ["email","user_friends","public_profile"], from: self) { (result, error) in if (error == nil){ let fbloginresult : FBSDKLoginManagerLoginResult = result! if fbloginresult.grantedPermissions != nil { if(fbloginresult.grantedPermissions.contains("email")) { // Do the stuff }else { } }else { } } } 

Entonces, en el momento del inicio de sesión de FB, aparece una pantalla que contiene todos los permisos enter image description here

Si el usuario presiona el botón continuar, los permisos se establecerán. Cuando accede a la lista de amigos usando FBGraphAPI, sus amigos que iniciaron sesión en la aplicación como se detalla arriba aparecerán en la lista

  if((FBSDKAccessToken.current()) != nil){ FBSDKGraphRequest(graphPath: "/me/friends", parameters: ["fields" : "id,name"]).start(completionHandler: { (connection, result, error) -> Void in if (error == nil){ print(result!) } }) } 

La salida contendrá los usuarios que otorgaron el permiso user_friends al momento de iniciar sesión en su aplicación a través de Facebook

 { data = ( { id = xxxxxxxxxx; name = "xxxxxxxx"; } ); paging = { cursors = { after = xxxxxx; before = xxxxxxx; }; }; summary = { "total_count" = 8; }; }