I have the following scenario with facebook sdk 3.0.1. When user first login and chooses "FB login" then the SSO starts, a new session is open and everything works fine. But then, when the user closes the app and start it again - I don't understand how to get the last open session, currently I'm opening a new session and the user sees again the FB progress bar(while it's being connected to FB again, even so the user already approved FB in his last run). Does anybody know how to skip this operation?
Edit 1:
This is how I retrieve the session:
public void tryRetrievFacebookSession() {
Session session = Session.getActiveSession();
if (session != null && session.isOpened())
return;
session = Session.openActiveSession(this, true, new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
MobliLog.d("SplashScreen", "Inside call() with session with state: " + session.getState());
// onSessionStateChanged(session, state, exception);
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Session session = Session.getActiveSession();
if (session != null)
session.onActivityResult(this, requestCode, resultCode, data);
uiHelper.onActivityResult(requestCode, resultCode, data);
}
The session is normally being created or from the LoginButton or with those lines:
session = Session.getActiveSession();
if (session.getState().isClosed())
session = new Session(this);
if (session.isOpened()) {
onAuthenticationEndListener.onSuccessfullAuthentication();
return;
} else {
this.onFacebookAuthenticationEndListener = onAuthenticationEndListener;
Session.setActiveSession(session);
session.openForRead(new Session.OpenRequest(SocNetwksCompatScreen.this).setCallback(null));
return;
}
Information 1:
When I'm doing the first Session session = Session.getActiveSession(); in the logins after the sso authentication, my session has state CLOSED instead of OPENED
Information 2:
I'm using uiHelper and initialize it like this:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
twitter = SocialPluginsUtils.getTwitterClient();
uiHelper = new UiLifecycleHelper(this, statusCallback);
uiHelper.onCreate(savedInstanceState);
}
Now, I know that after I perform Session.getActiveSession(); the session state should get OPENED and after that OPEN and then the uiHelper's callback should be invoked. In my code the state is CLOSED or CLOSED_LOGIN_FAILED or CREATED(not sure why it's not stable) and the rest doesn't happens
In fact the sessions are being closed every time the user closed the app.
So if Session.getActiveSession() return a null session you only need to call Session.openActiveSession(activity, true, sessionCallback).
If there is a valid token cache this method will use it in order to open a new session without the need for the user to insert any data. Otherwise this will shows the default dialog with the basic permissions.
From what I can see after your edit maybe the problem is related with the way in which you manage the session.
I use this code in my projects:
Session session = Session.getActiveSession();
if (session == null){
Session.openActiveSession(activity, true, sessionCallback);
}
else if (!session.getState().isOpened()){
session.openForRead(new Session.OpenRequest(activity)
.setCallback(sessionCallback));
//this will open the session with basic read permissions
}
else {
//do what you want with the opened session
}
Moreover if you use the UiLifecycleHelper you don't need the two line of code that I suggest to you in the comment, they are already in the method of the helper. But you must be sure to call all the methods of the helper in each related method of the activity (onResume, onPause etc.)
If there isn't a token cache the openActiveSession(activity, true, sessionCallback) will automatically call a new dialog and if the user login with success a new token cache will be available for future uses.
Problem solved. I accidentally called session.closeAndClearTokenInformation(); in the onStop() (yeah, so stupid!)
Related
I am trying to post image on Facebook using sdk 3.0, but I am facing some problems. If I close the app and reopens the app it always goes in else condition, then it goes in if condition. Do I need to save session or its already stored??
Session mSession = Session.getActiveSession();
if (mSession != null
&& mSession.getPermissions().contains("publish_actions")) {
postPhoto();
} else {
if (mSession == null) {
Log.d("Facebook", "Session null");
mSession = new Session.Builder(this).setApplicationId(
"xxxxxxxxxxxxxxx").build();
Session.setActiveSession(mSession);
}
if (!mSession.isOpened()) {
Log.d("Facebook", "Session not opened");
Session.OpenRequest sessionRequest = new Session.OpenRequest(
this);
sessionRequest.setPermissions(PERMISSIONS);
sessionRequest.setCallback(statuscallback);
sessionRequest
.setLoginBehavior(SessionLoginBehavior.SSO_WITH_FALLBACK);
mSession.openForPublish(sessionRequest);
}
}
StatusCallback statuscallback = new StatusCallback() {
#Override
public void call(Session session, SessionState state,
Exception exception) {
// TODO Auto-generated method stub
if (session.isOpened()) {
Log.d("Facebook", "Logged in");
postPhoto();
}
if (session.isClosed()) {
Log.d("Facebook", "Logged out");
}
}
};
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Session.getActiveSession().onActivityResult(this, requestCode,
resultCode, data);
Log.d("Facebook", "onActivity Result");
}
What if I need to logout the user??
I tried the following code onDestroy()
if (mSession.isOpened())
mSession.closeAndClearTokenInformation();
whenever I open the app next time it always throws an error at this line if I use the above code in destroy method
mSession.openForPublish(sessionRequest);
Please help guys. Answers/Suggestion would be highly appreciable.
Thanks
You can use the UiLifecycleHelper to help manage the active session throughout an Activity or Fragment lifecycle. Generally, all the session related data (access tokens, permissions, etc) are cached, and if you create a new Session(), it will use the cached data (unless you call closeAndClearTokenInformation, in which case it clears the cache). I would only call closeAndClearTokenInformation() on an explicit logout from the user, otherwise just call close() in onDestroy().
I would also avoid calling openForPublish. Always do openForRead, and then call session.getPermissions() to check if you have the necessary permissions, and then call requestNewPublishPermissions if you need more.
I am trying to implement the new Facebook SDK 3.0 into my Android app and I have run into a problem. The problem I am having is that the user is asked to log in again to give publish ("post_to_wall") permissions, even though the user is already logged in, with read permissions. This only happens if the user doesn't have the FB application installed. If he has the FB application installed, then he is only asked to grant the permissions.
This is how I implemented the login:
public void login(Activity activity) {
Session session = Session.getActiveSession();
if (session == null || !session.isOpened()) {
openActiveSession(activity, true, sessionStatusCallback);
}
}
private Session openActiveSession(final Activity activity, final boolean allowLoginUI, final StatusCallback callback) {
return openActiveSession(activity, allowLoginUI, new OpenRequest(activity).setCallback(callback));
}
private Session openActiveSession(final Context context, final boolean allowLoginUI, final OpenRequest openRequest) {
Session session = new Builder(context).setApplicationId(FACEBOOK_APPLICATION_ID).build();
if (SessionState.CREATED_TOKEN_LOADED.equals(session.getState()) || allowLoginUI) {
Session.setActiveSession(session);
session.openForRead(openRequest);
return session;
}
return null;
}
This is the callback's call method:
public void call(final Session session, final SessionState state, final Exception exception) {
if (session.isOpened()) {
if (state.equals(SessionState.OPENED_TOKEN_UPDATED)) {
// code if new permissions have been granted
} else {
// code for login
}
} else if (session.isClosed()) {
// code for user canceled login
} else if (exception != null) {
// code if there were errors during login
}
}
}
This is the code I added to onActivityResult method of the activity that calls the login:
Session.getActiveSession().onActivityResult(activity, requestCode, resultCode, data);
And this is how I ask for new permissions:
Session session = Session.getActiveSession();
if (session != null && session.isOpened()) {
if (DONT_HAVE_PERMISSIONS) {
Session.NewPermissionsRequest newPermissionsRequest = new Session.NewPermissionsRequest(activity,
FACEBOOK_PERMISSIONS).setRequestCode(FACEBOOK_AUTHORIZE_ACTIVITY_CODE);
session.requestNewPublishPermissions(newPermissionsRequest);
}
}
I've tried to find out more about this problem, and I only found out some hints that this is intended, but I haven't found anything concrete.
Is this the default behavior? If so, is there a way around it? Or, perhaps I did something wrong?
Thanks for the help.
Update your SDK version; this issue is resolved in Facebook Android SDK v3.0.1.
Looking at facebooks source code I think it should be possible to start trying to get the permissions directly as both login, and permissions classes derive from the same AuthorizationRequest class, and the AuthorizationRequest class does all the work, like really all the work. The Session.NewPermissionsRequest class just makes some private methods, public in the AuthorizationRequest class and that's it! They might as well give us access to AuthorizationRequest directly. The new facebook API doesn't seem to have any form of "OnFailed/OnSuccess" callbacks, so I end up having a state machine to remember the goal of firing up facebook (login, permissions, get friends list ...), and which step I'm on. If they have done some form of onFailed/onSuccess callbacks it would be simple to make a chain rather than keeping track of a state machine.
I haven't tried what I said. If I do, I'll update the answer. If you try and it works to just fire up Session.NewPermissionsRequest directly without logging in let me know!
Update
I got it working with only asking for credentials once as I explained above.
goto src/com/facebook/Sessions.java
On line 862 you will find
private static Session openActiveSession(Context context, boolean allowLoginUI, OpenRequest openRequest)
make it be a public function and save.
Now instead of creating the Session.NewPermissionsRequest object. Make Session.OpenRequest
permisions = new ArrayList<String>();
permisions.add("user_photos");
permisions.add("friends_photos");
Session.NewPermissionsRequest request = new Session.NewPermissionsRequest(
activity, permisions);
request.setCallback(helper);
if (Session.getActiveSession() != null)
Session.getActiveSession().requestNewReadPermissions(request);
else {
Session.OpenRequest orequest = new Session.OpenRequest(activity);
orequest.setPermissions(permisions);
orequest.setCallback(helper);
// its now public so you can call it
Session.openActiveSession(act, true, request);
}
Now make sure you do set a callback, for one important reason
#Override
public void call(Session session, SessionState state, Exception exception) {
if (state.isClosed()) {
// we are doing unofficial stuff so we loose guarantees.
// Set the active session to null if we logout or user cancels
// logging in. If you don't do this, the second time it will result
// in a crash.
Session.setActiveSession(null);
}
}
Now it will ask for all permissions directly and login in one go.
I am developing an Android App that integrates with Facebook. I would like to:
Let the user login with Facebook
Get the user's email address on Facebook (could be a proxied email address, which is fine)
Post to the user's wall/timeline on his/her behalf
Technically, that would be to:
Authenticate the user
Request the email permission
Request the publish_stream permission
1. Authenticate the user
I called Session.openActiveSession() with a Session.StatusCallback (I already checked that there is no active opened session beforehand):
final Session.StatusCallback sessionStatusCallback = new Session.StatusCallback() {
public void call(final Session session, SessionState state, Exception exception) {
// If there is an exception...
if(exception != null)
{
// Handle fail case here.
return;
}
// If session is just opened...
if(state == SessionState.OPENED)
{
// Handle success case here.
return;
}
};
};
// Start Facebook Login.
Session.openActiveSession(activity, true, sessionStatusCallback);
My callback is called after successful login. So far so good.
2. Request the email permission
This is my status callback:
new Session.StatusCallback() {
public void call(final Session session, SessionState state, Exception exception) {
// If there is an exception...
if(exception != null)
{
// Handle fail case here.
return;
}
// If token is just updated...
if(state == SessionState.OPENED_TOKEN_UPDATED)
{
// Handle success case here.
return;
}
};
};
I request the permission with Session.requestNewReadPermissions():
final Session session = Session.getActiveSession();
final static String[] PERMISSION_ARRAY_READ = {"email"};
final List<String> permissionList = Arrays.asList(PERMISSION_ARRAY_READ);
// If all required permissions are available...
if(session.getPermissions().containsAll(permissionList))
{
// Handle success case here.
return;
}
// Request permissions.
session.requestNewReadPermissions(new Session.NewPermissionsRequest(activity, permissionList));
My callback is called after permission is granted. So far so good.
3. Request the publish_stream permission
This is my status callback:
new Session.StatusCallback() {
public void call(final Session session, SessionState state, Exception exception) {
// If there is an exception...
if(exception != null)
{
// Handle fail case here.
return;
}
// If token is just updated...
if(state == SessionState.OPENED_TOKEN_UPDATED)
{
// Handle success case here.
return;
}
};
};
I request the permission with Session.requestNewPublishPermissions():
final Session session = Session.getActiveSession();
final static String[] PERMISSION_ARRAY_PUBLISH = {"publish_stream"};
final List<String> permissionList = Arrays.asList(PERMISSION_ARRAY_PUBLISH);
// If all required permissions are available...
if(session.getPermissions().containsAll(permissionList))
{
// Handle success case here.
return;
}
// Request permissions.
session.requestNewPublishPermissions(new Session.NewPermissionsRequest(activity, permissionList));
This time, my callback is not called after permission is granted.
Investigation
Upon further investigation, I found that my callback is triggered by com.facebook.Session#postStateChange(SessionState, SessionState, Exception):
void postStateChange(final SessionState oldState, final SessionState newState, final Exception exception) {
if (oldState == newState && exception == null) {
return;
}
/* ... */
}
Since oldState and newState are equal (both being SessionState.OPENED_TOKEN_UPDATED, my callback is not called.
Question
How can I receive any notification after permission is granted for the 2nd time? Am I supposed to close() the session and re-open it from cache?
Additional info
My Facebook Android SDK 3.0 is download from here, which is stated in Facebook's Getting Started with the Facebook SDK for Android.
This is a bug.
[edit: As Guy points out in comments, this was fixed in 3.0.1, so this workaround is no longer necessary]
The workaround you mention is basically correct, though you do not need to call close. If you are using the single active session, before calling requestNewPublishPermissions() just call:
Session.openActiveSessionFromCache(myContext);
If you are using multiple sessions, you need to initialize a new Session with the TokenCachingStrategy, verify it is in the CREATED_TOKEN_LOADED state, and call openForRead(null);
After doing one of these, requestNewPublishPermissions() should call your notification once it completes.
Working code based on rightparen's answer
Before requesting permission for the 2nd time (i.e. before Session.requestNewPublishPermissions()), do this:
// Re-initialize Facebook session.
session.removeCallback(sessionStatusCallback); // Remove callback from old session.
session = Session.openActiveSessionFromCache(context); // Create new session by re-opening from cache.
session.addCallback(sessionStatusCallback); // Add callback to new session.
Code is still based on Facebook Android SDK 3.0, as in the question.
Another thing I ran into was that my requestCode for the NewPermissionRequest was not being set to the same requestCode that I used to open my Session for Read with, thereby my Session.StatusCallback was never being invoked when the new permissions have been granted.
For instance, in my onActivityResult I have a check for the requestCode and delegate the call accordingly because I have other stuff coming in to this method.
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
if (requestCode == FACEBOOK_AUTH_RESULT_CODE) {
Session session = Session.getActiveSession();
if(session != null) {
session.onActivityResult(activity, requestCode, resultCode, data);
}
}
}
I then opened my Session with the following code :
Session.getActiveSession().openForRead(
new Session.OpenRequest(activity).
setLoginBehavior(SessionLoginBehavior.SSO_WITH_FALLBACK).
setRequestCode(FACEBOOK_AUTH_RESULT_CODE).
setPermissions(MY_READ_PERMISSIONS));
I then forgot to use the same requestCode when constructing my NewPermissionRequest.
This is what the correct NewPermissionRequest needs to look like :
Session.getActiveSession().requestNewPublishPermissions(
new NewPermissionsRequest(activity, MY_PUBLISH_PERMISSIONS)
.setRequestCode(FACEBOOK_AUTH_RESULT_CODE));
The title says it all. I'm using a custom button to fetch the user's facebook information (for "sign up" purposes). Yet, I don't want the app to remember the last registered user, neither the currently logged in person via the Facebook native app. I want the Facebook login activity to pop up each time. That is why I want to log out any previous users programmatically.
How can I do that? This is how I do the login:
private void signInWithFacebook() {
SessionTracker sessionTracker = new SessionTracker(getBaseContext(), new StatusCallback()
{
#Override
public void call(Session session, SessionState state, Exception exception) {
}
}, null, false);
String applicationId = Utility.getMetadataApplicationId(getBaseContext());
mCurrentSession = sessionTracker.getSession();
if (mCurrentSession == null || mCurrentSession.getState().isClosed()) {
sessionTracker.setSession(null);
Session session = new Session.Builder(getBaseContext()).setApplicationId(applicationId).build();
Session.setActiveSession(session);
mCurrentSession = session;
}
if (!mCurrentSession.isOpened()) {
Session.OpenRequest openRequest = null;
openRequest = new Session.OpenRequest(RegisterActivity.this);
if (openRequest != null) {
openRequest.setPermissions(null);
openRequest.setLoginBehavior(SessionLoginBehavior.SSO_WITH_FALLBACK);
mCurrentSession.openForRead(openRequest);
}
}else {
Request.executeMeRequestAsync(mCurrentSession, new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser user, Response response) {
fillProfileWithFacebook( user );
}
});
}
}
Ideally, I would make a call at the beginning of this method to log out any previous users.
Update for latest SDK:
Now #zeuter's answer is correct for Facebook SDK v4.7+:
LoginManager.getInstance().logOut();
Original answer:
Please do not use SessionTracker. It is an internal (package private) class, and is not meant to be consumed as part of the public API. As such, its API may change at any time without any backwards compatibility guarantees. You should be able to get rid of all instances of SessionTracker in your code, and just use the active session instead.
To answer your question, if you don't want to keep any session data, simply call closeAndClearTokenInformation when your app closes.
This method will help you to logout from facebook programmatically in android
/**
* Logout From Facebook
*/
public static void callFacebookLogout(Context context) {
Session session = Session.getActiveSession();
if (session != null) {
if (!session.isClosed()) {
session.closeAndClearTokenInformation();
//clear your preferences if saved
}
} else {
session = new Session(context);
Session.setActiveSession(session);
session.closeAndClearTokenInformation();
//clear your preferences if saved
}
}
Since Facebook's Android SDK v4.0 (see changelog) you need to execute the following:
LoginManager.getInstance().logOut();
Here is snippet that allowed me to log out programmatically from facebook. Let me know if you see anything that I might need to improve.
private void logout(){
// clear any user information
mApp.clearUserPrefs();
// find the active session which can only be facebook in my app
Session session = Session.getActiveSession();
// run the closeAndClearTokenInformation which does the following
// DOCS : Closes the local in-memory Session object and clears any persistent
// cache related to the Session.
session.closeAndClearTokenInformation();
// return the user to the login screen
startActivity(new Intent(getApplicationContext(), LoginActivity.class));
// make sure the user can not access the page after he/she is logged out
// clear the activity stack
finish();
}
Since Facebook's Android SDK v4.0 you need to execute the following:
LoginManager.getInstance().logOut();
This is not sufficient. This will simply clear cached access token and profile so that AccessToken.getCurrentAccessToken() and Profile.getCurrentProfile() will now become null.
To completely logout you need to revoke permissions and then call LoginManager.getInstance().logOut();. To revoke permission execute following graph API -
GraphRequest delPermRequest = new GraphRequest(AccessToken.getCurrentAccessToken(), "/{user-id}/permissions/", null, HttpMethod.DELETE, new GraphRequest.Callback() {
#Override
public void onCompleted(GraphResponse graphResponse) {
if(graphResponse!=null){
FacebookRequestError error =graphResponse.getError();
if(error!=null){
Log.e(TAG, error.toString());
}else {
finish();
}
}
}
});
Log.d(TAG,"Executing revoke permissions with graph path" + delPermRequest.getGraphPath());
delPermRequest.executeAsync();
Session class has been removed on SDK 4.0. The login magement is done through the class LoginManager. So:
mLoginManager = LoginManager.getInstance();
mLoginManager.logOut();
As the reference Upgrading to SDK 4.0 says:
Session Removed - AccessToken, LoginManager and CallbackManager classes supercede and replace functionality in the Session class.
Yup, As #luizfelippe mentioned Session class has been removed since SDK 4.0. We need to use LoginManager.
I just looked into LoginButton class for logout. They are making this kind of check. They logs out only if accessToken is not null. So, I think its better to have this in our code too..
AccessToken accessToken = AccessToken.getCurrentAccessToken();
if(accessToken != null){
LoginManager.getInstance().logOut();
}
private Session.StatusCallback statusCallback = new SessionStatusCallback();
logout.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Session.openActiveSession(this, true, statusCallback);
}
});
private class SessionStatusCallback implements Session.StatusCallback {
#Override
public void call(Session session, SessionState state,
Exception exception) {
session.closeAndClearTokenInformation();
}
}
Facebook provides two ways to login and logout from an account. One is to use LoginButton and the other is to use LoginManager. LoginButton is just a button which on clicked, the logging in is accomplished. On the other side LoginManager does this on its own. In your case you have use LoginManager to logout automatically.
LoginManager.getInstance().logout() does this work for you.
I'm using FB API 3.0 for Android, and I'm trying to set the session in proper way.
But, it seems I'm doing something wrong, or to say I'm missing something.
In my launcher activity, I check if there is a session already and if it does not exist I create new one (as in FB example):
Settings.addLoggingBehavior(LoggingBehaviors.INCLUDE_ACCESS_TOKENS);
Session session = Session.getActiveSession();
if (session != null){
String sesija = session.toString();
Log.w ("ss", sesija);}
if (session == null) {
if (savedInstanceState != null) {
session = Session.restoreSession(this, null, MyGlobals.INSTANCE.statusCallback, savedInstanceState);
Log.w("No Session found", "Loading saved session as it exists");
}
if (session == null) {
session = new Session(this);
Log.w("No Session found", "CreatingNewSession");
String sesija2 = session.toString();
Log.w ("ss2", sesija2);
}
Session.setActiveSession(session);
if (session.getState().equals(SessionState.CREATED_TOKEN_LOADED)) {
session.openForRead(new Session.OpenRequest(this).setCallback(MyGlobals.INSTANCE.statusCallback));
Log.w("There is an active session", "Active Session Exists");
}
}
At this point my log says this:
10-24 09:11:52.284: W/ss(1404): {Session state:CREATED, token:{AccessToken token: permissions:[}, appId:xxxxxx}
(AppId is correct)
Then in my fragment, I try to log on to facebook using this code:
Session session = Session.getActiveSession();
if (!session.isOpened() && !session.isClosed()) {
Log.w("Session is not opend", "Session is not closed");
session.openForRead(new Session.OpenRequest(getActivity()).setCallback(MyGlobals.INSTANCE.statusCallback));
} else {
Session.openActiveSession(getActivity(), true, MyGlobals.INSTANCE.statusCallback);
Log.w("Open Active Session", "Status Callback");
}
At this point, FB webview appears, I set username and pass, it kind a works, and then disappears.
Now, I'm sort of nowhere, I do not see response and TOKEN recived, and if I click again to login (on the same button) my App crashes.
In the log I have this then:
10-24 09:12:31.944: W/ss(1404): {Session state:OPENING, token:{AccessToken token: permissions:[}, appId:xxxxxx}
If I compare it to SessionLoginExample provided by FB, I get there:
10-24 09:08:50.004: W/ss(1356): {Session state:OPENED, token:{AccessToken token:AAAFaKtb7Pg4BALYg4B5eosa0ZAE9ZAXB0ZBMFDJdNbsDsZAkGJUfKtGs71OEJikDxT2VBfo4QMXiNASz23ZAa6D76eUxW0mZAMa013HP2kxgZDZD permissions:[}, appId:xxxxxxx}
Meaning I'm doing something wrong, as I do not catch the returned AccessToken, and it is not saved properly.
That's what I think is wrong, but I do not understand how should I read the session information in proper way, or to say where to catch and save Token information within the fragment.
I tried to put in the fragment:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Boolean session = Session.getActiveSession().onActivityResult(getSherlockActivity(), requestCode, resultCode, data);
}
As this was the "onActivityResult" in the example, but it seems that it does nothing.
Just to sum things up:
I create session behind the launcher activity. Then if there is no FB app installed, on Tab4 (settings) user should be able to log on to FB using webview. Then on Tab1 and Tab2 user should be able to Share image to FB similar like on Instagram.
If there is the app installed, I'd disable the tab 4, and let user share throuhg FB app using Tab1 and Tab2.
Tnx.
RESOLVED:
Thing that is never written but should be well known. When FB authentication is performed, the "On Activity Result" code must be executed to save the Token with the session.
However, if you are dealing with Fragments and Tabs, like I do, function "onActivityResult" is never executed within Fragment code, but must be executed in the Activity that is taking care of fragments/tabs.
So it looks like you have already worked around this and your workaround is fine, but I wanted to give another option here in case it is cleaner for you or others to use the Fragment for this instead.
For cases where you cannot or do not want to derive from FacebookActivity, you can use either your Activity or your Fragment to initialize the Session. Both Activity and Fragment have onActivityResult you can override, and the one that gets used depends on what you pass to initialize Session.OpenRequest.
So if you want the callback to come to the Fragment, you can call:
...new Session.OpenRequest(myFragment)...
Then override onActivityResult in your Fragment and forward the call to your Session.
This is somewhat nicer in that your Fragment no longer needs to have special knowledge of what Activity it is running in.