I can log in fine the first time. And I have an option where the user can disable facebook within the android application. When this is selected the facebook status goes to CLOSED. When I use the option again, to log back in the API hangs at OPENING within the callback function.
Per the examples I've found the first call uses
session.openForRead(new Session.OpenRequest(activity).setCallback(statusCallback));
and the second uses
Session.openActiveSession(activity, true, statusCallback);
The callback function looks like this:
private static class SessionStatusCallback implements Session.StatusCallback {
// callback when session changes state
#Override
public void call(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) {
GlobalVars.setUser(user.getName());
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(GlobalVars.getContext());
Editor editor = prefs.edit();
editor.putBoolean("facebook", true);
editor.commit();
System.out.println("facebook logged in");
}
}
});
}
System.out.println("facebook session state callback " + session.getState().toString());
}
}
I'm not sure if we have the exact problem, but my facebook's session state retains "OPENING" after the Session.openActiveSession(activity, true, statusCallback);. I had overridden the onActivityResult() inside my fragment. What I did to solve this was to override the method on my Activity instead.
Related answer: https://stackoverflow.com/a/13888652/782870
Related
Prompt how to correctly use the method openActiveSessionWithAccessToken() in Fasebook API. Authorization pass, get token, and launch a dialogue posting, it appears (I can post). After cleaning token, and a closed session, the method of closeAndClearTokenInformation() I'm trying to open a session already having previously received the token, and the session is opened, there is a dialogue, but alas, writes that an error occurred try again later.
In the dialog box displays:
An error occurred. Please try again later.
and gives an error in the log:
Error Code 110,
Error Description: Invalid user id,
Error Message: Missing user cookie (to validate session user).
Here's the code:
public static void migrateFbTokenToSession() {
AccessToken accessToken = AccessToken.createFromExistingAccessToken(getAccessToken(), new Date(getAccessExpires()), null, AccessTokenSource.FACEBOOK_APPLICATION_NATIVE, Arrays.asList(Constants.FB_APP_PERMISSIONS));
Session.openActiveSessionWithAccessToken(getContext(), accessToken , new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) {
if(session != null && session.isOpened()) {
Session.setActiveSession(session);
}
}
});
}
You are removed preous session so how will you get access. You need to login again. If you want to maintain session then just use UiLifecycleHelper .
I did it with using createFromString method like this:
AccessToken accessToken = AccessToken.createFromString(savedTokenAsString, facebookPermissions, AccessTokenSource.NONE);
Session.openActiveSessionWithAccessToken(context, accessToken, new Session.StatusCallback() {
#Override
public void call(Session session, SessionState state, Exception exception) { }
});
But you need to make createFromString method public, because its package-private in facebook sdk.
hey i got problem with facebook login dialog and permission request dialog, overlay of both show with no alpha channel and covers activity
its looks like this under white space around dialog should be visible activity content
i dont know how to delete that overlay and/or change it to overlay with alpha channel
this is there i login to FB
public void facebookLogin() {
Session.openActiveSession(this, true, new Session.StatusCallback() {
// callback when session changes state
#Override
public void call(Session session, SessionState state, Exception exception) {
if (session.isOpened()) {
// If the session is open, make an API call to get user data
// and define a new callback to handle the response
//final GraphUser graphUser;
Utils.PrintDebug("session is Opened");
final String accessToken = session.getAccessToken();
Request request = Request.newMeRequest(session, new Request.GraphUserCallback() {
#Override
public void onCompleted(GraphUser user, Response response) {
// If the response is successful
if (user != null) {
Utils.PrintDebug("logged as "+user.getName());
FacebookConnectSpiceRequest request = new FacebookConnectSpiceRequest(accessToken, user.getId(), (int) DataManager.CurrentData.UserID);
getSpiceManager().execute(request, new FacebookConnectListener());
}
}
});
Request.executeBatchAsync(request);
}
};
});
}
How do you have the LoginActivity declared in your manifest? Try something like:
<activity android:name="com.facebook.LoginActivity"
android:theme="#android:style/Theme.Translucent.NoTitleBar" />
I had the same issue...
in com.facebook.widgets.WebDialog class, there is a variable:
BACKGROUND_GRAY = 0xCC000000;
just edit to:
BACKGROUND_GRAY = 0x00000000;
and it's fixed.
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.
Is it possible to create a class to encapsulate the Android SDK on android?
i.e - I don't want to clutter my activity with all the FB sessions and stuff, I want to have a class that I can call and it will do the job.
For example,
FacebookSDK sdk = new FacebookSDK();
sdk.publish();
For now I couldn't find a way to do this, without using Fragments or cluttering my activity with the facebook code.
Many Thank!
Its all about session management.
//Check for active session -
Session session = Session.getActiveSession();
// if it doesnt exist create one-
if(session ==null)
session= new Session(getApplicationContext)
// if it is not open open it first
if (!session.isOpened() && !session.isClosed()) {
session.openForRead(new Session.OpenRequest(this)
.setPermissions(Arrays.asList("basic_info"))
.setCallback(statusCallback));
}
else
{
Session.openActiveSession(getActivity(), this, true, statusCallback);
}
// callback listner fires when session state changes
private class SessionStatusCallback implements Session.StatusCallback {
#Override
public void call(Session session, SessionState state, Exception exception) {
//If your session is opened
if(session.isOpened()
publishData(session);
}
Method to publish your request -
public void publishData(Session session)
{
OpenRequest open = new OpenRequest(this);
open.setLoginBehavior(SessionLoginBehavior.SUPPRESS_SSO);
open.setPermissions(Arrays.asList(new String[]{"email", "publish_actions", "user_birthday", "user_hometown"}));
open.setCallback(this);
session.openForPublish(open);
}
publishData defination can also be -
public void publishData(Session session)
{
Bundle params = new Bundle();
params.putByteArray("message", "some message".egtBytes());
params.putByteArray("name", "some name".getBytes());
params.putByteArray("link", "some link".getBytes());
params.putByteArray("description", "Some description".getBytes());
params.putByteArray("picture", "picture.url".getBytes());
Request postToWall = Request.newRestRequest(session,
"/" + pickedUsersId.get(0) + "/feed", params, HttpMethod.POST);
postToWall.setCallback( new Request.Callback()
{
#Override
public void onCompleted(Response response)
{
// get response
Log.e(TAG, response.toString());
}
});
Request.executeBatchAsync(postToWall);
}
In short, no.
Your activity needs to be notifying the Facebook SDK of lifecycle events in order to properly store state and handle the UI flow to and from the Facebook SDK activities.
UILifecycleHelper is an effort to encapsulate this as much as possible.
You may be able to unclutter your code by having all your activities extend some base class (i.e. FBActivity) that makes all the proper calls to UILifecycleHelper, though this only helps if all your activities are interacting with Facebook in a fairly uniform manner.
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.