I'm writing an application which requires facebook login. I can make user log in when he/she first opens the application. However, I can't retrieve the session after they restart the application. My login code is the following:
private static Session openActiveSession(Activity activity, boolean allowLoginUI, StatusCallback callback, List<String> permissions) {
OpenRequest openRequest = new OpenRequest(activity).setPermissions(permissions).setCallback(callback);
Session session = new Session.Builder(activity).build();
if (SessionState.CREATED_TOKEN_LOADED.equals(session.getState()) || allowLoginUI) {
Session.setActiveSession(session);
session.openForRead(openRequest);
return session;
}
return null;
}
And I use isLoggedIn method when the app is opened in order to understand if the user is logged in or not.
public static boolean isLoggedIn() {
Session session = Session.getActiveSession();
if (session != null && session.isOpened()) {
return true;
} else {
return false;
}
}
But when the application is closed and reopened, this method never returns true.
How can I retrieve old session back without showing a popup window to want user's facebook account informations, if he/she logged in in the past.
You can call Session.openActiveSessionFromCache which will open the active session only if there's a cached access token, or return null otherwise.
Related
When I Login First Time with Facebook it work Properly and Redirect To another Page,but when I perform sign out operation with Facebook Account And Re-login With Facebook It can Not work Properly till Relaunch application.
If I Relaunch Application it perform Login properly.
This method will help you to clear token information and 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
}
}
I use the following method to login to Facebook using the Facebook sdk. I added there an exception try/catch handler that caught the following exception:
Exception ::::::﹕ Session: an attempt was made to open an already
opened session.
As you can see I check if the session is closed before I open it. and it passes it which means its closed and it is safe to open it. even that an exception is caught.
I run the debugger and stopped at the line marked below and checked the currentSession state and it is closed!!!!!
private Session openActiveSession(Activity activity, boolean allowLoginUI, List permissions, Session.StatusCallback callback) {
Session currentSession = Session.getActiveSession();
if (currentSession == null) {
Session session = new Session.Builder(activity).build();
Session.setActiveSession(session);
currentSession = session;
}
if (!currentSession.isOpened() && (SessionState.CREATED_TOKEN_LOADED.equals(currentSession.getState()) || allowLoginUI)) {
try {
Session.OpenRequest openRequest = new Session.OpenRequest(activity).setPermissions(permissions).setCallback(callback);
currentSession.openForRead(openRequest); // I stopped here..
} catch (Exception e) {
Log.d("Exception :::::: ", e.getMessage()); // and stopped here.
}
return currentSession;
}
return null;
}
Any explanation?
Could that mean that there is another session that is open? my could always gets an active session if exists I don't see how that could happen. I always check for active session in all methods and use it!
How Session.getActiveSession() method really works? what if another session has been initialised in a previous activity? this method should get it right?
The error message could be improved, I think. It should actually say: "an attempt was made to open a session that's already open, or has already been closed".
You should check to see if currentSession.isClosed() is true, and if so, create a new session.
A session can only be opened once. It can't be re-opened.
I use com.facebook.widget.UserSettingsFragment to manage login/logout to Facebook in my app:
UserSettingsFragment userSettingsFragment = new UserSettingsFragment();
Session session = Session.getActiveSession();
if(session==null || session.isClosed()){
userSettingsFragment.setPublishPermissions(Arrays.asList("publish_actions"));
}
fragmentTransaction.replace(R.id.content_container, userSettingsFragment, "userSettingsFragment");
In another Fragment (but same Activity), Before publishing on Facebook I'm checking whether I'm logged using
Session session = Session.getActiveSession();
if (session != null && session.isOpened()){
publishOnFacebook(intent.getExtras());
}
When I start my app and try to publish, I always get a null Session although I logged in before. And when I start UserSettingsFragment, it shows me that I'm connected.
How can Session.getActiveSession(); be null if I'm actually connected?
Moreover, if I I start the Fragment where I do the publishing straight after UserSettingsFragment, I get the correct Session, i.e.:
1 start the app
2 call `Session.getActiveSession()` in another `Fragment` returns `null`
3 start `UserSettingsFragment` shows that I'm log
but
1 start the app
2 start `UserSettingsFragment` shows that I'm log
3 call `Session.getActiveSession()` in another `Fragment` returns a session
Anybody can help?
Ok, I've just read about openActiveSessionFromCache (not from Facebook doc though):
Session session = Session.getActiveSession();
if(session==null){
// try to restore from cache
session = Session.openActiveSessionFromCache(getActivity());
}
if(session!=null && session.isOpened()){
publishOnFacebook(intent.getExtras());
}
else{
login();
}
Jul's answer does not work for me. So I tried this:
If you had loggedin earlier and if you restarted the app then the session may not be null and it could be in the CREATED_TOKEN_LOADED state. This state implies that the Session has not yet been opened and has a cached token. Opening a Session in this state will not involve user interaction. To open the session from this state you can call the method session.openForRead(null). This immediately opens the session without any user interaction.
So check for this add the following code:
Session session = Session.getActiveSession();
if (session != null){
if(session.getState() == SessionState.CREATED_TOKEN_LOADED){
//this immediately opens the session
session.openForRead(null);
}
if(session.isOpened()) {
publishOnFacebook(intent.getExtras());
}
else{
//start the facebook login fragment or activity
login();
}
}
else{
login();
}
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.
Hi I'm using Facebook sdk3.0 for Android. How can I check whether a user is logged in or not?
Currently I'm using this:
public static boolean isUserLoggedInWithFacebook() {
Session session = Session.getActiveSession();
if(session != null && session.isOpened())
return true;
return false;
}
But it sometimes gives false while user is still logged in.
try using facebook.isSessionValid(). It should return false if the user is logged out.