Advanced Facebook

Advanced Use
The following section is not required if you are simply using the Action Bar

Linking Users with Facebook

When connecting users in your app to their Facebook account it is important to understand the distinction between READ permissions and WRITE permissions.

Facebook makes a clear distinction between those operations required READ access and those requiring WRITE (publish) access.

It is important to observe the following policy conventions from Facebook:

  • READ permissions must be requested BEFORE WRITE permissions
  • It is invalid to request READ permissions at the same time as WRITE permissions (this will cause an error)

The default behavior of the Socialize Action Bar means that Facebook permissions are requested in the correct order so you should not need to worry if you are simply using the Action Bar, however if you want to perform any direct interaction with Facebook you will need to be mindful of these rules.

By default Socialize requests no additional permissions for READ access, and requests the following permissions for WRITE access:

“publish_actions”

When performing a direct Facebook operation you must first check to see whether the appropriate permissions have been linked:

// The "this" argument refers to the current Activity	
if(FacebookUtils.isLinkedForWrite(this)) {
	// Perform direct Facebook operation.
} 
else {
	// Request write access
	FacebookUtils.linkForWrite(this, new SocializeAuthListener() {
	
		@Override
		public void onCancel() {
			// The user cancelled the operation.
		}
		
		@Override
		public void onAuthSuccess(SocializeSession session) {
			// Perform direct Facebook operation.
		}
		
		@Override
		public void onAuthFail(SocializeException error) {
			// Handle error
		}
		
		@Override
		public void onError(SocializeException error) {
			// Handle error
		}
	});	
}

If you want to include additional permissions not included in the default list you can just specify these as additional parameters to the isLinked and link methods

// The "this" argument refers to the current Activity	
if(FacebookUtils.isLinkedForWrite(this, "publish_stream", "create_event")) {
	// Perform direct Facebook operation.
} 
else {
	// Request write access
	FacebookUtils.linkForWrite(this, new SocializeAuthListener() {
	
		@Override
		public void onCancel() {
			// The user cancelled the operation.
		}
		
		@Override
		public void onAuthSuccess(SocializeSession session) {
			// Perform direct Facebook operation.
		}
		
		@Override
		public void onAuthFail(SocializeException error) {
			// Handle error
		}
		
		@Override
		public void onError(SocializeException error) {
			// Handle error
		}
	}, "publish_stream", "create_event");	
}

If you already have Facebook integration in your app and do not wish to replace this with the Socialize implementation you can still link the user to Facebook within Socialize by providing the user’s Facebook auth token

// The user's Facebook auth token
String fbToken = "ABCDEF...GHIJKL";

// The "this" argument refers to the current Activity
// Specify "true" to verify that the permissions on this token are correct
FacebookUtils.linkForRead(this, fbToken, true, new SocializeAuthListener() {

	@Override
	public void onCancel() {
		// The user cancelled the operation.
	}
	
	@Override
	public void onAuthSuccess(SocializeSession session) {
		// User was authed.
	}
	
	@Override
	public void onAuthFail(SocializeException error) {
		// Handle error
	}
	
	@Override
	public void onError(SocializeException error) {
		// Handle error
	}
});

Unlinking Users from Facebook

To unlink a user from their Facebook account simple call unlink. This call executes synchronously.

// Disconnect the user from their Facebook account
// The "this" argument refers to the current Activity
FacebookUtils.unlink(this);	

Posting to Facebook

By default all actions created using the SDK will provide the end user with the opportunity to share their action with Facebook (if Facebook has been configured) however it is also possible to manually post content to a user’s Facebook wall.

Posting Socialize Entities to Facebook

The simplest and most effective use of Facebook within Socialize is to post entities. This approach takes full advantage of Socialize SmartDownloads as well as automatically supporting Facebook Open Graph which helps maximize the effectiveness of your social strategy.

To post an entity to a user’s Facebook timeline simply call the postEntity method.

