facebook-graph-api get - Facebook Graph API v2.0+-/ me / friends devuelve vacío, o solo amigos que también usan mi aplicación




list login (6)

Estoy tratando de obtener mi nombre de amigo e ID con Graph API v2.0, pero los datos están 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<FBGraphUser>* friend in friends) {
        NSLog(@"I have a friend named %@ with id %@", friend.name, friend.id);
    }
}];

Pero ahora no puedo tener amigos!


Answers

Aunque la respuesta de Simon Cross es aceptada y correcta, pensé que lo reforzaría un poco con un ejemplo (Android) de lo que hay que hacer. Lo mantendré lo más general posible y me centraré solo en la pregunta. Personalmente terminé almacenando cosas en una base de datos, por lo que la carga se realizó sin problemas, pero eso requiere un CursorAdapter y ContentProvider, que está un poco fuera de alcance aquí.

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

La cuestión

Al igual que el usuario 3594351 , noté que los datos del amigo estaban en blanco. Descubrí esto utilizando el FriendPickerFragment. Lo que funcionó hace tres meses, ya no funciona. Incluso los ejemplos de facebook se rompieron. Así que mi problema fue '¿Cómo puedo crear FriendPickerFragment a mano?

Lo que no funcionó

La opció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 permitiría 5 solicitudes a la vez. El diálogo de solicitudes también mostró los mismos amigos durante cualquier sesión de Facebook que haya iniciado sesión. Inútil.

Lo que funcionó (resumen)

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

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

  1. Crear una actividad de pestaña que muestra dos fragmentos. Cada fragmento muestra una lista. Un fragmento para los amigos disponibles (/ me / friends) y otro para los amigos invitables (/ me / invitable_friends). Utilice el mismo código de fragmento para representar ambas pestañas.
  2. Cree una AsyncTask que obtenga los datos de amigos de Facebook. Una vez que se carguen esos datos, tíralos al adaptador que mostrará los valores en la pantalla.

Detalles

El AsynchTask

private class DownloadFacebookFriendsTask extends AsyncTask<FacebookFriend.Type, Boolean, Boolean> {
        private final String TAG = DownloadFacebookFriendsTask.class.getSimpleName();
        GraphObject graphObject;
        ArrayList<FacebookFriend> myList = new ArrayList<FacebookFriend>();

        @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 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 puedes obtener la lista completa de amigos de todos modos si tu aplicación no tiene una implementación de Canvas y si no es un juego. Por supuesto, también hay taggable_friends, pero ese es solo para etiquetar.

Podrá extraer la lista de amigos que solo han autorizado la aplicación.

Las aplicaciones que utilizan Graph API 1.0 funcionarán hasta el 30 de abril de 2015 y, posteriormente, quedarán en desuso.

Vea el enlace de abajo para obtener más detalles sobre esto

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


en FBSDKGraphAPI v2.0 o superior, debe solicitar el permiso de user_friends a cada usuario en el momento del inicio de sesión de FB. Dado que user_friends ya no está incluido de forma predeterminada en cada inicio de sesión, debemos agregarlo. Cada usuario debe otorgar el permiso de 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 {
            }
        }
    }

Así que en el momento del inicio de sesión de FB, aparece una pantalla de solicitud que contiene todos los permisos

Si el usuario presiona el botón continuar, se establecerán los permisos. Cuando acceda a la lista de amigos utilizando FBGraphAPI, se enumerarán sus amigos que iniciaron sesión en la aplicación como se indica arriba.

   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 de 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;
    };
}

Como mencionó Simon, esto no es posible en la nueva API de Facebook. 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, esto puede no ser legal
  • Tendrá que usar sus credenciales / solicitar al usuario las credenciales y posiblemente almacenarlas (no es una buena idea almacenar las contraseñas incluso con cifrado simétrico)
  • cuando Facebook cambie su api, también tendrá que 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 es pasar por alto el concepto OAuth
  • por otro lado, mi sensación es que soy dueño de mis datos, incluida la lista de mis amigos y FB no debería restringirme el acceso a ellos a través de la API

Implementación de muestra usando WatiN

class FacebookUser
{
  public string Name { get; set; }
  public long Id { get; set; }
}

public IList<FacebookUser> GetFacebookFriends(string email, string password, int? maxTimeoutInMilliseconds)
{
  var users = new List<FacebookUser>();
  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=(?<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 implementación de este enfoque (utilizando C # / Watin) vea 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.



Actualizado el 2014-07-02

No puede buscar directamente en la API de Facebook eventos cercanos a una ubicación. Dado que originalmente dio esta respuesta, Graph API ha dificultado la búsqueda de eventos.

La secuencia de comandos de Elmcity a la que hace referencia el OP realiza una búsqueda simple de una palabra clave en el título del evento. Prueba "Lancaster" por ejemplo. Obtendrá eventos que tienen la palabra Lancaster en algún lugar de sus metadatos.

Su consulta se ve más o menos así:

 https://graph.facebook.com/search?q=lancaster&type=event

También puede buscar una palabra que no esté basada en la ubicación en el título como "picnic" y la secuencia de comandos devuelve los eventos.

Para el problema de encontrar realmente eventos cerca de una ubicación, en la iteración actual, el campo "sede" es solo una cadena, por lo que no tiene relación con ningún lugar de Facebook. Ejecutar estas consultas no devuelve nada:

https://graph.facebook.com/madisonsquaregarden/events
https://graph.facebook.com/108424279189115/events

Entonces, usar una solicitud por lotes ni siquiera es una posibilidad.

De acuerdo con la documentación FQL parece ser una mejor solución. ¡En la documentación del evento , la columna venue.name es indexable! Fácil, ¿verdad?

Incorrecto. Cuando ejecuta esta consulta FQL para encontrar eventos en alguna ubicación como esta:

 SELECT name, start_time, venue FROM event WHERE CONTAINS("madison square garden")

Encuentra que venue.name no está venue.name .

Intentando cualquier otra variación como:

 SELECT name, start_time, venue FROM event WHERE venue.id = 108424279189115

Lanza un error de "declaración no indexable".

Así que, mientras construyes un "Facebook Events Near Me" es la aplicación más arriesgada, la única forma en que parece posible es buscar cadenas comunes para eventos cercanos a ti, obtener esos eventos y luego filtrar los eventos irrelevantes del conjunto de resultados.





facebook facebook-graph-api facebook-ios-sdk facebook-graph-api-v2.0