Unity3D Facebook SDK for iOS Integration 4. 친구 목록 얻기 및 친구에게 초대 요청하기

 유니티3D iOS 페이스북 담벼락 게시 및 자신의 정보 얻기 연동을 정리해봤습니다. 이번에는 친구 목록을 가져와 친구 프로필 사진을 출력해보고 친구에게 요청을 보내기를 정리해봅니다.

 먼저 iOS 플러그인 부분입니다.

//iOSFacebookPlugin.h

- (void) requestFriendsInfo;
- (void) requestInviteFriends:(NSString*)strMessage
             suggestedFriends:(NSString*)strSuggestedFriends;


- (NSDictionary*)parseURLParams:(NSString *)query;


//iOSFacebookPlugin.mm

extern "C"
{
...   
    void iOSRequestFriendsInfo()
    {
        [[iOSFacebookPlugin sharediOSFacebookPlugin] requestFriendsInfo];
    }

    void iOSRequestInviteFriends(const char* pszInviteMessage, const char* pszSuggestedFriends)
    {
        NSString* strInviteMessage = [NSString stringWithUTF8String:pszInviteMessage];
        NSString* strSuggestedFriends = [NSString stringWithUTF8String:pszSuggestedFriends];
        [[iOSFacebookPlugin sharediOSFacebookPlugin] requestInviteFriends:strInviteMessage
                                                         suggestedFriends:strSuggestedFriends];
    }    

}



@implementation iOSFacebookPlugin
...

- (void) requestFriendsInfo
{
    if (FBSession.activeSession.isOpen) {
        [[FBRequest requestForMyFriends] startWithCompletionHandler:
         ^(FBRequestConnection *connection,
           NSDictionary* result,
           NSError *error) {
             if (!error) {
                 NSArray* friends = [result objectForKey:@"data"];
                 SBJsonWriter* jsonWriter = [[SBJsonWriter alloc] init];
                 
                 NSMutableArray* jsonArray = [[NSMutableArray alloc] init];
                 for(NSDictionary<FBGraphUser>* user in friends) {
                     NSMutableDictionary* dicFriend = [[NSMutableDictionary alloc] init];
                     //[dicFriend setValue: user.id forKey: @"FacebookId"];

                     [dicFriend setValue: [user objectForKey:@"id"] forKey: @"FacebookId"];
                     [dicFriend setValue: user.name forKey: @"Name"];
                     [jsonArray addObject: dicFriend];
                 }
                 
                 NSString* jsonString = [jsonWriter stringWithObject:jsonArray];
                 NSLog(@"%@", jsonString);
                 UnitySendMessage("iOSManager", "ResultFriendsInfo", [jsonString UTF8String]);
                 [jsonArray release];
                 [jsonWriter release];
             }
        }];
    }
}

 친구 목록을 얻어와 'FacebookId' 키와 'Name'로 친구 정보를 저장하고 SBJson으로 NSMutableArray를 NSString로 변환 후 유니티3D에 넘기고 있습니다.


