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);
}
}];
Но теперь я не могу найти друзей!
8 ответов
В v2.0 API Graph, вызывая /me/friends
возвращает друзей человека, которые также используют приложение.
Кроме того, в версии 2.0 вы должны запросить user_friends
разрешение от каждого пользователя. user_friends
больше не включается по умолчанию в каждый логин. Каждый пользователь должен предоставить user_friends
разрешение для того, чтобы появиться в ответе на /me/friends
, См. Руководство по обновлению Facebook для получения более подробной информации или ознакомьтесь с кратким изложением ниже.
Если вы хотите получить доступ к списку друзей, не использующих приложение, есть два варианта:
Если вы хотите, чтобы ваши люди отмечали своих друзей в историях, которые они публикуют в Facebook с помощью вашего приложения, вы можете использовать
/me/taggable_friends
API. Использование этой конечной точки требует проверки со стороны Facebook и должно использоваться только в том случае, когда вы отображаете список друзей, чтобы позволить пользователю отметить их в сообщении.Если ваше приложение является игрой и ваша игра поддерживает Facebook Canvas, вы можете использовать
/me/invitable_friends
конечной точки, чтобы отобразить настраиваемое диалоговое окно приглашения, а затем передать токены, возвращенные этим API, в стандартный диалог запросов.
В других случаях приложения больше не могут получить полный список друзей пользователя (только те друзья, которые специально авторизовали ваше приложение, используя user_friends
разрешение). Facebook подтвердил это как "дизайн".
Для приложений, которые хотят разрешить людям приглашать друзей использовать приложение, вы все равно можете использовать Диалог отправки в Интернете или новый Диалог сообщений на iOS и Android.
ОБНОВЛЕНИЕ: Facebook опубликовал FAQ об этих изменениях здесь: https://developers.facebook.com/docs/apps/faq котором объясняются все опции, доступные разработчикам для приглашения друзей и т. Д.
Хотя ответ Саймона Кросса принят и верен, я подумал, что немного подкреплю его примером (android) того, что нужно сделать. Я сделаю это как можно более общим и сосредоточусь только на вопросе. Лично я закончил хранить вещи в базе данных, чтобы загрузка была гладкой, но для этого нужны CursorAdapter и ContentProvider, который здесь немного выходит за рамки.
Я пришел сюда сам, а потом подумал, что теперь?!
Проблема
Так же, как user3594351, я заметил, что данные друзей были пустыми. Я выяснил это с помощью FriendPickerFragment. То, что работало три месяца назад, больше не работает. Даже примеры в Facebook сломались. Итак, моя проблема была "Как мне создать FriendPickerFragment вручную?
Что не сработало
Вариант № 1 от Саймона Кросса оказался недостаточно сильным, чтобы пригласить друзей в приложение. Саймон Кросс также рекомендовал Диалог запросов, но он позволял только 5 запросов одновременно. Диалог запросов также показывал одних и тех же друзей во время любого входа в Facebook. Не полезно.
Что сработало (резюме)
Вариант № 2 с тяжелой работой. Вы должны убедиться, что выполняете новые правила Facebook: 1.) Вы игра 2.) У вас есть приложение Canvas (веб-присутствие) 3.) Ваше приложение зарегистрировано в Facebook. Все сделано на сайте разработчика Facebook в настройках.
Чтобы эмулировать сборщик друзей вручную в моем приложении, я сделал следующее:
- Создайте вкладку, которая показывает два фрагмента. Каждый фрагмент показывает список. Один фрагмент для доступных друзей (/me/friends) и другой для приглашенных друзей (/me/invitable_friends). Используйте один и тот же фрагмент кода для визуализации обеих вкладок.
- Создайте 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());
}
}
}
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
Надеюсь это поможет
В Swift 4.2 и Xcode 10.1
Если вы хотите получить список друзей от FB, вам нужно отправить свое приложение на рассмотрение в FB. Посмотрите некоторые разрешения на вход.
https://developers.facebook.com/docs/apps/review/login-permissions
Здесь два шага
1) Сначала статус вашего приложения должен быть в Live
2) Получить необходимые разрешения формы FB.
1) Включите статус нашего приложения в режиме реального времени:
- Перейдите на страницу приложений и выберите свое приложение
https://developers.facebook.com/apps/
- Выберите статус в правом верхнем углу в Dashboard.
- Отправить URL политики конфиденциальности
- Выберите категорию
- Теперь наше приложение в живом состоянии.
На шаге завершено.
2) Отправьте наше приложение на рассмотрение:
- Сначала отправьте необходимые запросы.
Например: user_friends, user_videos, user_posts и т. Д.
- Второй перейти на страницу текущего запроса
Пример: user_events
- Отправить все детали
Как это отправить для всех запросов (user_friends, user_events, user_videos, user_posts и т. Д.).
Наконец, отправьте ваше приложение на рассмотрение.
Если ваш отзыв принял форму FB, теперь вы имеете право читать контакты и т. Д.
Попробуйте /me/taggable_friends? Limit=5000, используя ваш код JavaScript
ИЛИ ЖЕ
попробуй API графа
https://graph.facebook.com/v2.3/user_id_here/taggable_friends?access_token=
Повеселись
Как отметил Саймон, это невозможно в новом 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, который получает список ваших контактов.
Если вы все еще боретесь с этой проблемой в режиме разработки. Следуйте тому же процессу, как указано ниже:
- создайте тестовое приложение вашего основного приложения,
- создавать тестовых пользователей, автоматически устанавливать приложение для тестовых пользователей и назначать им разрешение «user_friend».
- Добавьте своих тестовых пользователей в друзья друг к другу.
Я следовал тому же процессу после множества исследований, и, наконец, это сработало.
В FBSDKGraphAPI v2.0 или выше вы должны запрашивать разрешение user_friends у каждого пользователя во время входа в FB. Поскольку user_friends больше не включается по умолчанию в каждый логин, мы должны добавить его. Каждый пользователь должен предоставить разрешение user_friends, чтобы появиться в ответе /me/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 {
}
}
}
Таким образом, во время входа в систему FB, это экран подсказки, который содержит все разрешения
Если пользователь нажмет кнопку "Продолжить", разрешения будут установлены. Когда вы получаете доступ к списку друзей с помощью FBGraphAPI, ваши друзья, которые вошли в приложение, как указано выше, будут перечислены
if((FBSDKAccessToken.current()) != nil){
FBSDKGraphRequest(graphPath: "/me/friends", parameters: ["fields" : "id,name"]).start(completionHandler: { (connection, result, error) -> Void in
if (error == nil){
print(result!)
}
})
}
Вывод будет содержать пользователей, которые предоставили разрешение user_friends во время входа в ваше приложение через Facebook
{
data = (
{
id = xxxxxxxxxx;
name = "xxxxxxxx";
}
);
paging = {
cursors = {
after = xxxxxx;
before = xxxxxxx;
};
};
summary = {
"total_count" = 8;
};
}