Facebook Graph API v2.0 + - / me / friends gibt leer zurück oder nur Freunde, die auch meine Anwendung verwenden

366

Ich versuche, meinen Freundesnamen und meine IDs mit der Graph API v2.0 abzurufen, aber die Daten werden leer zurückgegeben:

{
  "data": [
  ]
}

Als ich v1.0 verwendete, war mit der folgenden Anfrage alles in Ordnung:

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

Aber jetzt kann ich keine Freunde finden!

Kaslico
quelle
eine mögliche Überwindung dieses Problems stackoverflow.com/a/25584013/2529087
java.quaso

Antworten:

627

In Version 2.0 der Graph-API gibt der Aufruf /me/friendsdie Freunde der Person zurück, die auch die App verwenden.

Darüber hinaus müssen Sie in Version 2.0 die user_friendsBerechtigung von jedem Benutzer anfordern . user_friendsist nicht mehr standardmäßig in jedem Login enthalten. Jeder Benutzer muss die user_friendsBerechtigung erteilen, um in der Antwort auf zu erscheinen /me/friends. Weitere Informationen finden Sie im Facebook-Upgrade-Handbuch oder in der folgenden Zusammenfassung.

Wenn Sie auf eine Liste von Freunden zugreifen möchten, die keine App verwenden, gibt es zwei Möglichkeiten:

  1. Wenn Sie möchten, dass Ihre Leute ihre Freunde in Geschichten markieren , die sie mithilfe Ihrer App auf Facebook veröffentlichen, können Sie die/me/taggable_friendsAPI verwenden. Die Verwendung dieses Endpunkts erfordert eine Überprüfung durch Facebook und sollte nur für den Fall verwendet werden, dass Sie eine Liste von Freunden rendern, damit der Benutzer sie in einem Beitrag markieren kann.

  2. Wenn Ihre App ein Spiel ist UND Ihr Spiel Facebook Canvas unterstützt , können Sie den/me/invitable_friendsEndpunkt verwenden, um einen benutzerdefinierten Einladungsdialog zu rendern, und die von dieser API zurückgegebenen Token an den Standard-Anforderungsdialog übergeben.

In anderen Fällen können Apps nicht mehr die vollständige Liste der Freunde eines Benutzers abrufen (nur diejenigen Freunde, die Ihre App mit dieser user_friendsBerechtigung speziell autorisiert haben ). Dies wurde von Facebook als "by design" bestätigt.

Für Apps, mit denen Benutzer Freunde zur Verwendung einer App einladen können, können Sie weiterhin den Dialog "Senden" im Web oder den neuen Dialog "Nachricht" unter iOS und Android verwenden .

UPDATE: Facebook hat hier eine FAQ zu diesen Änderungen veröffentlicht: https://developers.facebook.com/docs/apps/faq, in der alle Optionen erläutert werden, die Entwicklern zur Verfügung stehen, um Freunde usw. einzuladen.

Simon Cross
quelle
Gibt es Neuigkeiten seit Ihrer letzten Bearbeitung oder wir auf derselben Seite?
Ilya Gazman
Die taggable_friendsin den Elementen zur Überprüfung eingereichten Informationen können nicht angezeigt werden.
AlikElzin-Kilaka
7
Ich kann nicht verstehen, warum sie es so sehr einschränken mussten. Ich meine, das alte System war viel zu missbräuchlich, aber dieses ist so gut wie nutzlos. Das öffentliche Profil all Ihrer Freunde zu sehen, wäre sicherlich kein Datenschutzproblem. Es sei denn, Sie denken, dass die Verbindung der Freundschaft selbst privat ist (aber warum auch nicht, wenn es sich um taggable Freunde handelt). Dies war kein Schritt zur Einschränkung des Datenschutzmissbrauchs, der ein Nebeneffekt ist. Sie wollten die Möglichkeit für normale (nicht mit Facebook verbundene) Entwickler schließen, ihr Geschäft mithilfe von Facebook-Daten auszubauen.
Daniel Sharp
3
Facebook hat kürzlich wesentliche Änderungen der verfügbaren Daten veröffentlicht: siehe Changelog . Das gibt taggable_friendsjetzt nichts zurück. Außerdem ist eine Überprüfung der Anmeldung erforderlich, bevor Ihnen die Berechtigung user_friendserteilt werden kann.
Duncan Jones
Was bringt es, eine API bereitzustellen, wenn Sie damit keine grundlegende Aufgabe wie das Auflisten der Freunde ausführen können?
6infinity8
17

Obwohl die Antwort von Simon Cross akzeptiert und richtig ist, dachte ich, ich würde sie mit einem Beispiel (Android) ein wenig aufpeppen, was getan werden muss. Ich werde es so allgemein wie möglich halten und mich nur auf die Frage konzentrieren. Persönlich habe ich Dinge in einer Datenbank gespeichert, damit das Laden reibungslos verlief, aber dafür sind ein CursorAdapter und ein ContentProvider erforderlich, die hier etwas außerhalb des Geltungsbereichs liegen.

Ich bin selbst hierher gekommen und habe dann gedacht, was nun?!

Die Angelegenheit

Genau wie bei user3594351 bemerkte ich, dass die Freundesdaten leer waren. Ich habe dies mithilfe des FriendPickerFragment herausgefunden. Was vor drei Monaten funktioniert hat, funktioniert nicht mehr. Sogar Facebooks Beispiele brachen. Mein Problem war also: "Wie erstelle ich FriendPickerFragment von Hand?"

Was hat nicht funktioniert

Option 1 von Simon Cross war nicht stark genug, um Freunde zur App einzuladen. Simon Cross empfahl auch den Anforderungsdialog, der jedoch nur fünf Anfragen gleichzeitig zulässt. Der Anforderungsdialog zeigte auch die gleichen Freunde während einer bestimmten Facebook-Anmeldesitzung. Nicht nützlich.

Was hat funktioniert (Zusammenfassung)

Option 2 mit harter Arbeit. Sie müssen sicherstellen, dass Sie die neuen Regeln von Facebook erfüllen: 1.) Sie sind ein Spiel 2.) Sie haben eine Canvas-App (Webpräsenz) 3.) Ihre App ist bei Facebook registriert. Dies geschieht alles auf der Facebook-Entwickler-Website unter Einstellungen .

Um den Freund-Picker von Hand in meiner App zu emulieren, habe ich Folgendes getan:

  1. Erstellen Sie eine Registerkartenaktivität, die zwei Fragmente anzeigt. Jedes Fragment zeigt eine Liste. Ein Fragment für verfügbare Freunde ( / me / friends ) und ein anderes für einladbare Freunde ( / me / invitable_friends ). Verwenden Sie denselben Fragmentcode, um beide Registerkarten zu rendern.
  2. Erstellen Sie eine AsyncTask, die die Freundesdaten von Facebook abruft. Sobald diese Daten geladen sind, werfen Sie sie auf den Adapter, der die Werte auf dem Bildschirm rendert.

Einzelheiten

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

Die FacebookFriend-Klasse, die ich erstellt habe

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 Facebook JSON: " + e.getLocalizedMessage());
        }
    }
}
LÖWE
quelle
20
Wie wäre es mit Nicht-Gaming-Apps? Eine Dating-Website ... ein Spiel, um Leute zu finden, eine App, um Restaurants zu finden ... ein Spiel, um Restaurants zu finden usw. Sie haben die Idee. Ist dies also WIRKLICH nah an Spielen oder ist dies nur eine Möglichkeit, Sie dazu zu zwingen, eine App in Facebook zu platzieren und Geld für deren Werbeplattform auszugeben? Wer wird entscheiden, was ein Spiel ist? Wer hat entschieden, dass Ihre App tatsächlich ein Spiel ist oder nicht? Versteh mich nicht falsch, aber für mich macht es keinen Sinn, Nicht-Gaming-Apps zu blockieren, es sei denn, Sie möchten sie nur zwingen, das Facebook-Ökosystem zu nutzen.
Mário
@ Mário Das ist Facebook Absicht unter der Haube. Sie können alles setzen und als Spiel markieren, da es ihnen egal ist, ob es wirklich ein Spiel ist oder nicht. Alles, was sie interessiert, ist Geld aus der Tasche zu bekommen.
Sandalone
12

