Like Hardy said, you have to create an instance of ProfileTracker
which will start tracking profile updates, (i.e ProfileTracker.onCurrentProfileChanged()
will be called when the user's profile finishes being fetched).
Following is the complete code that you'd need to login to FB and get the user's profile:
LoginButton loginButton = (LoginButton) findViewById(R.id.btn_facebook);
loginButton.setReadPermissions("public_profile");
mCallbackManager = CallbackManager.Factory.create();
loginButton.registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() {
private ProfileTracker mProfileTracker;
@Override
public void onSuccess(LoginResult loginResult) {
if(Profile.getCurrentProfile() == null) {
mProfileTracker = new ProfileTracker() {
@Override
protected void onCurrentProfileChanged(Profile oldProfile, Profile currentProfile) {
Log.v("facebook - profile", currentProfile.getFirstName());
mProfileTracker.stopTracking();
}
};
// no need to call startTracking() on mProfileTracker
// because it is called by its constructor, internally.
}
else {
Profile profile = Profile.getCurrentProfile();
Log.v("facebook - profile", profile.getFirstName());
}
}
@Override
public void onCancel() {
Log.v("facebook - onCancel", "cancelled");
}
@Override
public void onError(FacebookException e) {
Log.v("facebook - onError", e.getMessage());
}
});
You must override your Activity's or Fragment's onActivityResult()
as below:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// if you don't add following block,
// your registered `FacebookCallback` won't be called
if (mCallbackManager.onActivityResult(requestCode, resultCode, data)) {
return;
}
}
Code updated with Alex Zezekalo's suggestion to only call mProfileTracker.startTracking();
if Profile.getCurrentProfile()
returns null.
Following to Sufian's answer, you can also save the new profile to Profile class:
@Override
public void onSuccess(LoginResult loginResult) {
ProfileTracker profileTracker = new ProfileTracker() {
@Override
protected void onCurrentProfileChanged(Profile oldProfile, Profile currentProfile) {
this.stopTracking();
Profile.setCurrentProfile(currentProfile);
}
};
profileTracker.startTracking();
}
Facebook loads the profile information asynchronously, so even after you get your result from the login callback, Profile.getCurrentProfile() will return null.
However, every time the user logs in through Facebook (the first time and every subsequent time) his profile will change and will fire the profiletracker. This is where you must call the profile.
Here is how you should structure your code. You must listen for the ProfileTracker to update in order to update your user properties - avoid calling getCurrentProfile outside the tracker during the login process:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FacebookSdk.sdkInitialize(getApplicationContext());
callbackManager = CallbackManager.Factory.create();
profileTracker = new ProfileTracker() {
@Override
protected void onCurrentProfileChanged(Profile profile, Profile profile1) {
//Listen for changes to the profile or for a new profile: update your
//user data, and launch the main activity afterwards. If my user has just logged in,
//I make sure to update his information before launching the main Activity.
Log.i("FB Profile Changed", profile1.getId());
updateUserAndLaunch(LoginActivity.this);
}
};
profileTracker.startTracking();
accessTokenTracker = new AccessTokenTracker() {
@Override
protected void onCurrentAccessTokenChanged(
AccessToken oldAccessToken,
AccessToken currentAccessToken) {
//Check that the new token is valid. This tracker is fired
//when the user logs in the first time and afterwards any time he interacts with
//the Facebook API and there is a change in his permissions.
if (!accessTokenIsValid(currentAccessToken)){
Log.i("FB Token Updated", String.valueOf(currentAccessToken.getPermissions()));
requestLogin();
}
}
};
// User already has a valid access token? Then take the user to the main activity
if (accessTokenIsValid(AccessToken.getCurrentAccessToken())){
launchApp();
}else{
//Show the Facebook login page
requestLogin();
}
}
The key here is that you should not call Profile.getcurrentprofile from the login callback (either LoginManager,registercallback or loginButton.registercallback) - the values are not reliable. Set up the tracker and rely on it firing at the opportune time in order to get updated profile info.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With