it-swarm.dev

Facebook Graph API v2.0 + - / me / friends возвращает пустое значение, или только друзья, которые также используют мое приложение

Я пытаюсь получить имя и идентификаторы моего друга в Graph API v2.0, но данные возвращаются пустыми:

{
  "data": [
  ]
}

Когда я использовал v1.0, все было в порядке со следующим запросом:

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

Но теперь я не могу найти друзей!

364
KasliCo

В версии 2.0 API Graph вызов /me/friends возвращает друзей этого человека, которые также используют приложение.

Кроме того, в версии 2.0 вы должны запрашивать разрешение user_friends у каждого пользователя. user_friends больше не включается по умолчанию при каждом входе в систему. Каждый пользователь должен предоставить разрешение user_friends, чтобы появиться в ответе на /me/friends. Смотрите руководство по обновлению Facebook для получения более подробной информации или просмотрите сводку ниже.

Если вы хотите получить доступ к списку друзей, не использующих приложение, есть два варианта:

  1. Если вы хотите, чтобы ваши люди отмечали своих друзей в историях, которые они публикуют в Facebook с помощью вашего приложения, вы можете использовать /me/taggable_friends API. Использование этой конечной точки требует проверки со стороны Facebook и должно использоваться только в случае, когда вы отображаете список друзей, чтобы пользователь мог пометить их в сообщении.

  2. Если ваше приложение представляет собой игру и ваша игра поддерживает Facebook Canvas, вы можете использовать конечную точку /me/invitable_friends для рендеринга - настраиваемое диалоговое окно приглашения , затем передайте токены, возвращенные этим API, стандартный диалог запросов.

В других случаях приложения больше не могут получить полный список друзей пользователя (только тех друзей, которые специально авторизовали ваше приложение, используя разрешение user_friends). Это было подтверждено Facebook как "по замыслу".

Для приложений, которые хотят разрешить людям приглашать друзей использовать приложение, вы все равно можете использовать Отправить диалог в Интернете или новый Диалог сообщений в iOS и Android .

ОБНОВЛЕНИЕ: Facebook опубликовал FAQ об этих изменениях здесь: https://developers.facebook.com/docs/apps/faq , которые объясняют все варианты, доступные для разработчиков по порядку приглашать друзей и т. д.

623
Simon Cross

Хотя ответ Саймона Кросса принят и верен, я подумал, что немного увеличу его на примере (Android) того, что необходимо сделать. Я сделаю это как можно более общим и сосредоточусь только на вопросе. Лично я закончил хранить вещи в базе данных, чтобы загрузка была гладкой, но для этого нужны CursorAdapter и ContentProvider, который здесь немного выходит за рамки.

Я пришел сюда сам, а потом подумал, что теперь ?!

Проблема

Как и user3594351 , я заметил, что данные о друзьях были пустыми. Я выяснил это с помощью FriendPickerFragment. То, что работало три месяца назад, больше не работает. Даже примеры в Facebook сломались. Итак, моя проблема была "Как мне создать FriendPickerFragment вручную?

Что не сработало

Вариант № 1 из Саймона Кросса оказался недостаточно сильным, чтобы пригласить друзей в приложение. Саймон Кросс также рекомендовал диалог запросов, но он позволял бы только 5 запросов одновременно. Диалоговое окно запросов также показывало тех же друзей во время любого входа в Facebook. Не полезно.

Что сработало (Резюме)

Вариант № 2 с тяжелой работой. Вы должны убедиться, что выполняете новые правила Facebook: 1.) Вы игра 2.) У вас есть приложение Canvas (веб-присутствие) 3.) Ваше приложение зарегистрировано в Facebook. Все сделано на сайте разработчика Facebook в настройках.

Чтобы эмулировать сборщик друзей вручную в моем приложении, я сделал следующее:

  1. Создайте вкладку, которая показывает два фрагмента. Каждый фрагмент показывает список. Один фрагмент для доступных друзей (/ me/friends) и другой для приглашенных друзей (/ me/invitable_friends). Используйте один и тот же фрагмент кода для визуализации обеих вкладок.
  2. Создайте AsyncTask, который будет получать данные о друзьях из Facebook. Как только эти данные загружены, бросьте их в адаптер, который отобразит значения на экране.

Подробнее

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

Класс FacebookFriend, который я создал

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());
        }
    }
}
17
LEO

Facebook пересмотрел свою политику сейчас. В любом случае вы не сможете получить весь список друзей, если ваше приложение не имеет реализации Canvas и если ваше приложение не является игрой. Конечно, есть также taggable_friends, но этот предназначен только для тегов.

Вы сможете получить список друзей, которые только авторизовали приложение.

Приложения, использующие Graph API 1.0, будут работать до 30 апреля 2015 года, после чего они будут устаревшими.

Смотрите ссылку ниже, чтобы получить более подробную информацию об этом

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

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

Надеюсь это поможет

12
Jobins John

Как уже упоминал Саймон, это невозможно в новом API Facebook. Чисто с технической точки зрения вы можете сделать это с помощью автоматизации браузера.

  • это противоречит политике Facebook, поэтому в зависимости от страны, в которой вы живете, это может быть не законно
  • вам придется использовать свои учетные данные/запросить учетные данные у пользователя и, возможно, сохранить их (хранение паролей, даже симметрично зашифрованных, не очень хорошая идея)
  • когда Facebook меняет свои API, вам также придется обновлять код автоматизации браузера (если вы не можете принудительно обновлять свое приложение, вы должны включить функцию автоматизации браузера как веб-сервис)
  • это обходит концепцию OAuth
  • с другой стороны, я чувствую, что я владею своими данными, включая список моих друзей, и FB не должен ограничивать меня в доступе к ним через API

Пример реализации с использованием 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;
}

Прототип с реализацией этого подхода (с использованием C #/Watin) см. https://github.com/svejdo1/ShadowApi Это также позволяет динамически обновлять коннектор Facebook, который получает список ваших контактов.

2
Ondrej Svejdar

В Swift 4.2 и Xcode 10.1

Если вы хотите получить список друзей от FB, вам нужно отправить свое приложение на рассмотрение в FB. Посмотрите некоторые разрешения на вход.

https://developers.facebook.com/docs/apps/review/login-permissions

Здесь два шага

1) Сначала ваш статус приложения должен быть в режиме реального времени

2) Получить необходимые разрешения из формы FB.

1) Включите статус нашего приложения в режиме реального времени:

  1. Перейдите на страницу приложений и выберите свое приложение

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

  1. Выберите статус в верхнем правом углу панели инструментов .

enter image description here

  1. Отправить URL политики конфиденциальности

enter image description here

  1. Выберите категорию

enter image description here

  1. Теперь наше приложение находится в режиме .

enter image description here

На шаге завершено.

2) Отправьте наше приложение на рассмотрение:

  1. Сначала отправьте необходимые запросы.

Например: user_friends, user_videos, user_posts и т.д.

enter image description here

  1. Второй перейти на страницу текущего запроса

enter image description here

Пример: user_events

  1. Отправить все детали

enter image description here

  1. Как это отправить для всех запросов (user_friends, user_events, user_videos, user_posts и т.д.).

  2. Наконец, отправьте ваше приложение на рассмотрение.

Если ваш отзыв принял форму FB, теперь вы имеете право читать контакты и т.д.

2
iOS

Попробуйте/me/taggable_friends? Limit = 5000, используя ваш код JavaScript

OR

попробуй API графа

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

Повеселись

2
Abhishek Sharma