Facebook session get closed when trying to post status - android

here is my code for updating status:
new Session(context);
Session.setActiveSession(session);
Session.openActiveSession(context);
Log.e("session after setted",Session.getActiveSession().toString());
Request request = Request.newMeRequest(Session.getActiveSession(), new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser user, Response response) {
// If the response is successful
if (Session.getActiveSession().isOpened()) {
if (user != null) {
session = Session.getActiveSession();
postFromAlarm();
Log.e("user","not null");
}else{
postFromAlarm();
Log.e("user","null");
}
} else{
postFromAlarm();
Log.e("not open session",Session.getActiveSession().toString());
Log.e("session","not open");
}
}
});
Log.e("request session",request.getSession().toString());
Request.executeBatchAsync(request);
Log.e("session after setted",Session.getActiveSession().toString());
is showing a good and healthy session, which can be used for posting. because in logcat, it is showing that the session is open, accesstoken is good, app_id is also good.
but using this session when i am trying to post, in the onComplete() method, executed these lines:
Log.e("not open session",Session.getActiveSession().toString());
Log.e("session","not open");
and it is showing that:
{Session state:CLOSED, token:null, appId:***************** }
what is wrong? i have tried without new Session(context), but getting the same result. what should i do?

save the session when you create it for first time using
SessionStore.save(mFacebook, getBaseContext());
and also restore the session when same user performs post operation
SessionStore.restore(mFacebook, getBaseContext());
where mFacebook is your Facebook object reference

Related

Android - Facebook session CLOSED when using ParseFacebookUtils.logIn

I am using Facebook and Parse SDK in my Android app. I followed this tutorial for Facebook login and authentication, changing between fragments for login fragment and main menu fragment depending on whether the session state is OPENED in the Session.StatusCallback. And the app works perfectly before integrating with Parse.
And now I encounter a problem. In the onResume() method of the main menu fragment, I added the following code.
final Session session = Session.getActiveSession();
if(session != null && session.isOpened()) {
Request meRequest = Request.newMeRequest(session, new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser graphUser, Response response) {
if(session == Session.getActiveSession()) {
// Check if the session is same as usual
ParseFacebookUtils.logIn(graphUser.getId(), session.getAccessToken(),
session.getExpirationDate(), new LogInCallback() {
#Override
public void done(ParseUser user, ParseException err) {
if (user == null) {
// The user wasn't saved.
System.out.println("User was not saved to Parse. ");
} else {
// The user has been saved to Parse.
System.out.println("User has successfully been saved to Parse.");
if (user.isNew()) {
// This user was created during this session with Facebook Login.
System.out.println("ParseUser created.");
} else {
// This user existed before.
System.out.println("User exists in Parse. Pull their values: " + user);
}
}
}
});
}
}
});
meRequest.executeAsync();
}
So when the fragment is resumed and the Facebook session is opened, the Facebook user is added to the Parse database so that I can use ParseUser to put and get data afterwards. But the problem happens when using ParseFacebookUtils.logIn(), that it makes the Facebook session CLOSED and invokes the Session.StatusCallback, thus switching the visible fragment back to the login fragment.
I was dealing with this problem all day but cannot find a solution. I have added the code below in an Application but still not work.
Parse.enableLocalDatastore(this);
Parse.initialize(this, Application_id, Client_key);
ParseFacebookUtils.initialize(getString(R.string.facebook_app_id));
Is there a way to fix this? I have read this but no quite good solution is provided. Thanks in advance!
I was trying to do the same thing today. I was using the facebook sdk's UiLifecycleHelper to do the facebook login, make the graph api request and add the user to Parse db. That is how it is done in the example you mentioned - which I think is a bit outdated.
ParseFacebookUtils handles the session and all we need to do is call the login method on it, make the graph api call, get user data like email and update the user field.
Here's some code:
private void parseFacebookLogin(){
ParseFacebookUtils.logIn(this, PARSE_FB_LOGIN_CODE, new LogInCallback() {
#Override
public void done(ParseUser user, ParseException err) {
if (user == null) {
Log.d(tag, "Uh oh. The user cancelled the Facebook login.");
} else if (user.isNew()) {
Log.d(tag, "User signed up and logged in through Facebook!");
Request.newMeRequest(ParseFacebookUtils.getSession(), graphUserCallback).executeAsync();
} else {
Log.d(tag, "User logged in through Facebook!");
}
}
});
}
GraphUserCallback graphUserCallback = new GraphUserCallback() {
#Override
public void onCompleted(GraphUser user, Response response) {
if (user != null){
getUserDataFacebook(user);
Log.d(tag, response.toString());
}
}
};
private void getUserDataFacebook(GraphUser user){
//get user data here
}
Check out Parse's docs on Facebook login.
Let me know if this works for you.

