web-dev-qa-db-fra.com

Profile.getCurrentProfile () renvoie null après la connexion (API FB v4.0)

Pour une raison quelconque, Profile.getCurrentProfile() apparaît parfois nulle juste après la connexion à FaceBook, à l'aide de l'API FB v4.0.

Cela me cause des problèmes dans mon application car je ne peux pas afficher mon Activity suivant avec Profile étant nul.

La raison pour laquelle je dis qu'elle est parfois nulle est parce que si je ferme mon application et la rouvre, je peux accéder à ma prochaine Activity, mais si je ne suis pas déjà connecté, puis login, Profile est null. Il semble que ce soit pour une courte période.

Y a-t-il un moyen de contourner ce problème ou d'y remédier?

44
user1944429

Comme Hardy a dit , vous devez créer une instance de ProfileTracker qui commencera le suivi des mises à jour de profil, (ie ProfileTracker.onCurrentProfileChanged() sera appelé lorsque le profil de l'utilisateur finira d'être récupéré ).

Voici le code complet dont vous auriez besoin pour vous connecter à FB et obtenir le profil de l'utilisateur:

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());
    }
});

Vous devez remplacer la onActivityResult() de votre activité ou fragment comme ci-dessous:

@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;
    }
}

Modifier:

Code mis à jour avec suggestion d'Alex Zezekalo pour appeler uniquement mProfileTracker.startTracking(); si Profile.getCurrentProfile() renvoie null.

83
Sufian

Suite à la réponse de Sufian, vous pouvez également enregistrer le nouveau profil dans la classe Profile:

@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();
}
18

Facebook charge les informations de profil de manière asynchrone, donc même après avoir obtenu votre résultat du rappel de connexion, Profile.getCurrentProfile () renverra null.

Cependant, chaque fois que l'utilisateur se connecte via Facebook (la première fois et chaque fois par la suite), son profil change et déclenche le profiletracker. C'est là que vous devez appeler le profil.

Voici comment structurer votre code. Vous devez écouter la mise à jour de ProfileTracker afin de mettre à jour vos propriétés utilisateur - évitez d'appeler getCurrentProfile en dehors du tracker pendant le processus de connexion:

@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();
        }

    }

La clé ici est que vous ne devez pas appeler Profile.getcurrentprofile à partir du rappel de connexion (LoginManager, registercallback ou loginButton.registercallback) - les valeurs ne sont pas fiables. Configurez le tracker et comptez sur lui pour déclencher au moment opportun afin d'obtenir des informations de profil mises à jour.

4
Laurent

J'ai une suggestion plus simple que les autres réponses ici.

Il n'y a pas besoin d'enregistrer un rappel de connexion avec:

registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() { ... }

Au lieu de cela, chaque fois que vous avez besoin de données utilisateur (comme lors d'un clic sur un bouton) - commencez à suivre les modifications de profil avec:

new ProfileTracker() {
    @Override
    protected void onCurrentProfileChanged(Profile oldProfile, Profile profile) {
        stopTracking();

        Log.d(TAG, profile.getFirstName());
        Log.d(TAG, profile.getLastName());
        Log.d(TAG, String.format("https://graph.facebook.com/%s/picture?type=large", profile.getId()));
    }
}.startTracking();

Et puis démarrez le processus de connexion Facebook en:

LoginManager.getInstance().logInWithReadPermissions(getContext(), Arrays.asList("public_profile"));

Pour que le code ci-dessus fonctionne, vous devez bien sûr préparer les éléments habituels de votre activité:

private CallbackManager mCallbackManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    mCallbackManager = CallbackManager.Factory.create();
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (FacebookSdk.isFacebookRequestCode(requestCode) &&
            mCallbackManager.onActivityResult(requestCode, resultCode, data)) {
        // do nothing
    } else {
        super.onActivityResult(requestCode, resultCode, data);
    }
}

N'oubliez pas non plus de modifier le fichier AndroidManifest.xml .

0
Alexander Farber