API đồ thị Facebook v2.0 + - / tôi / bạn bè trả về sản phẩm nào hoặc chỉ những người bạn cũng sử dụng ứng dụng của tôi


366

Tôi đang cố gắng lấy tên và id của bạn bè bằng Graph API v2.0, nhưng dữ liệu trả về trống:

{
  "data": [
  ]
}

Khi tôi đang sử dụng v1.0, mọi thứ đều ổn với yêu cầu sau:

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

Nhưng bây giờ tôi không thể có được bạn bè!


có thể khắc phục vấn đề này stackoverflow.com/a/25584013/2529087
java.quaso

Câu trả lời:


627

Trong v2.0 của API đồ thị, việc gọi /me/friendstrả về bạn bè của những người cũng sử dụng ứng dụng.

Ngoài ra, trong v2.0, bạn phải yêu cầu sự user_friendscho phép của mỗi người dùng. user_friendskhông còn được bao gồm theo mặc định trong mỗi lần đăng nhập. Mỗi người dùng phải cấp user_friendsquyền để xuất hiện trong phản hồi /me/friends. Xem hướng dẫn nâng cấp của Facebook để biết thêm thông tin chi tiết hoặc xem lại tóm tắt bên dưới.

Nếu bạn muốn truy cập danh sách bạn bè không sử dụng ứng dụng, có hai tùy chọn:

  1. Nếu bạn muốn cho phép mọi người gắn thẻ bạn bè của họ trong các câu chuyện mà họ xuất bản lên Facebook bằng Ứng dụng của bạn, bạn có thể sử dụng/me/taggable_friendsAPI. Việc sử dụng điểm cuối này yêu cầu Facebook xem xét và chỉ nên được sử dụng cho trường hợp bạn hiển thị danh sách bạn bè để cho phép người dùng gắn thẻ họ trong bài đăng.

  2. Nếu Ứng dụng của bạn là Trò chơi VÀ Trò chơi của bạn hỗ trợ Facebook Canvas , bạn có thể sử dụng/me/invitable_friendsđiểm cuối để hiển thị hộp thoại mời tùy chỉnh , sau đó chuyển mã thông báo được API này trả về cho Hộp thoại Yêu cầu tiêu chuẩn.

Trong các trường hợp khác, ứng dụng không còn có thể truy xuất danh sách đầy đủ của bạn bè người dùng (chỉ những người bạn đã ủy quyền cụ thể cho ứng dụng của bạn bằng user_friendsquyền). Điều này đã được Facebook xác nhận là "theo thiết kế".

Đối với các ứng dụng muốn cho phép mọi người mời bạn bè sử dụng một ứng dụng, bạn vẫn có thể sử dụng Hộp thoại Gửi trên Web hoặc Hộp thoại Tin nhắn mới trên iOSAndroid .

CẬP NHẬT: Facebook đã xuất bản Câu hỏi thường gặp về những thay đổi này tại đây: https://developers.facebook.com/docs/apps/faq giải thích tất cả các tùy chọn có sẵn cho nhà phát triển để mời bạn bè, v.v.


Bất kỳ tin tức kể từ lần chỉnh sửa cuối cùng của bạn hoặc chúng tôi ở cùng một trang?
Ilya Gazman

Không thể nhìn thấy taggable_friendstrong các mục để xem xét trình.
AlikElzin-kilaka

7
Tôi không thể hiểu tại sao họ phải hạn chế nó nhiều như vậy. Tôi có nghĩa là hệ thống cũ là quá dễ sử dụng nhưng hệ thống này là vô dụng. Xem hồ sơ công khai của tất cả bạn bè của bạn chắc chắn sẽ không phải là một vấn đề riêng tư. Trừ khi bạn nghĩ rằng kết nối của tình bạn là riêng tư (nhưng một lần nữa tại sao nó không phải là trong trường hợp của bạn bè có thể gắn thẻ). Đây không phải là một động thái nhằm hạn chế lạm dụng quyền riêng tư mà là một tác dụng phụ, họ muốn đóng khả năng cho các nhà phát triển bình thường (không liên kết với facebook) phát triển doanh nghiệp của họ bằng dữ liệu facebook.
Daniel Sharp

