dvir
dvir

Reputation: 5115

Android ParseFacebookUtils flow with login and logout

I've implemented a Parse & Facebook flow in my Android app using ParseFacebookUtils.

TL;DR

  1. Created a Parse user after logging in (and linking) with Facebook (ParseFacebookUtils.logIn)
  2. Logged out (ParseFacebookUtils.logOut & ParseUser.logOut)
  3. Logging in again with Facebook creates a new Parse user instead of fetching the old one.

Longer version: The login flow works - the ParseFacebookUtils.logIn call launches the Facebook dialog and after accepting a new Parse user is being created and linked to the user's Facebook account.

The problems arises after logging out (ParseFacebookUtils.logOut and ParseUser.logOut), and trying to log back in to the same Parse user. The Facebook dialog shows up briefly then I'm getting redirected to the app (as it's already authorized for that Facebook user), but it seems like a new Parse user is being created instead of finding the previous one for the relevant Facebook user.

Question: Is there a way to enable such flow? Would I have to get the already created user manually?

The code for my MainActivity, in which all the login logic reside:

public class MainActivity extends Activity {

  private ProgressBar progressBar;
  private Button loginButton;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    progressBar = (ProgressBar) findViewById(R.id.splash_loading_spinner);
    loginButton = (Button) findViewById(R.id.splash_facebook_login);
    loginButton.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View view) {
        onLoginButtonClicked();
      }
    });

    ParseAnalytics.trackAppOpened(getIntent());

    // Check if there is a currently logged in user
    // and they are linked to a Facebook account.
    ParseUser currentUser = ParseUser.getCurrentUser();
    if ((currentUser != null) && ParseFacebookUtils.isLinked(currentUser)) {
      // load data from Parse user and launch the next activity immediately
      retrieveData();
    } else {
      failedLoggingIn();
    }
  }

  @Override
  public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    ParseFacebookUtils.getSession().onActivityResult(this, requestCode, resultCode, data);
  }

  // this method will link the current ParseUser to the used Facebook account if needed
  private boolean linkFacebookUser() {
    ParseUser user = ParseUser.getCurrentUser();

    // save fb_id and email to the parse user
    Request.newMeRequest(ParseFacebookUtils.getSession(), new Request.GraphUserCallback() {
      @Override
      public void onCompleted(GraphUser fbUser, Response response) {
        if (fbUser == null) {
          Log.e("Facebook Me Request", "Failed fetching user Facebook Graph object.");
        } else {
          Log.d("Facebook Me Request", "Received Facebook graph object for "+fbUser.getId()+"("+fbUser.getProperty("email").toString()+")");

          ParseUser.getCurrentUser().put("fb_id", fbUser.getId());
          ParseUser.getCurrentUser().setEmail(fbUser.getProperty("email").toString());
          ParseUser.getCurrentUser().setUsername(fbUser.getProperty("email").toString());
          ParseUser.getCurrentUser().setPassword(UUID.randomUUID().toString());
          ParseUser.getCurrentUser().signUpInBackground(new SignUpCallback() {
            @Override
            public void done(ParseException e) {
              if (e == null) {
                Log.d("Parse signup user", "Successfully saved a new Parse-Facebook user!");
                retrieveData();
              } else {
                Log.e("Parse signup user", "FAILED saving a new Parse-Facebook user. Error: " + e.getMessage());
                e.printStackTrace();
              }
            }
          });
        }
      }
    }).executeAsync();

    return true;
  }

  private void retrieveData() {
    // fetch data needed to show movie recommendations
    Log.d("Parse Facebook Login Info", "fb_id=" + ParseUser.getCurrentUser().get("fb_id"));

    startActivity(new Intent(this, BrowseMoviesActivity.class));
    finish();
  }

  private void failedLoggingIn() {
    ParseUser.logOut();
    progressBar.setVisibility(View.GONE);
    loginButton.setVisibility(View.VISIBLE);
  }

  private void onLoginButtonClicked() {
    Log.d("UI", "Clicked the Facebook login button");
    progressBar.setVisibility(View.VISIBLE);
    loginButton.setVisibility(View.GONE);

    List<String> permissions = Arrays.asList(
      "public_profile",
      "user_friends",
      "user_actions.video",
      ParseFacebookUtils.Permissions.User.EMAIL,
      ParseFacebookUtils.Permissions.User.ABOUT_ME,
      ParseFacebookUtils.Permissions.User.RELATIONSHIPS,
      ParseFacebookUtils.Permissions.User.BIRTHDAY,
      ParseFacebookUtils.Permissions.User.LOCATION
    );

    ParseFacebookUtils.logIn(permissions, this, new LogInCallback() {
      @Override
      public void done(ParseUser user, ParseException err) {
        MainActivity.this.progressBar.setVisibility(View.GONE);
        if (user == null) {
          Log.d("ParseFacebookLogin", "Uh oh. The user cancelled the Facebook login.");
          if (err != null) {
            Log.d("ParseFacebookLogin",  "Error: " + err.getLocalizedMessage());
          }

          failedLoggingIn();
        } else if (user.isNew()) {
          Log.d("ParseFacebookLogin", "User signed up and logged in through Facebook!");
          // we should probably use this scenario to set fb id to the Parse user
          linkFacebookUser();
        } else {
          Log.d("ParseFacebookLogin", "User logged in through Facebook!");
          if (user.get("fb_id") == null) {
            linkFacebookUser();
          } else {
            retrieveData();
          }
        }
      }
    });
  }
}

Upvotes: 2

Views: 2091

Answers (1)

marios-codes
marios-codes

Reputation: 159

I had the same problem. Actually it was a bug in parse sdk and the problem was solved without changing any of my code, just by installing the latest parse android sdk(1.8.1 at the time of writing).

Upvotes: 2

Related Questions