it-swarm.cn

Facebook Graph API v2.0 + - /me/friends返回空,或只有使用我的应用程序的朋友

我试图用Graph API v2.0获取我的朋友姓名和ID,但数据返回空:

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

但现在我不能得到朋友!

363
KasliCo

在Graph API的v2.0中,调用/me/friends会返回同时使用该应用程序的人的朋友。

此外,在v2.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 解释了开发人员可以选择的所有选项以邀请朋友等等.

622
Simon Cross

虽然Simon Cross's答案被接受并且正确,但我想我会用一个例子(Android)来加强它需要做些什么。我将尽可能保持一般,并专注于问题。我个人最终将数据存储在一个数据库中,因此加载很顺利,但这需要一个CursorAdapter和ContentProvider,这里有点超出范围。

我自己来到这里然后想,现在是什么?!

问题

就像user3594351一样,我注意到朋友数据是空白的。我通过使用FriendPickerFragment找到了这个。三个月前有效的,不再有效。甚至Facebook的例子都破了。所以我的问题是'如何手动创建FriendPickerFragment?

什么没有奏效

来自Simon Cross的选项#1不足以邀请朋友加入应用。 Simon Cross还推荐了“请求”对话框,但这样一次只允许5个请求。在任何给定的Facebook登录会话期间,请求对话框也显示了相同的朋友。没有用。

工作成果(摘要)

选项#2有一些艰苦的工作。你必须确保你符合Facebook的新规则:1。)你是一个游戏2.)你有一个Canvas应用程序(Web Presence)3。)你的应用程序是在Facebook注册的。全部在Facebook开发者网站上完成设置。

要在我的应用程序中手动模拟朋友选择器,我执行了以下操作:

  1. 创建一个显示两个片段的选项卡活动。每个片段都显示一个列表。一个片段为可用的朋友(/我/朋友)和另一个片段为可邀请的朋友(/ 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的应用程序将在2015年4月30日之前运行,之后将不推荐使用。

请参阅以下链接以获取更多详细信息

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

正如Simon提到的,这在新的facebook API中是不可能的。 从技术上说 你可以通过浏览器自动化来实现。

  • 这是违反Facebook政策的,因此根据您所居住的国家/地区而言,这可能不合法
  • 你将不得不使用你的凭证/要求用户提供凭证并可能存储它们(存储密码甚至对称加密也不是一个好主意)
  • 当facebook改变他们的api时,你也必须更新浏览器自动化代码(如果你不能强制更新你的应用程序,你应该把浏览器自动化作为webservice)
  • 这是绕过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)首先你的 app状态必须是Live

2)获取 必需的权限 表单FB。

1)实时启用我们的应用状态:

  1. 应用页面 并选择 您的应用

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

  1. 仪表板 中选择右上角的状态。

enter image description here

  1. 提交 隐私政策网址

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

使用您的javascript代码尝试/ me/taggable_friends?limit = 5000

OR

试试图API

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

玩得开心

2
Abhishek Sharma