3
Gần đây, Facebook đã công bố những thay đổi lớn đối với dữ liệu hiện có: xem thay đổi . Các taggable_friendsbây giờ trở về không có gì. Ngoài ra, xem xét đăng nhập là cần thiết trước khi bạn có thể được cấp user_friendsphép.
Duncan Jones

Điểm cung cấp API là gì nếu nó không cho phép bạn thực hiện một nhiệm vụ cơ bản như liệt kê bạn bè?
6infinity8

17

Mặc dù câu trả lời của Simon Cross được chấp nhận và chính xác, tôi nghĩ rằng tôi sẽ tăng cường một chút với một ví dụ (Android) về những gì cần phải làm. Tôi sẽ giữ nó chung chung nhất có thể và chỉ tập trung vào câu hỏi. Cá nhân tôi cố gắng lưu trữ mọi thứ trong cơ sở dữ liệu để quá trình tải diễn ra suôn sẻ, nhưng điều đó đòi hỏi phải có CoderAd CHƯƠNG và ContentProvider, một thứ nằm ngoài phạm vi ở đây.

Tôi đến đây một mình và sau đó nghĩ, bây giờ thì sao?!

Vấn đề

Giống như user3594351 , tôi nhận thấy dữ liệu bạn bè trống. Tôi đã tìm thấy điều này bằng cách sử dụng FriendPickerFragment. Những gì làm việc ba tháng trước, không còn làm việc. Ngay cả các ví dụ của Facebook đã phá vỡ. Vì vậy, vấn đề của tôi là 'Làm cách nào để tạo FriendPickerFragment bằng tay?

Những gì không làm việc

Tùy chọn số 1 từ Simon Cross không đủ mạnh để mời bạn bè vào ứng dụng. Simon Cross cũng đề xuất Hộp thoại Yêu cầu, nhưng điều đó sẽ chỉ cho phép năm yêu cầu cùng một lúc. Hộp thoại yêu cầu cũng hiển thị cùng những người bạn trong bất kỳ phiên đăng nhập nào của Facebook. Không hữu ích.

Những gì đã làm việc (Tóm tắt)

Lựa chọn số 2 với một số công việc khó khăn. Bạn phải đảm bảo hoàn thành các quy tắc mới của Facebook: 1.) Bạn là một trò chơi 2.) Bạn có ứng dụng Canvas (Web Presence) 3.) Ứng dụng của bạn được đăng ký với Facebook. Tất cả được thực hiện trên trang web của nhà phát triển Facebook trong Cài đặt .

Để giả lập trình chọn bạn bè bằng tay trong ứng dụng của tôi, tôi đã làm như sau:

  1. Tạo một hoạt động tab cho thấy hai mảnh. Mỗi mảnh hiển thị một danh sách. Một đoạn dành cho bạn bè có sẵn ( / tôi / bạn bè ) và một đoạn khác dành cho những người bạn mời ( / tôi / invitable_friends ). Sử dụng cùng một đoạn mã để kết xuất cả hai tab.
  2. Tạo một AsyncTask sẽ lấy dữ liệu bạn bè từ Facebook. Khi dữ liệu đó được tải, hãy ném nó vào bộ điều hợp sẽ hiển thị các giá trị cho màn hình.

Chi tiết

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

Lớp FacebookFriend tôi đã tạo

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

20
Còn đối với các ứng dụng không chơi game thì sao? Một trang web hẹn hò ... một trò chơi để tìm người, một ứng dụng để tìm nhà hàng ... một trò chơi để tìm nhà hàng, v.v. bạn có ý tưởng. Vì vậy, điều này thực sự gần với các trò chơi hay đây chỉ là một cách buộc bạn phải đặt một ứng dụng bên trong Facebook và chi tiền cho nền tảng quảng cáo của họ? Ai sẽ quyết định trò chơi là gì? Ai quyết định rằng ứng dụng của bạn thực sự là một trò chơi hay không? Đừng hiểu sai về điều này nhưng đối với tôi, việc chặn các ứng dụng không chơi game là vô nghĩa trừ khi bạn chỉ muốn ép buộc họ sử dụng hệ sinh thái facebook.
Mário

@ Mário Đó là ý định của Facebook dưới mui xe. Bạn có thể đặt bất cứ thứ gì và đánh dấu nó là một trò chơi vì họ không quan tâm liệu đó có thực sự là một trò chơi hay không. tất cả những gì họ quan tâm là nhận tiền từ túi của bạn.
cá cát

12