if(FacebookUtils.isLinkedForWrite(this)) {
	Entity entity = Entity.newInstance("http://myentity.com", "My Name");
	
	// The "this" argument refers to the current Activity
	FacebookUtils.postEntity(this, entity, "Text to be posted", new SocialNetworkShareListener() {
		
		@Override
		public void onNetworkError(Activity context, SocialNetwork network, Exception error) {
			// Handle error
		}
		
		@Override
		public void onCancel() {
			// The user cancelled the operation.
		}
		
		@Override
		public void onAfterPost(Activity parent, SocialNetwork socialNetwork, JSONObject responseObject) {
			// Called after the post returned from Facebook.
			// responseObject contains the raw JSON response from Facebook.
		}
		
		@Override
		public boolean onBeforePost(Activity parent, SocialNetwork socialNetwork, PostData postData) {
			// Called just prior to the post.
			// postData contains the dictionary (map) of data to be posted.  
			// You can change this here to customize the post.
			// Return true to prevent the post from occurring.
			return false;
		}
	});
}
else {
	// Handle non-linked case
}	

Posting Directly to Facebook

If you want complete control over what is posted to Facebook, Socialize provides a simple interface to the Facebook Graph API.

Refer to the Facebook Graph API documentation for more specific implementation information

http://developers.facebook.com/docs/reference/api/

Executing a POST

if(FacebookUtils.isLinkedForWrite(this)) {
	// The graph API path to be called
	String graphPath = "me/links";

	// The data to be posted. This is based on the graphPath
	// See http://developers.facebook.com/docs/reference/api/
	Map<String, Object> postData = new HashMap<String, Object>();
	postData.put("message", "A message to post");
	postData.put("link", "http://getsocialize.com");
	postData.put("name", "Socialize SDK!");
		
	// Execute a POST on facebook
	// The "this" argument refers to the current Activity
	FacebookUtils.post(this, graphPath, postData, new SocialNetworkPostListener() {
		
		@Override
		public void onNetworkError(Activity context, SocialNetwork network, Exception error) {
			// Handle error
		}
		
		@Override
		public void onCancel() {
			// The user cancelled the operation.
		}
		
		@Override
		public void onAfterPost(Activity parent, SocialNetwork socialNetwork, JSONObject responseObject) {
			// Called after the post returned from Facebook.
			// responseObject contains the raw JSON response from Facebook.
		}
	});
}
else {
	// Handle non-linked case
}	

If you want to take full advantage of Socialize SmartDownloads and post the auto-generated SmartDownload urls for your entity or app you can do this by creating a simple share object without propagation first.

if(FacebookUtils.isLinkedForWrite(this)) {
	// Create a simple share object to get the propagation data
	final Entity entity = Entity.newInstance("http://myentity.com", "My Name");

	ShareOptions options = ShareUtils.getUserShareOptions(this);

	// The "this" argument refers to the current Activity
	ShareUtils.registerShare(this, entity, options, new ShareAddListener() {
		
		@Override
		public void onError(SocializeException error) {
			// Handle error
		}
		
		@Override
		public void onCreate(Share share) {
			
			// Get the propagation info from the result
			PropagationInfoResponse propagationInfoResponse = share.getPropagationInfoResponse();
			
			PropagationInfo propagationInfo = propagationInfoResponse.getPropagationInfo(SocialNetwork.FACEBOOK);
			
			// The graph API path to be called
			String graphPath = "me/links";

			// The data to be posted. This is based on the graphPath
			// See http://developers.facebook.com/docs/reference/api/
			Map<String, Object> postData = new HashMap<String, Object>();
			postData.put("message", "A message to post");
			postData.put("link", propagationInfo.getEntityUrl()); // Use the SmartDownload URL
			postData.put("name", entity.getDisplayName());
				
			// Execute a POST on facebook
			FacebookUtils.post(context, graphPath, postData, new SocialNetworkListener() {
				
				@Override
				public void onNetworkError(Activity context, SocialNetwork network, Exception error) {
					// Handle error
				}
				
				@Override
				public void onCancel() {
					// The user cancelled the operation.
				}
				
				@Override
				public void onAfterPost(Activity parent, SocialNetwork socialNetwork, JSONObject responseObject) {
					// Called after the post returned from Facebook.
					// responseObject contains the raw JSON response from Facebook.
				}
				
				@Override
				public boolean onBeforePost(Activity parent, SocialNetwork socialNetwork, PostData postData) {
					// Called before the post to the given network is made
					// Return true to prevent the post from occurring
					return false;
				}
			});		
		}
	}, SocialNetwork.FACEBOOK);	
}
else {
	// Handle non-linked case
}

Executing a GET

