📜 ⬆️ ⬇️

Facebook SDK (iOS) integration into mobile free-to-play games

image Mobile free-to-play is almost no time without the use of social networks in games. Social networks provide what is called virality (from the English. Viral - viral, ie, able to spread like a virus, from one person to another), which allows you to attract new players with minimal cost. In this article we will share the experience of integrating Facebook into Alawar games on the iOS platform.

In a typical free-to-play mobile game, Facebook integration provides the following features:
  1. The possibility of authorization through a user account in Facebook This authorization is good because we form a unique user ID of the game with minimal effort on his part. The player does not need to invent a login, enter an e-mail address, etc. After all, we are talking about a mobile application, where it is somewhat tiring to constantly enter text data. It is enough to press the button with the well-recognized “f” logo once. There are also advantages for developers - the player’s progress can be synchronized between different devices on different platforms, the main thing is Facebook on these platforms.
  2. Ability to send app requests to friends. Requests are sort of messages that appear on a player’s Facebook page (and in the Facebook application) and contain game-related information. Typical requests include inviting friends to the game, requests like “send / give me something” or “help me complete a level”. Ultimately, the request is needed only in order for a person to click on it and go into the game (or to the game page in the App store). The use of requests is a powerful mechanism for attracting new players and returning old players to the game for free.
  3. Ability to send posts in the timeline (timeline). This posting allows you to report the game to anyone who reads the timeline. Games usually put there information about the achievements of the player, which adds a competitive component.
  4. The ability to receive information about the player from his Facebook account. Most often, such information includes the name of the player, his avatar, and possibly the avatars of his friends. An example of using avatars in a real - life free-to-play game under a spoiler.
    Avatar Game
    image

In order to simplify the integration of Facebook, we have created a demo application that implements almost everything needed from the client side.

Demo application


The demo application is written in C ++ (like most of our free-to-play-games) with inserts in Objective-C and is the simplest application on the Cocos2d-x engine (you can download it here ). A rectangle moves across the screen and is reflected from the edges of the screen when these borders are reached.
image
The control is carried out using 4 buttons: f - authorization, REQ - sending a request to friends, POST - posting to the timeline and LOGOUT. After authorization, the user's avatar is placed in place of the rectangle, and a welcome inscription is added.
image
To compile, you need to download and install the Facebook SDK , add the Facebook SDK framework to the project in Xcode. We used the Facebook SDK version 3.9.
To launch a demo application, you must create your own Facebook application on your developer portal, register its identifier in the plist of our demo application, and also perform a number of other simple operations. Read more about it here .

Technical implementation details


Access rights

The first thing you encounter when you integrate Facebook on a client is the creation of a session with a request for access rights (permissions), which Facebook offers various options . It is important to restrain the impulse and not to request access rights to everything at once. It is considered a good form to request access rights at the moment when they are really necessary. When creating a session, we request only basic rights.
')
+ (NSArray*) getBasicPermissions { NSArray* permissions = [[NSArray alloc] initWithObjects: @"user_birthday", nil]; return permissions; } 


In this case, the authorization will show the following dialog.
image
You should also pay attention to the fact that native iOS dialogs will only be shown if you pre-authorize on Facebook on the device itself in the settings.

image

Otherwise, iOS will try to use the Facebook application (if it was installed from the App Store) or it will open Facebook in the browser.
When we need the rights to publish something on the timeline or when we request friends, we will ask for rights specifically for this.

 + (void) requestPublishPermissions { if (hasPublishPermissions) return; NSArray *permissions = [[NSArray alloc] initWithObjects: @"publish_actions", @"publish_stream", nil]; [[FBSession activeSession] requestNewPublishPermissions:permissions defaultAudience:FBSessionDefaultAudienceFriends completionHandler:^(FBSession *session, NSError *error) { hasPublishPermissions = [[FBSession activeSession].permissions containsObject:@"publish_actions"] && [[FBSession activeSession].permissions containsObject:@"publish_stream"]; if (g_handler) { g_handler->OnGetPublishPermissions(hasPublishPermissions); } }]; } 


In this case, the following dialog will be displayed.
image
It is important to remember that the player can deny the rights to publish on his own behalf, but allow authorization. These cases need to be handled carefully.

Requests to friends