Facebook đã sửa đổi chính sách của họ bây giờ. Dù sao thì bạn cũng không thể có được toàn bộ danh sách bạn bè nếu ứng dụng của bạn không có triển khai Canvas và nếu ứng dụng của bạn không phải là một trò chơi. Tất nhiên cũng có taggable_friends, nhưng cái đó chỉ để gắn thẻ.

Bạn sẽ chỉ có thể kéo danh sách bạn bè đã ủy quyền ứng dụng.

Các ứng dụng đang sử dụng API API 1.0 sẽ hoạt động cho đến ngày 30 tháng 4 năm 2015 và sau đó, nó sẽ không còn hoạt động nữa.

Xem phần sau để biết thêm chi tiết về điều này:


3

Trong Swift 4.2 và Xcode 10.1:

Nếu bạn muốn lấy danh sách bạn bè từ Facebook, bạn cần gửi ứng dụng của mình để xem xét trong Facebook. Xem một số Quyền đăng nhập:

Quyền đăng nhập

Đây là hai bước:

1) Trước tiên, trạng thái ứng dụng của bạn phải ở chế độ Live

2) Nhận quyền yêu cầu từ Facebook.

1) Kích hoạt trạng thái ứng dụng của chúng tôi trực tiếp:

  1. Chuyển đến trang ứng dụng và chọn ứng dụng của bạn

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

  2. Chọn trạng thái ở trên cùng bên phải trong Bảng điều khiển .

    Nhập mô tả hình ảnh ở đây

  3. Gửi URL chính sách bảo mật

    Nhập mô tả hình ảnh ở đây

  4. Chọn danh mục

    Nhập mô tả hình ảnh ở đây

  5. Bây giờ ứng dụng của chúng tôi đang ở trạng thái Live .

    Nhập mô tả hình ảnh ở đây

Một bước được hoàn thành.

2) Gửi ứng dụng của chúng tôi để xem xét:

  1. Đầu tiên gửi yêu cầu.

    Ví dụ: user_friends, user_ideo, user_posts, v.v.

    Nhập mô tả hình ảnh ở đây

  2. Thứ hai, đi đến trang Yêu cầu hiện tại

    Nhập mô tả hình ảnh ở đây

    Ví dụ: user_events

  3. Gửi tất cả các chi tiết

    Nhập mô tả hình ảnh ở đây

  4. Giống như điều này gửi cho tất cả các yêu cầu (user_friends, user_events, user_ideo, user_posts, v.v.).

  5. Cuối cùng gửi ứng dụng của bạn để xem xét.

    Nếu đánh giá của bạn được chấp nhận từ phía Facebook, bạn hiện đủ điều kiện để đọc danh bạ, v.v.


3
Sự user_friendscho phép rất hạn chế. Từ tài liệu của Facebook (tháng 4 năm 2019): [Chỉ điều này] cấp quyền cho ứng dụng truy cập danh sách bạn bè cũng sử dụng ứng dụng nói trên. Quyền này được giới hạn trong một nhóm đối tác hạn chế và việc sử dụng cần có sự chấp thuận trước của Facebook. Để một người hiển thị trong danh sách bạn bè của người khác, cả hai người phải chia sẻ danh sách bạn bè của họ với ứng dụng và không bị vô hiệu hóa quyền này trong quá trình đăng nhập.
dearsina

2

Như Simon đã đề cập, điều này là không thể trong API Facebook mới. Nói một cách kỹ thuật, bạn có thể làm điều đó thông qua trình duyệt tự động.

  • Điều này trái với chính sách của Facebook, vì vậy tùy thuộc vào quốc gia bạn sống, điều này có thể không hợp pháp
  • bạn sẽ phải sử dụng thông tin đăng nhập của mình / yêu cầu người dùng xác thực và có thể lưu trữ chúng (lưu trữ mật khẩu thậm chí được mã hóa đối xứng không phải là một ý tưởng hay)
  • khi Facebook thay đổi API của họ, bạn cũng sẽ phải cập nhật mã tự động hóa trình duyệt (nếu bạn không thể buộc cập nhật ứng dụng của mình, bạn nên đặt phần tự động hóa trình duyệt ra làm dịch vụ web)
  • đây là bỏ qua khái niệm OAuth
  • mặt khác, cảm giác của tôi là tôi đang sở hữu dữ liệu của mình bao gồm danh sách bạn bè và Facebook không nên hạn chế tôi truy cập thông qua API