android-fb-sdk email is always null

I have a big problem with android-facebook-sdk 3.19.1. No problem to retrieve public information about user but it is not possible getting email address.
I know my post is very near to the following thread ==> facebook android sdk -user email returns null but I have no solution for now.
So here is my code
In my ConnectionActivity.java I have a button R.id.fb_connect
private List<String> permissions = Arrays.asList("email");
#Click(R.id.fb_connect)
protected void fbConnect() {
ensureOpenSession();
}
private boolean ensureOpenSession() {
Session session = Session.getActiveSession();
if (session == null || !session.isOpened()) {
LOGD(TAG, "Call Session.openActiveSession");
Session.openActiveSession(this, true, permissions, new FbCallback());
return false;
}
return true;
}
public class FbCallback implements Session.StatusCallback {
#Override
public void call(Session session, SessionState sessionState, Exception e) {
// make request to the /me API
Request.newMeRequest(session, new Request.GraphUserCallback() {
// callback after Graph API response with user object
#Override
public void onCompleted(GraphUser user, Response response) {
if (user != null) {
// user.asMap().get("email");
Toast.makeText(ConnectionActivity.this, "email : " + user.getProperty("email"), Toast.LENGTH_LONG).show();
}
}
}).executeAsync();
}
}
I've also tried the code in the link above but it doesn't work. One precision, with this code, I can see the facebook activity which says "XXX will receive the following info: your public profile and email address" but the toast displays "email : null"
EDIT
I work with android studio and my gradle file has the following line
compile 'com.facebook.android:facebook-android-sdk:3.19.1'
EDIT2
If I use
LOGD(TAG, "isPermissionGranted : " + session.isPermissionGranted(permissions.get(0)));
before call Request.newMeRequest so true is shown. Permission is correctly granted
Thx

Get Facebook user email using latest Facebook SDK

I'm developing an Android application, and I'm using this code to get some data from Facebook:
public void onFBLoginClick(View view)
{
// start Facebook Login
Session.openActiveSession(this, true, new Session.StatusCallback()
{
// callback when session changes state
#Override
public void call(final Session session, SessionState state, Exception exception)
{
if (session.isOpened())
{
// make request to the /me API
Request.executeMeRequestAsync(session, new Request.GraphUserCallback()
{
// callback after Graph API response with user object
#Override
public void onCompleted(GraphUser user, Response response)
{
if (user != null)
{
txtUserName.setText(session.getAccessToken());
saveUserData(user.getId(), user.getName(), user.getBirthday(), user.asMap().get("email").toString());
saveAccessToken(session.getAccessToken());
getFacebookUserProfilePicture(session.getAccessToken());
}
}
});
}
}
});
}
But, I can't get the email. Always is null.
I set up email permissions on User & Friend Permissions, on developers.facebook.com, but it doesn't work.
What am I doing wrong?
Use this code to open your session and you are ready to go!
String[] PERMISSION_ARRAY_READ = {"email","user_birthday"};
List<String> PERMISSION_LIST=Arrays.asList(PERMISSION_ARRAY_READ);
session.openForRead(new Session.OpenRequest(getParent()).setPermissions(PERMISSION_LIST).setCallback(statusCallback));
let me know if uyou have any problem regarding this.

Android and Facebook SDK 3.0.1 function getUserID

I am implementing the new Facebook SDK 3.0.1 and I have some doubts about use with Session.
I created a function to query just the user id:
String userID;
public String getUserID(){
final Session session = Session.getActiveSession();
if (session != null && session.isOpened()) {
Request request = Request.newMeRequest(session, new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser user, Response response) {
if (session == Session.getActiveSession()) {
if (user != null) {
userID = user.getId();
System.out.println("User ID " + userID); //OK
}
}
}
});
Request.executeBatchAsync(request);
return userID;
}else{
return null;
}
}
The problem is when I do System.out.println("ID is... "+FB.getUserID()); because only shows: "ID is...".
But the internal println perfectly shows the id (User ID XXXXXXXXX). The problem is the time to receive the information. How I can I control it?
I think you cannot control it.
You are executing an async request that is a request that "permits other processing to continue before the transmission has finished." (see Wikipedia page).
You have to wait until the onCompleted method is called by the request object.
There is actually a way around this. Simply use Request.executeAndWait(). that function does exactly what it sounds like it does, it pauses the thread until the onComplete is finished.

How to programmatically log out from Facebook SDK 3.0 without using Facebook login/logout button?

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.

Categories

Resources