Facebook hat seine Richtlinien jetzt überarbeitet. Sie können ohnehin nicht die gesamte Freundesliste abrufen, wenn Ihre App keine Canvas-Implementierung hat und wenn Ihre App kein Spiel ist. Natürlich gibt es auch taggable_friends, aber dieser dient nur zum Markieren.

Sie können die Liste der Freunde abrufen, die nur die App autorisiert haben.

Die Apps, die Graph API 1.0 verwenden, funktionieren bis zum 30. April 2015 und sind danach veraltet.

Weitere Informationen hierzu finden Sie im Folgenden:

Jobins John
quelle
3

In Swift 4.2 und Xcode 10.1:

Wenn Sie die Freundesliste von Facebook erhalten möchten, müssen Sie Ihre App zur Überprüfung in Facebook einreichen. Einige der Anmeldeberechtigungen anzeigen:

Anmeldeberechtigungen

Hier sind die zwei Schritte:

1) Zuerst muss Ihr App-Status in Live sein

2) Holen Sie sich die erforderlichen Berechtigungen von Facebook.

1) Aktivieren Sie unseren App-Status live:

  1. Gehen Sie zur Apps-Seite und wählen Sie Ihre App aus

    https://developers.facebook.com/apps/

  2. Wählen Sie oben rechts im Dashboard den Status aus .

    Geben Sie hier die Bildbeschreibung ein

  3. Senden Sie die URL der Datenschutzrichtlinie

    Geben Sie hier die Bildbeschreibung ein

  4. Kategorie auswählen

    Geben Sie hier die Bildbeschreibung ein

  5. Jetzt befindet sich unsere App im Live- Status.

    Geben Sie hier die Bildbeschreibung ein

Ein Schritt ist abgeschlossen.

2) Senden Sie unsere App zur Überprüfung:

  1. Senden Sie zuerst die erforderlichen Anfragen.

    Beispiel: user_friends, user_videos, user_posts usw.

    Geben Sie hier die Bildbeschreibung ein

  2. Wechseln Sie anschließend zur Seite Aktuelle Anforderung

    Geben Sie hier die Bildbeschreibung ein

    Beispiel: user_events

  3. Senden Sie alle Details

    Geben Sie hier die Bildbeschreibung ein

  4. So senden Sie für alle Anfragen (user_friends, user_events, user_videos, user_posts, etc.).

  5. Senden Sie schließlich Ihre App zur Überprüfung.

    Wenn Ihre Bewertung von Facebook akzeptiert wird, können Sie jetzt Kontakte usw. lesen.

iOS
quelle
3
Die user_friendsErlaubnis ist sehr begrenzt. Aus der Dokumentation von Facebook (April 2019): [Nur dies] gewährt einer App die Berechtigung, auf eine Liste von Freunden zuzugreifen, die diese App ebenfalls verwenden. Diese Erlaubnis ist auf eine begrenzte Anzahl von Partnern beschränkt und die Nutzung bedarf der vorherigen Genehmigung durch Facebook. Damit eine Person in der Freundesliste einer anderen Person angezeigt wird, müssen beide Personen ihre Freundesliste für die App freigegeben haben und dürfen diese Berechtigung beim Anmelden nicht deaktivieren.
Dearsina
2

Wie Simon erwähnte, ist dies in der neuen Facebook-API nicht möglich. Technisch gesehen können Sie dies über die Browser-Automatisierung tun.

  • Dies verstößt gegen die Facebook-Richtlinien. Je nach Land, in dem Sie leben, ist dies möglicherweise nicht legal
  • Sie müssen Ihre Anmeldeinformationen verwenden / Benutzer nach Anmeldeinformationen fragen und diese möglicherweise speichern (das Speichern von Kennwörtern, auch symmetrisch verschlüsselt, ist keine gute Idee).
  • Wenn Facebook seine API ändert, müssen Sie auch den Browser-Automatisierungscode aktualisieren (wenn Sie keine Aktualisierungen Ihrer Anwendung erzwingen können, sollten Sie die Browser-Automatisierung als Webservice bereitstellen).
  • Dies umgeht das OAuth-Konzept
  • Andererseits habe ich das Gefühl, dass ich meine Daten einschließlich der Liste meiner Freunde besitze und Facebook mich nicht daran hindern sollte, über die API auf diese zuzugreifen