Triển khai mẫu bằng 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;
}

Nguyên mẫu với việc thực hiện phương pháp này (sử dụng C # / WatiN) xem https://github.com/svejdo1/ShadowApi . Nó cũng cho phép cập nhật động của trình kết nối Facebook đang truy xuất danh sách các liên hệ của bạn.


2
Mã của bạn giả định rằng ứng dụng có quyền truy cập vào tên người dùng và mật khẩu của người dùng. Đây không phải là cách OAuth hoạt động và hầu hết người dùng sẽ không cung cấp tên người dùng và mật khẩu FB của họ cho một ứng dụng. Đó sẽ là một rủi ro bảo mật rất lớn.
jbustamovej

32
Điều này trái với chính sách của Facebook. Lời khuyên này không nên được tuân theo.
Simon Cross

3
Một lưu ý khác, bạn thậm chí không an toàn bảo vệ thông tin đăng nhập của người dùng trong vụ hack của mình. Chỉ trong trường hợp ai đó quyết định sử dụng mã của bạn, vui lòng đảm bảo rằng nó sử dụng SSL bằng cách thay đổi uri thành https.
Rogala

8
Thêm một cái để đẩy nó lên mặt!
Skynet

12
Tất cả các bạn có vẻ như các chính sách của Facebook là một loại Luật quốc tế và bằng cách phá vỡ nó, bạn là một tội phạm. Ngoài ra, bạn nghĩ rằng Facebook chỉ có điều tốt nhất cho người dùng, điều mà tôi nghĩ là sai như @OndrejSvejdar đã nói, bởi vì sau đó họ sẽ chỉ cho phép bạn chọn nếu bạn muốn thấy trong các ứng dụng khác. Tôi nghĩ rằng đây chỉ là một động thái của Facebook để phá vỡ sự phát triển của người khác thông qua nền tảng của họ MIỄN PHÍ. Thay vào đó, mọi người nên bắt đầu phát triển ứng dụng, dịch vụ, trò chơi, tin tức, vv trực tiếp trên Facebook. Và trả tiền cho quảng cáo Facebook khi họ sẽ không.
JustGoscha

2

Hãy thử /me/taggable_friends?limit=5000sử dụng mã JavaScript của bạn

Hoặc là

hãy thử API đồ thị :

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


2
Theo tôi nghĩ - downvote ở đây là vì "Việc sử dụng điểm cuối này yêu cầu Facebook xem xét và chỉ nên được sử dụng cho trường hợp bạn hiển thị danh sách bạn bè để cho phép người dùng gắn thẻ họ trong bài đăng." Bạn có thể đọc thêm về điều này trong câu trả lời được lựa chọn.
moonvader

{"data": [], "Tóm tắt": {"Total_count": 414}} tôi đã nhận được khối dữ liệu json này null không có bạn bè. Tôi có thể làm gì?
Makvin

-1

Trong API SDK đồ thị Facebook v2.0 trở lên, bạn phải yêu cầu quyền của user_friends từ mỗi người dùng trong thời gian đăng nhập Facebook vì user_friends không còn được bao gồm theo mặc định trong mỗi lần đăng nhập; chúng ta phải thêm điều đó

Mỗi người dùng phải cấp quyền cho user_friends để xuất hiện trong phản hồi cho / tôi / bạn bè .

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

Vì vậy, tại thời điểm đăng nhập Facebook, nó sẽ nhắc với một màn hình chứa tất cả các quyền:

Nhập mô tả hình ảnh ở đây

Nếu người dùng nhấn nút Tiếp tục , quyền sẽ được đặt. Khi bạn truy cập danh sách bạn bè bằng API đồ thị, những người bạn của bạn đã đăng nhập vào ứng dụng như trên sẽ được liệt kê

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

            print(result!)
        }
    })
}

Đầu ra sẽ chứa những người dùng đã cấp quyền user_friends tại thời điểm đăng nhập vào ứng dụng của bạn thông qua Facebook.

{
    data = (
             {
                 id = xxxxxxxxxx;
                 name = "xxxxxxxx";
             }
           );
    paging = {
        cursors = {
            after = xxxxxx;
            before = xxxxxxx;
        };
    };
    summary = {
        "total_count" = 8;
    };
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.