Facebook Graph API v2.0 +-/ me / friendsが空、または私のアプリケーションを使用している友達のみを返す


366

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

でも今は友達が取れない!


この問題を解決する可能性あり stackoverflow.com/a/25584013/2529087
java.quaso 2014

回答:


627

Graph APIのv2.0では、呼び出し/me/friendsにより、アプリを使用しているユーザーの友達が返されます。

また、v2.0では、user_friends各ユーザーに権限をリクエストする必要があります。user_friendsすべてのログインにデフォルトで含まれなくなりました。user_friendsへの応答に表示するには、各ユーザーが権限を付与する必要があり/me/friendsます。詳細については、Facebookアップグレードガイドを参照するか、以下の概要を確認してください。

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

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

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

他の場合では、アプリはユーザーの友達の完全なリストを取得できなくなります(user_friends許可を使用してアプリを特別に承認した友達のみ)。これはFacebookによって「仕様による」と確認されています。

友だちを招待してアプリを使用することを希望するアプリの場合は、引き続きウェブ上で送信ダイアログまたはiOSおよびAndroid の新しいメッセージダイアログを使用できます。

更新:Facebookはこれらの変更に関するFAQをここに公開しました:https : //developers.facebook.com/docs/apps/faqこれは、友達を招待するために開発者が利用できるすべてのオプションを説明しています。


あなたの最後の編集以降のニュース、または同じページにいる私たち?
Ilya Gazman

taggable_friendsレビュー提出用のアイテムにが表示されません。
AlikElzin-kilaka 2017

7
なぜそんなに制限しなければならないのか理解できません。古いシステムは酷使されすぎていたが、これはほとんど役に立たなかった。すべての友達の公開プロフィールを見ても、プライバシーの問題にはならないでしょう。友情のつながりはそれ自体がプライベートだと思う場合を除いて(ただし、タグ付け可能な友達の場合はなぜそうでないのか)。これは副作用であるプライバシーの悪用を制限する動きではなく、通常の(Facebookに所属していない)開発者がFacebookのデータを使用してビジネスを成長させる能力を閉鎖したかったのです。
Daniel Sharp

3
Facebookは最近、利用可能なデータに大きな変更を公開しました。変更ログを参照してください。taggable_friends今は何も返しません。また、user_friends許可を得る前に、ログインの確認が必要です。
ダンカンジョーンズ

友だちの一覧表示などの基本的なタスクを実行できないAPIを提供する意味は何ですか?
6infinity8

17

けれどもサイモンクロスの答えは受け入れられ、正しいされて、私は私が何をすべきかの例(アンドロイド)で少しそれをアップ牛肉だろうと思いました。私はそれをできる限り一般的に保ち、質問だけに焦点を当てます。個人的にはデータベースへの格納を完了したため、読み込みはスムーズに行われましたが、ここでは少し範囲外のCursorAdapterとContentProviderが必要です。

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

問題

user3594351と同様に、友達のデータが空白であることに気づきました。FriendPickerFragmentを使用してこれを見つけました。3か月前は機能していたが、機能しなくなった。Facebookの例でさえ破られました。したがって、私の問題は「FriendPickerFragmentを手動で作成するにはどうすればよいですか?」

うまくいかなかったこと

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

効果のあったもの(概要)

難しい作業を伴うオプション#2。Facebookの新しいルールを満たしていることを確認する必要があります:1.)ゲームである2.)Canvasアプリ(Webプレゼンス)を持っている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 Facebook JSON: " + e.getLocalizedMessage());
        }
    }
}

20
ゲーム以外のアプリはどうですか?出会い系サイト…人を探すゲーム、レストランを探すアプリ…レストランを探すゲームなど…。これは本当にゲームに近いのですか、それともFacebook内にアプリを配置し、広告プラットフォームにお金を費やすことを強制する方法にすぎませんか?ゲームとは何かを決めるのは誰ですか?アプリが実際にゲームであるかどうかはだれが判断しましたか?これについて誤解しないでください。ただし、Facebookエコシステムを使用するように強制したい場合を除き、ゲーム以外のアプリをブロックしても意味がありません。
マリオ2014年

@マリオそれは裏でFacebookの意図です。本当にゲームかどうかは気にしないので、何でも置いてゲームとしてマークすることができます。彼らが気にするのはあなたのポケットからお金を稼ぐことだけです。
Sandalone

12

Facebookは現在、ポリシーを改訂しています。アプリにCanvasが実装されておらず、アプリがゲームではない場合、フレンドリスト全体を取得することはできません。もちろんtaggable_friendsもありますが、これはタグ付け専用です。

アプリを承認した友達のリストのみを取得できます。

Graph API 1.0を使用しているアプリは、2015年4月30日まで機能し、それ以降はサポートが終了します。

詳細については、以下を参照してください。


3

スウィフト 4.2とXcodeの 10.1:

Facebookから友達リストを取得する場合は、Facebookでのレビューのためにアプリを送信する必要があります。ログイン権限の一部をご覧ください。

ログイン権限

2つの手順は次のとおりです。

1)最初にアプリのステータスがLiveである必要があります

2)Facebookから必要な権限を取得します。

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

  1. アプリのページに移動してアプリを選択します

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

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

    ここに画像の説明を入力してください

  3. 送信プライバシーポリシーのURLを

    ここに画像の説明を入力してください

  4. カテゴリーを選択

    ここに画像の説明を入力してください

  5. これで、アプリはLiveステータスになりました。

    ここに画像の説明を入力してください

1つのステップが完了しました。

2)レビューのためにアプリを送信します。

  1. 最初に必要なリクエストを送信します。

    例:user_friends、user_videos、user_postsなど。

    ここに画像の説明を入力してください

  2. 次に、現在のリクエストページに移動します

    ここに画像の説明を入力してください

    例:user_events

  3. すべての詳細を送信

    ここに画像の説明を入力してください

  4. このように、すべてのリクエスト(user_friends、user_events、user_videos、user_postsなど)に対して送信します。

  5. 最後に、レビューのためにアプリを送信します。

    Facebook側からレビューが承認された場合、連絡先などを読むことができます。


3
user_friends権限は非常に限られています。Facebookのドキュメントから(2019年4月):[これのみ]アプリは、同じアプリを使用している友達のリストにアクセスすることを許可されます。この許可は限られたパートナーのセットに制限されており、使用にはFacebookによる事前の承認が必要です。ある人が別の人の友達リストに表示されるようにするには、両方の人が友達のリストをアプリと共有し、ログイン中にこの権限を無効にしていない必要があります。
dearsina

2

Simonが述べたように、これは新しいFacebook APIでは不可能です。純粋に技術的に言えば、ブラウザの自動化によってそれを行うことができます。

  • これはFacebookのポリシーに反するため、お住まいの国によっては合法ではない場合があります
  • 資格情報を使用するか、ユーザーに資格情報を要求し、場合によってはそれらを保存する必要があります(対称的に暗号化されていてもパスワードを保存することはお勧めしません)
  • FacebookがAPIを変更したら、ブラウザーの自動化コードも更新する必要があります(アプリケーションの更新を強制できない場合は、ブラウザーの自動化をWebサービスとして提供する必要があります)
  • これはOAuthの概念をバイパスしています
  • 一方、私の気持ちは私の友人のリストを含む私のデータを所有しているとFacebookは私が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
コードは、アプリがユーザーのユーザー名とパスワードにアクセスできることを前提としています。これはOAuthの仕組みではなく、ほとんどのユーザーはFBのユーザー名とパスワードをアプリケーションに提供しません。これは大きなセキュリティリスクになります。
jbustamovej 14

32
これはFacebookのポリシーに反しています。このアドバイスに従うべきではありません。
Simon Cross、

3
別の注記では、ハッキングでユーザーの資格情報を保護することさえ安全ではありません。誰かがあなたのコードを使用することを決定した場合に備えて、URIをhttpsに変更して、コードがSSLを使用していることを確認してください。
Rogala 2014

8
プラス1つで、顔を押し上げることができます。
スカイネット2015年

12
Facebookのポリシーはなんらかの国際法のようであり、それを破ることで犯罪者になります。また、Facebookはユーザーにとって最良のものだけを考えていると思いますが、@ OndrejSvejdarが述べたように、それは間違っていると思います。これはFacebookがプラットフォームを通じて無料で他者の成長を妨げようとしている動きだと思います。代わりに、人々は直接Facebookでアプリ、サービス、ゲーム、ニュースなどの開発を始めるべきです。そして、彼らがそうしない場合は、Facebook広告の料金を支払います。
JustGoscha 2015

2

試す /me/taggable_friends?limit=5000JavaScriptコードを使用しててください

または

グラフAPIを試してください:

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


2
私が思うに-ここでの反対投票は、「このエンドポイントを使用するにはFacebookによるレビューが必要であり、ユーザーが投稿にタグ付けできるように友達のリストをレンダリングする場合にのみ使用する必要がある」ためです。これについて詳しくは、選択した回答をご覧ください。
ムーンベイダー2017

{"data":[]、 "summary":{"total_count":414}}このjsonデータブロックを取得しましたnullフレンドを取得しません。私に何ができる?
Makvin

-1

Facebook SDK Graph API v2.0 以降では、すべてのログインにデフォルトでuser_friendsが含まれなくなったため、Facebookログイン時に各ユーザーにuser_friends権限をリクエストする必要があります。追加する必要があります。

/ me / friendsへの応答に表示するには、各ユーザーがuser_friends権限を付与する必要があります

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

そのため、Facebookのログイン時に、すべての権限を含む画面が表示されます。

ここに画像の説明を入力してください

ユーザーが[ 続行 ]ボタンを押すと、アクセス許可が設定されます。Graph APIを使用して友達リストにアクセスすると、上記のようにアプリケーションにログインした友達がリストされます

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

            print(result!)
        }
    })
}

出力には、Facebookを介してアプリケーションにログインしたときにuser_friends権限を付与したユーザーが含まれます。

{
    data = (
             {
                 id = xxxxxxxxxx;
                 name = "xxxxxxxx";
             }
           );
    paging = {
        cursors = {
            after = xxxxxx;
            before = xxxxxxx;
        };
    };
    summary = {
        "total_count" = 8;
    };
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.