Beispielimplementierung mit 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;
}

Prototyp mit Implementierung dieses Ansatzes (unter Verwendung von C # / WatiN) siehe https://github.com/svejdo1/ShadowApi . Es ermöglicht auch die dynamische Aktualisierung des Facebook-Connectors, der eine Liste Ihrer Kontakte abruft.

Ondrej Svejdar
quelle
2
Ihr Code setzt voraus, dass die App Zugriff auf den Benutzernamen und das Passwort des Benutzers hat. So funktioniert OAuth nicht und die meisten Benutzer werden ihren FB-Benutzernamen und ihr Kennwort nicht für eine Anwendung bereitstellen. Das wäre ein großes Sicherheitsrisiko.
jbustamovej
32
Dies verstößt gegen die Richtlinien von Facebook. Dieser Rat sollte nicht befolgt werden.
Simon Cross
3
Außerdem sind Sie nicht einmal sicher, die Anmeldeinformationen Ihres Benutzers in Ihrem Hack zu schützen. Für den Fall, dass sich jemand für die Verwendung Ihres Codes entscheidet, stellen Sie sicher, dass SSL verwendet wird, indem Sie die URL in https ändern.
Rogala
8
Plus eins, um es ihnen ins Gesicht zu schieben!
Skynet
12
Sie alle klingen so, als wären Facebook-Richtlinien eine Art internationales Recht, und wenn Sie es brechen, sind Sie ein Verbrecher. Sie denken auch, Facebook hat nur das Beste für den Nutzer im Sinn, was meiner Meinung nach falsch ist, wie @OndrejSvejdar sagte, denn dann würden Sie einfach wählen können, ob Sie in anderen Apps gesehen werden möchten. Ich denke, dies ist nur ein Schritt von Facebook, um das Wachstum anderer über ihre Plattform KOSTENLOS zu stören. Stattdessen sollten die Nutzer ihre Apps, Dienste, Spiele, Nachrichten usw. direkt auf Facebook entwickeln. Und zahlen Sie für Facebook-Werbung, wenn dies nicht der Fall ist.
JustGoscha
2

Versuchen Sie es /me/taggable_friends?limit=5000mit Ihrem JavaScript-Code

Oder

Probieren Sie die Graph API aus :

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

Abhishek Sharma
quelle
2
Wie ich denke - Downvotes hier sind, weil "Die Verwendung dieses Endpunkts eine Überprüfung durch Facebook erfordert und nur für den Fall verwendet werden sollte, dass Sie eine Liste von Freunden rendern, damit der Benutzer sie in einem Beitrag markieren kann." Weitere Informationen hierzu finden Sie in der ausgewählten Antwort.
Moonvader
{"data": [], "summary": {"total_count": 414}} Ich habe diesen JSON-Datenblock null und bekomme keine Freunde. Was kann ich machen?
Makvin
-1

Im v2.0 Facebook Graph API SDK oder höher, müssen Sie die Anfrage user_friends Erlaubnis von jedem Benutzer in der Zeit der Facebook - Login seit user_friends wird nicht mehr standardmäßig in jedem Login enthalten ist ; das müssen wir hinzufügen.

Jeder Benutzer muss die Berechtigung user_friends erteilen, um in der Antwort an / me / friends angezeigt zu werden .

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 {
        }
    }
}

Zum Zeitpunkt der Facebook-Anmeldung wird ein Bildschirm angezeigt, der alle Berechtigungen enthält:

Geben Sie hier die Bildbeschreibung ein

Wenn der Benutzer die Schaltfläche Weiter drückt, werden die Berechtigungen festgelegt. Wenn Sie über die Graph-API auf die Freundesliste zugreifen, werden Ihre Freunde aufgelistet, die sich wie oben bei der Anwendung angemeldet haben

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

            print(result!)
        }
    })
}

Die Ausgabe enthält die Benutzer, die zum Zeitpunkt der Anmeldung bei Ihrer Anwendung über Facebook die Berechtigung user_friends erteilt haben.

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