// The graph API path to be called
String graphPath = "me/links";

// Execute a GET on facebook
// The "this" argument refers to the current Activity
FacebookUtils.get(this, graphPath, null, new SocialNetworkPostListener() {
	
	@Override
	public void onNetworkError(Activity context, SocialNetwork network, Exception error) {
		// Handle error
	}
	
	@Override
	public void onCancel() {
		// The user cancelled the operation.
	}
	
	@Override
	public void onAfterPost(Activity parent, SocialNetwork socialNetwork, JSONObject responseObject) {
		// Called after the post returned from Facebook.
		// responseObject contains the raw JSON response from Facebook.
	}
});

Executing a DELETE

if(FacebookUtils.isLinkedForWrite(this)) {
	
	// The graph API path to be called
	String graphPath = "me/links/1234";

	// Execute a DELETE on facebook
	// The "this" argument refers to the current Activity
	FacebookUtils.delete(this, graphPath, null, new SocialNetworkListener() {
		
		@Override
		public void onNetworkError(Activity context, SocialNetwork network, Exception error) {
			// Handle error
		}
		
		@Override
		public void onCancel() {
			// The user cancelled the operation.
		}
		
		@Override
		public void onAfterPost(Activity parent, SocialNetwork socialNetwork, JSONObject responseObject) {
			// Called after the post returned from Facebook.
			// responseObject contains the raw JSON response from Facebook.
		}
		
		@Override
		public boolean onBeforePost(Activity parent, SocialNetwork socialNetwork, PostData postData) {
			// Called before the post to the given network is made
			// Return true to prevent the post from occurring
			return false;
		}
	});
}
else {
	// Handle non-linked case
}	

Using Facebook Open Graph

From v2.3 onwards Socialize supports Facebook “like” Open Graph actions. This means that when a user executes a “like” on Socialize and elects to share this on Facebook it can be posted as an “Open Graph Like” in the user’s Facebook Activity stream.

This behavior can be enabled via configuration in your socialize.properties file

 Please Note
Setting this configuration option will force ALL likes within Socialize to use the Open Graph. Aside from the Facebook setup steps described below no other changes are required.
# Enable/Disable Open Graph calls for "like"
facebook.og.like.enabled=true

Note

If you are not already familiar with the Facebook Open Graph we recommend reviewing the Facebook Documentation first

Configuring your Facebook App for Open Graph

Before you are able to utilize Open Graph calls such as “like” you must first follow the Facebook Guidelines for approval of Open Graph actions.

This is detailed on the Facebook website here:

Open Graph Approval Process

The following steps apply to seeking approval for the in-built “like” action however the same approach can be followed for all Open Graph Actions.

Adding an Open Graph Action to your App

In your app settings on Facebook, access the Open Graph section:

images/fb_og_menu.png

You will be presented with the default configuration screen for Open Graph. Click the Create New Action Type button and select the action to be added

images/fb_og_page1.png

You will then be presented with a dialog in which your action can be selected. Choose an appropriate action and click Submit

images/fb_og_select_action.png

Once your action has been added you are ready to submit it for approval. Click the Submit link.

images/fb_og_page2.png

At this point you may encounter some validation errors. The most common of which are:

images/fb_og_error1.png

The Publish Action requirement is most easily satisfied by simply executing the same curl command provided by Facebook.

Click on the Get Code link next to your action and run the curl command you are provided from your terminal (command line) interface

images/fb_og_curl.png

The final step in the approval process requires you to clarify with Facebook the exact purpose for your OG action.

images/fb_og_error2.png

Socialize has prepared a standard response for you to use in this situation. If you are using the Socialize UI features “out-of-the-box” (that is, without modification) then you can simply refer to the content we have provided for you at:

http://blog.getsocialize.com/facebook-open-graph-review

If you have implemented your own UI and/or are calling the Socialize SDK directly through any other means we recommend you follow the guidelines established by Facebook for the approval of Open Graph actions.

https://developers.facebook.com/docs/opengraph/checklist/

Using In Built Open Graph Actions

The in built OG actions provided by Facebook require approval by Facebook and there is a limited set of actions available and a corresponding limited set of object types.

The actions supported and the corresponding object types are as follows