- (void) requestInviteFriends:(NSString*)strMessage
             suggestedFriends:(NSString*)strSuggestedFriends
{
    NSMutableDictionary* params = nil;
 
    if(strSuggestedFriends.length)
    {
        SBJsonParser* jsonParser = [[SBJsonParser alloc] init];
        NSArray* jsonInviteFriends = [jsonParser objectWithString:strSuggestedFriends];
        NSMutableArray *suggestedFriends = [[NSMutableArray alloc] init];
        for(NSDictionary* dic in jsonInviteFriends)
        {
            [suggestedFriends addObject:[dic valueForKey:@"FacebookId"]];
        }
     
        params = [[NSMutableDictionary alloc] init];
        [params setValue:[suggestedFriends componentsJoinedByString:@","] forKey:@"suggestions"];
        NSLog([params description]);
    }
 
 
    [FBWebDialogs presentRequestsDialogModallyWithSession:nil
                                                  message:strMessage
                                                    title:nil
                                               parameters:params
                                                  handler:^(FBWebDialogResult result, NSURL *resultURL, NSError *error) {
                                                      NSMutableDictionary* dicResult = [[NSMutableDictionary alloc] init];
                                                   
                                                      if (error) {
                                                          // Case A: Error launching the dialog or sending request.
                                                          [dicResult setValue:@"faile" forKey:@"Result"];
                                                          NSLog(@"Error sending request.");
                                                      } else {
                                                          if (result == FBWebDialogResultDialogNotCompleted) {
                                                              // Case B: User clicked the "x" icon
                                                              [dicResult setValue:@"cancel" forKey:@"Result"];
                                                              NSLog(@"User canceled request.");
                                                          } else {
                                                              NSDictionary *params = [self parseURLParams:[resultURL query]];
                                                              // 취소 버튼 눌렀을 때
                                                              if (![params valueForKey:@"request"]) {
                                                                  // User clicked the Cancel button
                                                                  [dicResult setValue:@"cancel" forKey:@"Result"];
                                                                  NSLog(@"User canceled request.");
                                                              } else {
                                                                  // User clicked the Send button
                                                                  [dicResult setValue:@"ok" forKey:@"Result"];
                                                               
                                                                  NSMutableArray* fbidArray = [[NSMutableArray alloc] init];
                                                                  for(NSString* paramKey in params)
                                                                  {
                                                                      if([paramKey hasPrefix:@"to["])
                                                                      {
                                                                          [fbidArray addObject:[params objectForKey:paramKey]];
                                                                      }
                                                                  }
                                                                  [dicResult setValue:fbidArray forKey:@"InviteFriends"];
                                                                  NSLog(@"Request Send.");
                                                              }
                                                          }
                                                      }
                                                      SBJsonWriter* jsonWriter = [[SBJsonWriter alloc] init];
                                                      NSString* jsonString = [jsonWriter stringWithObject:dicResult];
                                                      NSLog(@"%@", jsonString);
                                                      UnitySendMessage("iOSManager", "ResultInviteFriends", [jsonString UTF8String]);
                                                  }];
}

 친구에게 보낼 초대 메시지와 특정 친구에게만 요청시 친구ID들을 넘겨받아 요청 다이얼로그를 통해 처리하는 부분입니다. 유니티3D에서 친구 목록을 JSON으로 보내주고 SBJsonParser를 통해 다이얼로그에 넘겨줄 suggestions 파라메터를 만들어줍니다. 이 값이 없다면 다이얼로그 창에서 모든 친구 목록이 출력됩니다.

 요청 다이얼로그가 닫히고 후 처리하는 부분중에서 밑에 나오는 parseURLParams를 통해 결과값을 분석 해줍니다. 이때 페이스북 개발자 센터 샘플소스에는 없는 부분이 있는데 위에 주석부분에 있는 것처럼 X 아이콘 말고도 취소 버튼으로 취소한 것에 대한 예외 처리를 해줘야합니다.

 URL을 파싱 후 요청을 보낸 친구들을 역시나 최종적으로 게임에서 활용하기위해 SBJsonWriter로 처리 후 유니티3D에 보내줍니다.


- (NSDictionary*)parseURLParams:(NSString *)query {
    NSArray *pairs = [query componentsSeparatedByString:@"&"];
    NSMutableDictionary *params = [[[NSMutableDictionary alloc] init] autorelease];
    for (NSString *pair in pairs) {
        NSArray *kv = [pair componentsSeparatedByString:@"="];
        NSString* key = [[kv objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSString *val = [[kv objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        [params setObject:val forKey:key];
    }
    return params;
}

@end


 이하는 유니티3D 컴포넌트 소스 입니다.

//iOSManager.cs

[DllImport("__Internal")]
private static extern void iOSRequestFriendsInfo();
[DllImport("__Internal")]

private static extern void iOSRequestInviteFriends(string strInviteMessage, string strSuggestedFriends);


public void RequestFriendsInfo()
{
iOSRequestFriendsInfo();
}

public void ResultFriendsInfo(string jsonFriends)
{
JsonReader reader = new JsonReader(jsonFriends);

string strFacebookId = string.Empty;
string strFacebookName = string.Empty;

while(reader.Read())
{
if(reader.Token.ToString() == "PropertyName" && reader.Value.ToString() == "FacebookId")
{
reader.Read();
strFacebookId = reader.Value.ToString();
}
if(reader.Token.ToString() == "PropertyName" && reader.Value.ToString() == "Name")
{
reader.Read();
strFacebookName = reader.Value.ToString();
}

if((strFacebookId != string.Empty) && (strFacebookName != string.Empty))
{
Debug.Log("Friend id " + strFacebookId + " Name " + strFacebookName);
this.dicFriends.Add(strFacebookId, strFacebookName);
strFacebookId = string.Empty;
strFacebookName = string.Empty;
}
}
/*
JsonData jData = JsonMapper.ToObject(jsonFriends);
for (int i = 0 ; i < jData.Count ; i++)
{
string strFacebookId = jData[i]["FacebookId"].ToString();
string strFacebookName = jData[i]["Name"].ToString();
Debug.Log("Friend id " + strFacebookId + " Name " + strFacebookName);
this.dicFriends.Add(strFacebookId, strFacebookName);
}
*/
SetLog("Friend Count = " + this.dicFriends.Count.ToString());
}

 친구 목록을 얻어와 처리하는 ResultFriendsInfo 부분에서 LitJson을 사용하는데 있어 iOS에서는 KeyNotFoundException: The given key was not present in the dictionary. 이슈가 발생하기 때문에 링크와 같이 raw하게 json에 루프를 돌며 접근해서 처리해줘야 합니다. 주석으로 된 부분은 이슈가 없는 안드로이드 소스 부분이죠.


public void RequestInviteFriends(string strInviteMessage, bool bSuggestedFriends)
{
StringBuilder sb = new StringBuilder();
JsonWriter writer = new JsonWriter(sb);
if(bSuggestedFriends == true)
{
writer.WriteArrayStart();

writer.WriteObjectStart();
  writer.WritePropertyName("FacebookId");
  writer.Write("695755709");
  writer.WriteObjectEnd();

  writer.WriteObjectStart();
  writer.WritePropertyName("FacebookId");
  writer.Write("685145706");
  writer.WriteObjectEnd();

  writer.WriteArrayEnd();

  Debug.Log("bSuggestedFriends " + sb.ToString());
}

iOSRequestInviteFriends(strInviteMessage, sb.ToString());
}

 친구에게 앱 요청 호출 부분인데 샘플이라 간단히 페이스북 개발자 센터에 있는 페이스북 ID중 2개를 입력해봤습니다.


public void ResultInviteFriends(string jsonResult)
{
JsonReader reader = new JsonReader(jsonResult);

string strResult = string.Empty;
string strFacebookId = string.Empty;

while(reader.Read())
{
if(reader.Token.ToString() == "PropertyName" && reader.Value.ToString() == "Result")
{
reader.Read();
strResult = reader.Value.ToString();
}

if(reader.Token.ToString() == "PropertyName" && reader.Value.ToString() == "InviteFriends")
{
//ArrayStart
reader.Read();

//fbid1
reader.Read();
strFacebookId = reader.Value.ToString();
Debug.Log("Friend id " + strFacebookId);

//fbid2
reader.Read();
strFacebookId = reader.Value.ToString();
Debug.Log("Friend id " + strFacebookId);
}
}
  SetLog(jsonResult);
}

 친구 앱 요청 다이얼로그가 닫히고 유니티3D로 넘어온 결과를 처리하는 메서드입니다. 위에 친구 리스트 처리하듯이 LitJson의 이슈 때문에 JsonReader로 처리했습니다. 요청 받은 친구 목록을 가지고 게임에서는 그 수에 따라 리워드를 해주는 등의 처리를 하면 되겠죠.


 친구에게 앱 요청 테스트하기에 앞서 페이스북 개발자 센터 앱 정보를 수정해야 합니다. 먼저 애플 개발자 센터에서 등록한 앱의 Apple ID 를 기억해 두고

 페이스북 개발자 센터에서 등록한 앱의 Native iOS App 부분중 iPhone App Store ID와 필요하다면 iPad App Store ID 부분에 애플 스토어의 앱 ID를 기입합니다. 그림과 같이 Facebook 로그인과 딥 링킹도 활성화 해줍니다.

 그래야 친구에게 날라간 앱 요청을 친구가 클릭했을 때 해당 앱 스토어가 이동이 되던가 해당 앱이 실행됩니다. 해당 준비 사항이 처리되지 않으면 요청을 해도 친구에게 요청 알림이 가지않아 테스트가 안됩니다.

 친구 요청 버튼을 클릭하면 이렇게 페이스북 요청 보내기 다이얼로그 창이 뜹니다. 앱 요청을 받을 친구를 터치 후 보내기를 누르면 됩니다. 그림에는 없지만 Suggested Friends 요청 버튼을 누르면 2명의 친구만 요청 다이얼로그에 뜹니다.

 친구 프로필 사진들이 랜덤하게 출력되어 있는데 이와 관련된 유니티3D쪽 소스는 기존에 안드로이드에서 정리한 것과 같으니 링크를 참고하시기 바랍니다.

 요청을 받은 쪽에서는 이런식으로 요청을 확인 할 수 있습니다.

이 블로그의 인기 게시물

CMake Windows에 설치하기

'xxx.exe' 프로그램을 시작할 수 없습니다. 지정된 파일을 찾을 수 없습니다.

Unity3D 안드로이드 Keystore 생성하기