I followed the FB tutorial step by step, and I can't figure out why is this not working.
All my fragments inherits from the BaseFragment :
public class BaseFragment extends SherlockFragment {
...
protected UiLifecycleHelper _uiHelper;
protected boolean _isResumed = false;
protected static final List<String> PERMISSIONS = Arrays.asList("publish_actions");
protected static final String PENDING_PUBLISH_KEY = "pendingPublishReauthorization";
protected boolean _pendingPublishReauthorization = false;
protected Session.StatusCallback _callback = new Session.StatusCallback() {
@Override
public void call(Session session, SessionState state, Exception exception) {
onSessionStateChange(session, state, exception);
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
_uiHelper = new UiLifecycleHelper(getSherlockActivity(), _callback);
_uiHelper.onCreate(savedInstanceState);
}
protected void onSessionStateChange(Session session, SessionState state, Exception exception) {}
...(all lifecycle stuff)
}
Then I have a FacebookLoginFragment which contains the login/logout button :
public class FacebookLoginFragment extends BaseFragment {
protected LoginButton _authButton;
protected ProgressBar _loadingBar;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.facebook_login, container, false);
_loadingBar = (ProgressBar) view.findViewById(R.id.login_progressBar);
_authButton = (LoginButton) view.findViewById(R.id.authFacebookButton);
_authButton.setFragment(this);
_authButton.setReadPermissions(Arrays.asList("email", "user_birthday"));
return view;
}
@Override
protected void onSessionStateChange(Session session, SessionState state, Exception exception) {
super.onSessionStateChange(session, state, exception);
// LogIn process
}
...
}
And finally I've a NewsFragment which contains a listView of feeds. Each feed is sharable. When we click on the share button of a feed, the adapter call the NewsFragment.publishFeed(feed) method.
public class NewsFragment extends BaseFragment{
...
protected Feed _feedPendingPublish;
@Override
// => NEVER CALLED
protected void onSessionStateChange(Session session, SessionState state, Exception exception) {
super.onSessionStateChange(session, state, exception);
if (_isResumed) {
if (_pendingPublishReauthorization && state.equals(SessionState.OPENED_TOKEN_UPDATED)) {
_pendingPublishReauthorization = false;
if(_feedPendingPublish != null){
publishFeed(_feedPendingPublish);
_feedPendingPublish = null;
}
}
}
}
public void publishFeed(Feed feed){
if(_pendingPublishReauthorization){
return;
}
Session session = Session.getActiveSession();
if (session != null){
// If permission doesn't exist, ask and return. Otherwise, send request
List<String> permissions = session.getPermissions();
if (!isSubsetOf(PERMISSIONS, permissions)) {
_pendingPublishReauthorization = true;
_feedPendingPublish = feed;
Session.NewPermissionsRequest newPermissionsRequest = new Session
.NewPermissionsRequest(getSherlockActivity(), PERMISSIONS);
session.requestNewPublishPermissions(newPermissionsRequest);
return;
}
// DO stuff
}
}
}
The problem is that the NewsFragment callback is not called after the publish authorization. (neither the BaseFragment, neither the FacebookLogin). Note that both fragments exist in the same activity.
I'm using facebook-android-sdk-3.5.2
Even if you add the callback as Ming said, you may have an issue.
See this bug: https://developers.facebook.com/bugs/130681460449340
It looks like there is a proposed solution/workaround in the comments.
Yes, there indeed seems to still be a bug around callbacks and new permissions requests.
As a temporary work around, you can call:
just before you call session.requestNewPublishPermissions.
Note that this callback will now receive all future state changes on your session. If that's not what you want, you can always call session.removeCallback(yourCallback) after you do the publish.
I finally figured this out. As many people said, it was an
onActivityResult()
problem, but quite vicious.When Log In, the
FacebookLoginFragment.onSessionStateChange()
was called succefully, whereas theNewsFragment.onSessionStateChange()
was never called during the persmission process.After several tests, I assume this was due to a static and dynamic binding. My
FacebookLoginfragment
is directy referenced in the xml (static), whereas my NewsFragment is added dynamically in the source code. Consequently, the Activity which contains both fragments was only sending theonActivityResult
signal to theFacebokLoginFragment
. Therefore, theNewsFragment.onActivityResult()
which is necessary to trigger the callback was never called.Overriding the
Activity.onActivityResult()
gives me the expected behavior :