Action Path Object Types Parameter
like me/og.likes object object
follow me/og.follows profile profile
publish me/news.publishes article article
read me/news.reads article article
watch me/video.watches video.movie movie
    video.episode movie
    video.tv_show movie
    video.other movie

The Object Types specified in the Open Graph call MUST correspond to a valid og:type meta element in the HTML page that represents the object.

For example:

<meta property="og:type" content="video.movie" />

Fortunately Socialize will automatically generate OG tags on your entity page, but you must specify the correct type on the entity object itself.

Entity entity = Entity.newInstance("http://myentity.com", "My Name");

// MUST be a valid OG type
entity.setType("video.movie");

Once you have setup your Entity with the correct type you can force an Open Graph post by changing the PostData in the SocialNetworkListener. Here’s a complete example

	
if(FacebookUtils.isLinkedForWrite(this)) {
	Entity entity = Entity.newInstance("http://myentity.com", "My Entity Name");

	// MUST be a valid OG type
	entity.setType("video.movie");

	ShareOptions options = ShareUtils.getUserShareOptions(this);
	options.setText("Text to be posted");

	// The "this" argument refers to the current Activity
	ShareUtils.shareViaSocialNetworks(this, entity, options, new SocialNetworkShareListener() {
		
		@Override
		public boolean onBeforePost(Activity parent, SocialNetwork socialNetwork, PostData postData) {
			
			if(socialNetwork.equals(SocialNetwork.FACEBOOK)) {
				// Change the post data to force an Open Graph call
				postData.setPath("me/video.watches");
				
				// me/video.watches requires a movie object type
				postData.getPostValues().put("movie", postData.getPropagationInfo().getEntityUrl());
			}
			
			return false;
		}	
		
		@Override
		public void onNetworkError(Activity context, SocialNetwork network, Exception error) {
			// Handle error
		}
		
		@Override
		public void onCancel() {
			// The user cancelled the operation.
		}
		
		@Override
		public void onAfterPost(Activity parent, SocialNetwork socialNetwork, JSONObject responseObject) {
			// Called after the post returned from Facebook.
			// responseObject contains the raw JSON response from Facebook.
		}

	}, SocialNetwork.FACEBOOK);
}
else {
	// Handle non-linked case
}		

The corresponding entity page on Socialize will automatically populate the required OG meta tags:

<meta property="og:title" content="My Entity Name" />
<meta property="og:description" content="...parsed from your URL..." />
<meta property="og:image" content="...parsed from your URL..." />
<meta property="og:type" content="video.movie" />
<meta property="og:url" content="...the URL of this page..." />
 Please Note
If you have configured Socialize (via your dashboard) to skip the Socialize entity page and go straight to your entity URL for all links, you MUST add the Facebook OG meta tags to your entity page manually. If the final page referenced in a Facebook OG post does not contain the correct meta tags the post to Facebook may fail.

If you don’t have an actual URL for your entity you can setup the correct description, image etc by changing the meta data on your entity.

Refer to Entities Without URLs for more details on customizing the entity page.

Using Custom Open Graph Actions

In addition to using the built-in Open Graph actions, you can also define your own.

For example an app that reviews restaurants may want to post the fact that a user “ate” a “meal” rather than simply saying a user “shared” a “link”.

There is however a fairly lengthy setup process to correctly configure your application to handle custom OG actions.

We recommend reviewing the Open Graph Tutorial to understand how to configure your app for custom Open Graph actions.

Configuring Custom Open Graph Actions

Facebook Open Graph implements several security systems to ensure that owners of content are verified. One such security measure ensures that websites housing information about custom OG types are registered against the Facebook App to guarantee that 3rd party users cannot fraudulently represent custom types on external pages.

If you want to utilize custom open graph actions in your Socialize enabled app you must first configure your Facebook application to expect posts that refer to websites hosted by Socialize.

This consists of 3 simple steps:

  1. Obtain your Socialize App Url from your dashboard at www.getsocialize.com
  2. Nominate the Socialize App Url as your “Site URL” on Facebook
  3. Add the getsocialize.com domain to your list of App Domains on Facebook.
images/fb_og_config.png

You can obtain your Socialize App Url from the “SmartDownloads” section accessed from your dashboard at www.getsocialize.com

images/app_url.png

Once you have configured your application to accept custom Open Graph actions you can post these actions to Facebook by changing the PostData in the SocialNetworkListener.

	
if(FacebookUtils.isLinkedForWrite(this)) {
	Entity entity = Entity.newInstance("http://myentity.com", "My Entity Name");

	// Set the type of the entity to include the namespace.
	entity.setType("yournamespace:yourtype");
		
	ShareOptions options = ShareUtils.getUserShareOptions(this);
	options.setText("Text to be posted");

	// The "this" argument refers to the current Activity
	ShareUtils.shareViaSocialNetworks(this, entity, options, new SocialNetworkShareListener() {
		
		@Override
		public boolean onBeforePost(Activity parent, SocialNetwork socialNetwork, PostData postData) {
			
			if(socialNetwork.equals(SocialNetwork.FACEBOOK)) {
				// Change the post data to force an Open Graph call
				postData.setPath("me/yournamespace:youraction");
				
				// Set the type to be the entity URL
				postData.getPostValues().put("yourtype", postData.getPropagationInfo().getEntityUrl());
			}
			
			return false;
		}	
		
		@Override
		public void onNetworkError(Activity context, SocialNetwork network, Exception error) {
			// Handle error
		}
		
		@Override
		public void onCancel() {
			// The user cancelled the operation.
		}
		
		@Override
		public void onAfterPost(Activity parent, SocialNetwork socialNetwork, JSONObject responseObject) {
			// Called after the post returned from Facebook.
			// responseObject contains the raw JSON response from Facebook.
		}

	}, SocialNetwork.FACEBOOK);
}
else {
	// Handle non-linked case
}		

Posting Photos to Facebook

You can easily post photos to a user’s Facebook Photo Album using the post method on FacebookUtils

//The "this" argument refers to the current Activity
final Activity context = this;

if(FacebookUtils.isLinkedForWrite(this)) {
	final Entity entity = Entity.newInstance("http://myentity.com", "My Name");	
	
	// First create a Socialize share object so we get the correct URLs
	ShareOptions options = ShareUtils.getUserShareOptions(context);

	ShareUtils.registerShare(context, entity, options, new ShareAddListener() {
		
		@Override
		public void onError(SocializeException error) {
			// Handle error
		}
		
		@Override
		public void onCreate(Share result) {
			
			// We have the result, use the URLs to add to the post
			PropagationInfo propagationInfo = result.getPropagationInfoResponse().getPropagationInfo(ShareType.FACEBOOK);
			String link = propagationInfo.getEntityUrl();

			// Now post to Facebook.
			Map<String, Object> postData = new HashMap<String, Object>();
			
			// TODO: Get the URI of your image from the local device.
			// TODO: ***** DON'T FORGET TO USE YOUR OWN IMAGE HERE (See the sample app for a working example) ****
			Uri photoUri = null;
			
			try {
				
				// Format the picture for Facebook
				byte[] imageData = FacebookUtils.getImageForPost(context, photoUri);
				
				// Add the photo to the post
				postData.put("photo", imageData);
				
				// Add the link returned from Socialize to use SmartDownloads
				postData.put("caption", "A test photo of something " + link);
				
				// Add other fields to postData as necessary
				
				// Post to me/photos
				FacebookUtils.post(context, "me/photos", postData, new SocialNetworkPostListener() {
					
					@Override
					public void onNetworkError(Activity context, SocialNetwork network, Exception error) {
						// Handle error
					}
					
					@Override
					public void onCancel() {
						// The user cancelled the auth process
					}
					
					@Override
					public void onAfterPost(Activity parent, SocialNetwork socialNetwork, JSONObject responseObject) {
						// The post was successful
					}
				});			
			}
			catch (IOException e) {
				// Handle error
			}
		}
	}, SocialNetwork.FACEBOOK); // This is a Facebook-only share
}
else {
	// Handle non-linked case
}
	

Facebook Single Sign On (SSO)

Some users have reported having problems with the Single Sign On implementation in the Facebook SDK.

If you have experienced problems with this (e.g. the “invalid_key” error), you can easily disable this feature in your socialize.properties file

# Enable/Disable Single Sign On for Facebook
# Disable ONLY if you experience problems
facebook.sso.enabled=false

Or in code at runtime:

// Disable ONLY if you experience problems
// The "this" argument refers to the current Activity
ConfigUtils.getConfig(this).setFacebookSingleSignOnEnabled(false);