The implementation of requests to friends (app requests) is described in some detail in the documentation , but there are a number of subtleties. With the basic implementation of requests, the dialog box shown below will be displayed.
image
The code for this implementation is under the spoiler.
Implementation
 + (void) requestFriend { // more details here // https://developers.facebook.com/docs/ios/send-requests-using-ios-sdk/ if (!friendsCache) { friendsCache = [[FBFrictionlessRecipientCache alloc] init]; } [friendsCache prefetchAndCacheForSession:nil]; [FBWebDialogs presentRequestsDialogModallyWithSession:nil message:@"Help me, friend!" title:@"Help me!" parameters:nil handler:^(FBWebDialogResult result, NSURL *resultURL, NSError *error) { if (error) { NSLog(@"Error sending request"); } else { if (result == FBWebDialogResultDialogNotCompleted) { NSLog(@"User canceled request"); } else { NSDictionary *urlParams = [FacebookController parseURLParams:[resultURL query]]; if (![urlParams valueForKey:@"request"]) { NSLog(@"User canceled request"); } else { NSLog([NSString stringWithFormat: @"Request Sent: %@", [urlParams valueForKey:@"request"]]); } } } } friendCache:friendsCache]; } 

The behavior of the query window can be controlled using parameters passed after parameters: when the dialog is invoked. For example, the following set of parameters allows you to send a request to a friend known in advance.

 NSString *friendId=@"100006530868327"; NSMutableDictionary* params = [[NSMutableDictionary alloc] init]; params[@"to"] = friendId; 


The Facebook SDK in this case will show the modified App requests window and even suggest not to show the window on the following requests to this friend.

Posting timeline

Facebook allows you to post so-called stories in the timeline. In order to form a story, you need to select “Open Graph” in the menu on the left on the page of your application on the Facebook developer portal . You will see 3 tabs: Stories, Object Types and Action Types. The object type summarizes a certain group of objects that can be encountered by users of your game, for example, badges. Now we need actions that can be applied to the “Badge” object, for example, the “Find” action. The type of action and the type of object can be combined into the “Find a Badge” story. Facebook has ample opportunity to customize stories. Read more about it here .
To get the code for publishing the created story from the application, you need to click on the “Get Code” caption to the right of the story name. Select the required platform (iOS SDK in our case) and the “Code for Object” tab. The system will generate code like this:

 NSMutableDictionary<FBGraphObject> *object = [FBGraphObject openGraphObjectForPostWithType:@"aw_test:badge" title:@"Sample Badge" image:@"https://fbstatic-a.akamaihd.net/images/devsite/attachment_blank.png" url:@"http://samples.ogp.me/473380876115865" description:@""];; [FBRequestConnection startForPostWithGraphPath:@"me/objects/aw_test:badge" graphObject:object completionHandler:^(FBRequestConnection *connection, id result, NSError *error) { // handle the result }]; 


In the Code for Action tab, you can get the code for the action. To form a history in the timeline, you must first create an object and then create an action with this object.
Oddly enough, this code does not work. If you include it in the project without modifications, then there will be a crash on the undetected selector in one of the classes. In order to fix this, you need to add a couple of lines to the parameters of the Open Graph object being created.

 object[@"create_object"] = @"true"; object[@"fbsdk:create_object"] = @"true"; 


This "magic" corrects crash, but posting to the timeline is still not working. A good sign that everything has worked is a callback ID returned by Facebook. The identifier is a set of numbers (for example, 586146891470767). In response to the code received from the portal, comes the string "true". This can be fixed by modifying the code a little more. In particular, the call to startForPostWithGraphPath proposed by the code generator should be replaced by startForPostOpenGraphObject when creating the object.
The full code for posting in the timeline can be seen under the spoiler.
Implementation
 + (void) createOpenGraphObjectWithType:(NSString *) type title:(NSString *) title url:(NSString *) url image:(NSString *) image handler: (OpenGraphObjectCreationHandler) handler { NSMutableDictionary<FBOpenGraphObject> *object = [FBGraphObject openGraphObjectForPostWithType:type title:title image:image url:url description:@""]; object[@"create_object"] = @"true"; object[@"fbsdk:create_object"] = @"true"; [FBRequestConnection startForPostOpenGraphObject:object completionHandler:^(FBRequestConnection *connection, id result, NSError *error) { if (!error && result != nil) { NSLog([NSString stringWithFormat:@"Posting object '%@' (id=%@) is created!", title, [result objectForKey:@"id"]]); handler([result objectForKey:@"id"]); } else { NSLog([NSString stringWithFormat:@"Posting object creation error: %@", error]); } }]; } + (void) postStory { NSString* badge_title = @"Blue Badge"; NSString* badge_url = @"http://demo.tom3.html5.services.alawar.com/images/tester/blue_badge.htm"; NSString* badge_image = @"http://demo.tom3.html5.services.alawar.com/images/tester/blue_badge.png"; int rnd = arc4random() % 2; if (rnd == 0) { badge_title = @"Red Badge"; badge_url = @"http://demo.tom3.html5.services.alawar.com/images/tester/red_badge.htm"; badge_image = @"http://demo.tom3.html5.services.alawar.com/images/tester/red_badge.png"; } [FacebookController createOpenGraphObjectWithType:@"aw_test:badge" title:badge_title url:badge_url image:badge_image handler:^(NSString *objectId) { // action NSMutableDictionary<FBGraphObject> *action = [FBGraphObject graphObject]; action[@"badge"] = objectId; action[@"fb:explicitly_shared"] = @"1"; [FBRequestConnection startForPostWithGraphPath:@"me/aw_test:find" graphObject:action completionHandler:^(FBRequestConnection *connection, id result, NSError *error) { if (!error && result != nil) { NSLog([NSString stringWithFormat:@"Posted (id=%@)!", [result objectForKey:@"id"]]); } else { NSLog([NSString stringWithFormat:@"Posting error: %@", error]); } }]; }]; } 

The attentive reader will note that when executing the code for the action an additional parameter was added.

 action[@"fb:explicitly_shared"] = @"1"; 


If this parameter is not set, the created history will go to the user's Recent Activities, and not into the timeline. If everything is done correctly, then in the timeline of the user it will be possible to observe something similar to the picture below.

image

The last point that you need to figure out: where and how the descriptions of objects are stored The description of the object is stored as a specially marked up html-document on any open server. Images are also posted on public servers, where their Facebook is from and uploads.

Instead of conclusion


If you decide to integrate into the Facebook game, remember that this is not a momentary matter. Be sure to think about how the game will interact with the user through Facebook. Otherwise, you will receive instead of a useful tool for attracting players another application annoying players. Complaints from players on spam will lead to the fact that Facebook will ban the application, which, of course, no one wants.
As practice shows, not everyone gets to take Facebook with a swoop. We hope that the experience we have given on integrating this social network will be useful to you.

Source: https://habr.com/ru/post/214043/


All Articles