How to get current Facebook access token on app start?

14,738

Solution 1

It must be so (this Facebook v4.1.2)

FacebookSdk.sdkInitialize(getApplicationContext());

mFacebookCallbackManager = CallbackManager.Factory.create();

mFacebookAccessTokenTracker = new AccessTokenTracker() {
    @Override
    protected void onCurrentAccessTokenChanged(AccessToken oldAccessToken, AccessToken currentAccessToken) {
        ...
    }
};

mFacebookLoginButton = new LoginButton(this);
mFacebookLoginButton.setReadPermissions(Arrays.asList("public_profile", "email", "user_birthday"));
mFacebookLoginButton.registerCallback(mFacebookCallbackManager, new FacebookCallback<LoginResult>() {
    @Override
    public void onSuccess(LoginResult loginResult) {
        ...
        String token = loginResult.getAccessToken().getToken()
        ...
    }

    @Override
    public void onCancel() {
        Lo.d("Facebook login - the user did not give permission");
    }

    @Override
    public void onError(FacebookException e) {
        e.printStackTrace();
    }
});

Solution 2

@Gokhan Caglar is right, the access token is null if the Facebook Sdk is not done initializing. So what about this?

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    FacebookSdk.sdkInitialize(this /* applicationContext */);
    setContentView(R.layout.activity_getting_started);

    callbackManager = CallbackManager.Factory.create();

    if (AccessToken.getCurrentAccessToken() == null) {
        waitForFacebookSdk();
    } else {
        init();
    }
}

private void waitForFacebookSdk() {
    AsyncTask asyncTask = new AsyncTask() {
        @Override
        protected Object doInBackground(Object[] params) {
            int tries = 0;
            while (tries < 3) {
                if (AccessToken.getCurrentAccessToken() == null) {
                    tries++;
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } else {
                    return null;
                }
            }
            return null;
        }

        @Override
        protected void onPostExecute(Object result) {
            init();
        }
    };
    asyncTask.execute();
}

private void init() {
    AccessToken accessToken = AccessToken.getCurrentAccessToken();
    if (accessToken == null || accessToken.isExpired()) {
        // do work
    } else {
        // do some other work
    }
}

Not the best solution in my eyes but waiting a bit for the Facebook Sdk might help.

Share:
14,738
Ralph Bergmann
Author by

Ralph Bergmann

Updated on June 05, 2022

Comments

  • Ralph Bergmann
    Ralph Bergmann almost 2 years

    On app start I need to know if the user is logged in or not to show a login page or not.

    My first try was to call AccessToken.getCurrentAccessToken(), but this doesn't work, see https://stackoverflow.com/a/29854249/1016472

    My 2nd try was to use the AccessTokenTracker but this doesn't work too. To use the AccessTokenTracker I have to initialize the Facebook SDK first. But during this initialization the access token is send to the tracker. The tracker isn't created at this time and can't receive the token.

    My 3rd try was to create my own AccessTokenTracker which looks like the original one. I created and registered it before I initialize the SDK. And now my tracker get's the token during this SDK initialization process.

    With this knowledge I open a bug report at Facebook with the questions:

    • Why the AccessTokenTracker depends on the initialized SDK. I think this is a mistake.
    • What is the right way to see if a user is logged in or not on app start.

    The answer from Facebook:

    This doesn't look like bug. The AccessTokenTracker ::onCurrentAccessTokenChanged should let you know when the class has received a token.

    I know that this is not working. And now I know there is no bug.

    But how to solve my problem?

    This doesn't work:

    FacebookSdk.sdkInitialize(getApplicationContext());
    mAccessTokenTracker = new AccessTokenTracker() {
    
        @Override
        protected void onCurrentAccessTokenChanged(AccessToken oldAccessToken, AccessToken currentAccessToken) {
    
            Timber.i("AccessTokenTracker oldAccessToken: " + oldAccessToken + " - currentAccessToken: " + currentAccessToken);
        }
    };