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);
}
}];
하지만 지금은 친구를 사 cannot 수 없습니다!
답변
그래프 API v2.0에서 호출 /me/friends
하면 앱을 사용하는 사람의 친구가 반환됩니다.
또한 v2.0에서는 user_friends
각 사용자 에게 권한을 요청해야합니다 . user_friends
기본적으로 더 이상 모든 로그인에 포함되지 않습니다. user_friends
에 대한 응답으로 표시 하려면 각 사용자에게 권한을 부여해야합니다 /me/friends
. 자세한 내용 은 Facebook 업그레이드 안내서 를 참조하거나 아래 요약을 검토하십시오.
앱을 사용하지 않는 친구 목록에 액세스하려면 두 가지 옵션이 있습니다.
-
사람들이 앱을 사용하여 Facebook에 게시 한 스토리에서 친구에게 태그를 지정 하도록하려면
/me/taggable_friends
API를사용할 수 있습니다. 이 엔드 포인트를 사용하려면 Facebook의 검토가 필요 하며 사용자가 게시물에 친구를 태그 할 수 있도록 친구 목록을 렌더링하는 경우에만 사용해야합니다. -
앱이 게임이고 게임이 Facebook Canvas를 지원 하는 경우
/me/invitable_friends
엔드 포인트를사용하여 사용자 정의 초대 대화 상자 를 렌더링 한 다음이 API가 리턴 한 토큰을 표준 요청 대화 상자에 전달할 수 있습니다.
다른 경우에는 앱이 더 이상 사용자 친구의 전체 목록을 검색 할 수 없습니다 ( user_friends
권한을 사용하여 앱을 특별히 승인 한 친구 만 ). 이것은 페이스 북에 의해 ‘디자인에 의해’확인되었다.
사람들이 앱을 사용하도록 친구를 초대하도록 허용하려는 앱의 경우 웹 에서 보내기 대화 상자 또는 iOS 및 Android 에서 새 메시지 대화 상자를 계속 사용할 수 있습니다 .
업데이트 : Facebook은 https://developers.facebook.com/docs/apps/faq 에서 이러한 변경 사항에 대한 FAQ를 게시했습니다 .
답변
Simon Cross의 대답은 받아 들일 수 있지만 정확해야하지만 수행해야 할 일의 예 (Android)로 조금 강화 할 것이라고 생각했습니다. 나는 그것을 가능한 한 일반적으로 유지하고 질문에만 집중할 것이다. 개인적으로 데이터베이스에 물건을 저장하여 로딩이 원활했지만 여기서는 범위를 벗어난 CursorAdapter와 ContentProvider가 필요합니다.
나는 여기에 와서 생각했다. 지금 무엇?!
문제
user3594351 과 마찬가지로 친구 데이터가 비어 있음을 알았습니다. FriendPickerFragment를 사용하여 이것을 알았습니다. 3 개월 전에 효과가 있었지만 더 이상 작동하지 않습니다. 페이스 북의 사례조차도 깨졌습니다. 그래서 내 문제는 ‘FriendPickerFragment를 직접 작성하는 방법은 무엇입니까?
작동하지 않는 것
Simon Cross의 옵션 # 1은 친구를 앱에 초대하기에 충분하지 않았습니다. Simon Cross 는 요청 대화 상자를 권장했지만 한 번에 5 개의 요청 만 허용합니다. 요청 대화 상자는 특정 Facebook 로그인 세션 동안 동일한 친구를 표시했습니다. 유용하지 않다.
효과가있는 것 (요약)
약간의 노력으로 옵션 # 2. Facebook의 새로운 규칙을 준수해야합니다. 1.) 게임입니다. 2.) Canvas 앱 (Web Presence)이 있습니다. 3.) 앱이 Facebook에 등록되어 있습니다. Facebook 개발자 웹 사이트의 설정 에서 모두 수행됩니다 .
내 앱에서 친구 선택기를 손으로 에뮬레이트하기 위해 다음을 수행했습니다.
- 두 개의 조각을 표시하는 탭 활동을 작성하십시오. 각 조각은 목록을 보여줍니다. 사용 가능한 친구 ( / me / friends )와 초대 할 수있는 친구 ( / me / invitable_friends )를 위한 조각 입니다. 동일한 조각 코드를 사용하여 두 탭을 모두 렌더링하십시오.
- Facebook에서 친구 데이터를 가져 오는 AsyncTask를 만듭니다. 해당 데이터가로드되면 값을 화면에 렌더링하는 어댑터로 보내십시오.
세부
비동기 작업
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());
}
}
}
답변
Facebook은 이제 정책을 개정했습니다. 앱에 Canvas 구현이없고 앱이 게임이 아닌 경우 어쨌든 전체 친구 목록을 얻을 수 없습니다. 물론 taggable_friends도 있지만 그 중 하나는 태그 전용입니다.
앱만 승인 한 친구 목록을 가져올 수 있습니다.
Graph API 1.0을 사용하는 앱은 2015 년 4 월 30 일까지 작동하며 그 이후에는 더 이상 사용되지 않습니다.
이에 대한 자세한 내용은 다음을 참조하십시오.
답변
Facebook에서 친구 목록을 얻으려면 Facebook에서 검토 할 앱을 제출해야합니다. 로그인 권한 중 일부를 참조하십시오.
두 단계는 다음과 같습니다.
1) 먼저 앱 상태가 라이브 상태 여야합니다
2) Facebook에서 필요한 권한을 얻습니다 .
1) 앱 상태를 실시간으로 활성화하십시오.
-
앱 페이지로 이동하여 앱 을 선택 하십시오.
-
대시 보드 오른쪽 상단에서 상태를 선택합니다 .
-
개인 정보 보호 정책 URL 제출
-
카테고리 선택
-
이제 우리 앱은 라이브 상태입니다.
한 단계가 완료되었습니다.
2) 검토를 위해 앱을 제출하십시오.
답변
Simon이 언급했듯이 새로운 Facebook API에서는 불가능합니다. 기술적으로 말하자면 브라우저 자동화를 통해 할 수 있습니다.
- 이것은 Facebook 정책에 위배되므로 거주하는 국가에 따라 합법적이지 않을 수 있습니다
- 자격 증명을 사용하거나 사용자에게 자격 증명을 요청하고 저장해야 할 수도 있습니다 (대칭으로 암호화 된 암호라도 저장하는 것은 좋지 않습니다)
- Facebook에서 API를 변경하면 브라우저 자동화 코드도 업데이트해야합니다 (응용 프로그램을 강제로 업데이트 할 수없는 경우 브라우저 자동화 부분을 웹 서비스로 작성해야 함)
- 이것은 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 커넥터의 동적 업데이트도 허용합니다.
답변
/me/taggable_friends?limit=5000
JavaScript 코드를 사용해보십시오
또는
그래프 API를 사용해보십시오 :
https://graph.facebook.com/v2.3/user_id_here/taggable_friends?access_token=
답변
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;
};
}