Skip to content

Instantly share code, notes, and snippets.

@sgdesmet
Created December 17, 2013 15:48
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sgdesmet/8007039 to your computer and use it in GitHub Desktop.
Save sgdesmet/8007039 to your computer and use it in GitHub Desktop.
Post messages to Facebook with the Android Facebook SDK (v3.6)
package com.github.sgdesmet.android;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import com.facebook.*;
import com.facebook.widget.FacebookDialog;
import com.facebook.widget.WebDialog;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import com.github.sgdesmet.android.R;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import android.support.v4.app.Fragment;
/**
* Facebook login and sharing example
*
* @author sgdesmet
*/
public abstract class AbstractShareFragment extends Fragment {
private static final List<String> FB_PERMISSIONS = Arrays.asList( "publish_actions" );
private static final String TAG = AbstractShareFragment.class.getName();
private static final String PENDING_MESSAGE = "pending_message";
private UiLifecycleHelper fbUiHelper;
private FbMessage pendingMessage;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate( savedInstanceState );
fbUiHelper = new UiLifecycleHelper( getActivity(), new SessionCallback() );
fbUiHelper.onCreate( savedInstanceState );
if (savedInstanceState != null)
pendingMessage = (FbMessage) savedInstanceState.getSerializable( PENDING_MESSAGE );
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
fbUiHelper.onActivityResult( requestCode, resultCode, data, new ShareDialogCallbackWrapper() );
super.onActivityResult( requestCode, resultCode, data );
}
@Override
public void onResume() {
super.onResume();
fbUiHelper.onResume();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState( outState );
fbUiHelper.onSaveInstanceState( outState );
outState.putSerializable( PENDING_MESSAGE, pendingMessage );
}
@Override
public void onPause() {
super.onPause();
fbUiHelper.onPause();
}
@Override
public void onDestroy() {
super.onDestroy();
fbUiHelper.onDestroy();
}
/**
* General share
* @param name
* @param description
* @param url
* @param imageUrl
*/
protected void share(@NotNull final String name, @NotNull final String description, @Nullable final String url,
@Nullable final String imageUrl) {
shareWithFB( name, description, url, imageUrl );
}
/**
* Share with facebook.
*/
public void shareWithFB(@NotNull final String name, @NotNull final String description, @Nullable final String url,
@Nullable final String imageUrl) {
if (getActivity() == null)
return;
pendingMessage = new FbMessage( name, description, url, imageUrl );
// check if user logged in / has permission to post
Session session = Session.getActiveSession();
if (session == null) {
session = new Session.Builder( getActivity() ).setApplicationId( getString( R.string.app_id ) ).build();
Session.setActiveSession( session );
}
// if the session is not open or opening, we need to open it
if (!session.getState().isOpened() && session.getState() != SessionState.OPENING) {
Session.OpenRequest openRequest = new Session.OpenRequest( this );
openRequest.setPermissions( FB_PERMISSIONS );
openRequest.setLoginBehavior( SessionLoginBehavior.SSO_WITH_FALLBACK );
session.openForPublish( openRequest );
return;
}
// if the session is open, try to post message (else we wait for session callback)
if (session.isOpened()) {
if (hasPublishPermission()) {
// We can do the action right away.
postMessage( pendingMessage );
pendingMessage = null;
} else {
// We need to reauthorize, then complete the action when we get
// called back.
// requestCode -1 means use the default facebook value
Session.NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest( this,
FB_PERMISSIONS ).setRequestCode( -1 ).setLoginBehavior( SessionLoginBehavior.SSO_WITH_FALLBACK );
session.requestNewPublishPermissions( newPermissionsRequest );
}
}
}
private boolean hasPublishPermission() {
Session session = Session.getActiveSession();
return session != null && session.isOpened() && session.getPermissions().contains( "publish_actions" );
}
protected void postMessage(@NotNull final FbMessage message) {
// check if we can use native FB app, or need to fall back to web-based dialog
if (getActivity() != null && FacebookDialog.canPresentShareDialog( getActivity().getApplicationContext(),
FacebookDialog.ShareDialogFeature.SHARE_DIALOG )) {
postUsingShareDialog( message );
} else if (getActivity() != null) {
postUsingWebDialog( message );
}
}
protected void postUsingShareDialog(@NotNull final FbMessage message) {
FacebookDialog.ShareDialogBuilder builder = new FacebookDialog.ShareDialogBuilder( getActivity() ).setName( message.name )
.setDescription(
message.description );
if (StringUtils.isNotBlank( message.url ))
builder.setLink( message.url );
if (StringUtils.isNotBlank( message.imageUrl ))
builder.setPicture( message.url );
fbUiHelper.trackPendingDialogCall( builder.build().present() );
}
protected void postUsingWebDialog(@NotNull final FbMessage message) {
Bundle params = new Bundle();
params.putString( "name", message.name );
params.putString( "description", message.description );
if (StringUtils.isNotBlank( message.url ))
params.putString( "link", message.url );
if (StringUtils.isNotBlank( message.imageUrl ))
params.putString( "picture", message.imageUrl );
WebDialog feedDialog = (new WebDialog.FeedDialogBuilder( getActivity(), Session.getActiveSession(), params )).setOnCompleteListener(
new WebDialogCallbackWrapper() ).build();
feedDialog.show();
}
@NotNull
protected abstract ShareCallback getShareCallback();
public static interface ShareCallback {
public void success();
public void cancelled();
public void error();
}
/**
* Facebook callback when sharing with native dialog
*/
private class ShareDialogCallbackWrapper implements FacebookDialog.Callback, Serializable {
@Override
public void onError(FacebookDialog.PendingCall pendingCall, Exception error, Bundle data) {
Log.e( "Activity", String.format( "Error: %s", error.toString() ) );
getShareCallback().error();
}
@Override
public void onComplete(FacebookDialog.PendingCall pendingCall, Bundle data) {
if (data != null && StringUtils.isNotBlank( data.getString( "FacebookDialog.getNativeDialogPostId" ) ))
getShareCallback().success();
else
getShareCallback().cancelled();
}
}
/**
* Facebook callback when sharing with web-based (fallback) dialog
*/
private class WebDialogCallbackWrapper implements WebDialog.OnCompleteListener, Serializable {
@Override
public void onComplete(final Bundle values, final FacebookException error) {
if (error == null) {
// When the story is posted, echo the success
final String postId = values.getString( "post_id" );
if (postId != null) {
getShareCallback().success();
} else {
// User clicked the Cancel button
getShareCallback().cancelled();
}
} else if (error instanceof FacebookOperationCanceledException) {
// User clicked the "x" button
getShareCallback().cancelled();
} else {
// Generic, ex: network error
getShareCallback().error();
}
}
}
private class SessionCallback implements Session.StatusCallback, Serializable {
@Override
public void call(final Session session, final SessionState state, final Exception exception) {
Log.d( AbstractShareFragment.TAG, "Session state changed to: " + state );
if (pendingMessage != null && session != null) {
shareWithFB( pendingMessage.name, pendingMessage.description, pendingMessage.url, pendingMessage.imageUrl );
}
}
}
public static class FbMessage implements Serializable {
@NotNull
final String name;
@NotNull
final String description;
@Nullable
final String url;
@Nullable
final String imageUrl;
public FbMessage(@NotNull final String name, @NotNull final String description, @Nullable final String url,
@Nullable final String imageUrl) {
this.name = name;
this.description = description;
this.url = url;
this.imageUrl = imageUrl;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment