web-dev-qa-db-ja.com

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アップグレードガイド で詳細を確認するか、以下の概要を確認してください。

アプリを使用していない友人のリストにアクセスする場合、2つのオプションがあります。

  1. あなたの人々に、あなたのアプリを使用してFacebookに公開するストーリーで友人にタグを付けさせたい場合、 /me/taggable_friends APIを使用できます。 このエンドポイントの使用にはFacebook によるレビューが必要であり、ユーザーが投稿にタグ付けできるようにするために友人のリストをレンダリングする場合にのみ使用する必要があります。

  2. アプリがゲームであり、ゲームがFacebook Canvasをサポートしている場合、/me/invitable_friendsエンドポイントを順番に使用できます カスタム招待ダイアログ をレンダリングし、このAPIによって返されたトークンを 標準リクエストダイアログに渡します。

それ以外の場合、アプリはユーザーの友達の完全なリストを取得できなくなります(user_friends権限を使用してアプリを明確に承認した友達のみ)。 これはFacebookによって「設計」として確認されました。

ユーザーが友人を招待してアプリを使用できるようにしたいアプリの場合、 Send Dialog on Web または新しい Message Dialog on iOS および Android

更新:Facebookは、これらの変更に関するFAQを公開しています: https://developers.facebook.com/docs/apps/faq 友人などを招待するために開発者に.

625
Simon Cross

Simon Crossの 答えは受け入れられて正しいが、私はやるべきことの例(Android)で少しそれを強化するだろうと思った。私はできる限り一般的にして、問題だけに焦点を当てます。個人的にはデータベースに物事を保存することを決心したのでロードはスムーズでした、しかしそれはここの範囲外であるCursorAdapterとContentProviderを必要とします。

私は自分でここに来て、そして今、何を考えましたか?

問題

user3594351 と同じように、友達のデータが空白であることに気付きました。私はFriendPickerFragmentを使ってこれを見つけました。 3か月前に機能したものは、もう機能しません。 Facebookの例でさえも壊れた。だから私の問題は 'どうやってFriendPickerFragmentを手で作成するのですか?'でした。

うまくいかなかったこと

Simon Cross からのオプション#1は、友達をアプリに招待するほど強力ではありませんでした。 Simon Cross はRequestsダイアログも推奨しましたが、それは一度に5つの要求しか許さないでしょう。セッションがログインしている間に、リクエストダイアログにも同じ友達が表示されました。役に立ちません。

何が働いたのか(要約)

いくつかの努力とオプション#2。あなたはあなたがFacebookの新しいルールを満たすことを確認しなければなりません:1.)あなたはゲームです。2.)Canvasアプリケーション(Web Presence)を持っています。3.)あなたはFacebookに登録されています。設定はすべてFacebook開発者Webサイトで行われます。

私のアプリの中で友達ピッカーを手でエミュレートするために、私は以下をしました:

  1. 2つのフラグメントを表示するタブアクティビティを作成します。各フラグメントはリストを示しています。利用可能な友人(/ me/friends)と招待可能な友人(/ me/invitable_friends)の別のフラグメントです。同じフラグメントコードを使用して両方のタブをレンダリングします。
  2. Facebookから友達データを取得するAsyncTaskを作成します。そのデータがロードされたら、それをアダプタに投げてアダプタに投げ、値を画面に表示させます。

詳細

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は現在ポリシーを修正しました。あなたのAppがCanvasを実装していない場合やあなたのAppがゲームではない場合は、とにかく全体の友達リストを取得することはできません。もちろん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を変更したときは、ブラウザの自動化コードも更新する必要があります(アプリケーションの更新を強制できない場合は、ブラウザの自動化部分をWebサービスとして公開する必要があります)。
  • これは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 を参照してください。

2
Ondrej Svejdar

Swift 4.2とXcode 10.1では

FBから友達リストを取得したい場合は、FBでレビューするためにアプリを送信する必要があります。ログイン許可を参照してください。

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

ここに2つのステップ

1)まずあなたのアプリのステータスはLiveになっている必要があります

2)必要な権限フォームFB)を取得します。

1)ライブのアプリステータスを有効にします。

  1. アプリページに移動し、あなたのアプリを選択)

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

  1. ダッシュボード)の右上にあるステータスを選択します。

enter image description here

  1. 送信プライバシーポリシーurl

enter image description here

  1. categoryを選択してください

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