Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ParseUser user.saveEventually() always create new user in database #850

Open
andj207 opened this issue Jul 9, 2018 · 8 comments
Open

ParseUser user.saveEventually() always create new user in database #850

andj207 opened this issue Jul 9, 2018 · 8 comments

Comments

@andj207
Copy link

andj207 commented Jul 9, 2018

ParseUser was newly created every time I use user.saveEventually(). I checked in the ParseDashboard, the Installation object for my device is unique but the "user" field in Installation table always different every time I completely close the app (back pressed, wipe out recently apps) and reopen it. The User table has new row too.

My code:

ParseUser.enableAutomaticUser();
        ParseUser user = ParseUser.getCurrentUser();
        if (user != null) {
            ParseACL.setDefaultACL(new ParseACL(ParseUser.getCurrentUser()), true);
            if (user.get("appLaunch") == null) {
                user.put("appLaunch", 0);
                user.put("notifyAll", true);
            }
            user.saveEventually();  // <-- this line will create new user everytime it run
        }

ParseInstallation installation = ParseInstallation.getCurrentInstallation();
        if (installation != null) {
            String refreshedToken = FirebaseInstanceId.getInstance().getToken();
            if (refreshedToken != null) {
                installation.setDeviceToken(refreshedToken);
            }
            installation.put("user", ParseUser.getCurrentUser());
            installation.saveEventually();
        }

I use latest ParseServer and:
implementation "com.parse:parse-android:1.17.3"

@Jawnnypoo
Copy link
Member

I would remove the ParseUser.enableAutomaticUser();, as you are essentially doing what it does in the next lines. That might be the issue, but maybe not. Try that out first.

@andj207
Copy link
Author

andj207 commented Jul 9, 2018

@Jawnnypoo If ParseUser.enableAutomaticUser(); was removed, ParseUser.getCurrentUser(); always returns null. I need to create anonymous user for use in the app.

@andj207
Copy link
Author

andj207 commented Jul 9, 2018

Btw, If I use user.saveInBackground(); everything works as expected. There must be a bug with user.saveEventually();.

@AlejandroHCruz
Copy link

Also struggling with this, did you encounter any further issues when creating anonymous users with user.saveInBakcground() for example if you call that when there's no internet connection?

@andj207
Copy link
Author

andj207 commented Sep 17, 2018

@AlejandroHCruz yes, I still struggle with this issue, the User collection grows very fast compare to Installation collection. For now I switch to use Installation pointer for "relation" instead.

@AlejandroHCruz
Copy link

Gotcha, thanks!
user.cryInBackground()

@nisrulz
Copy link

nisrulz commented Sep 18, 2018

So, the issue is that the ParseAnonymousUser is actually not getting saved properly, which results in no user being available when the app starts again. So the usual path of creating a new anon user is followed. The solution that worked for me was like below:

In my Application file

@Override 
public void onCreate() {
     ...
     // Enable automatic creation of ParseAnonymousUser 
     ParseUser.enableAutomaticUser();
    
     // Login the anonymous user so as to create an entry in the Parse's User table
     loginAnonUserIfNeeded() 
}

where loginAnonUserIfNeeded() is another method, which takes care of logging in the ParseAnonymousUser.

void loginAnonUserIfNeeded() {
        // If the current user does not have the object id then it is
        // an anon user, then go ahead and login the user into parse
        if (ParseUser.getCurrentUser() != null
                && ParseUser.getCurrentUser().getObjectId() == null) {
            // call to login only creates the anon user but does not persist it
            ParseAnonymousUtils.logIn((user, e) -> {
                if (e == null) {
                    // The user returned here is ParseUser object which is now stored in remote Parse
                    // server. If the login was not successful this will be null. So we check for the
                    // user object that si returned is not null and login was successful.
                    if (user != null) {
                        // After login, save is required so that it persists across app starts
                        // ⚠️ WARNING: Do not use saveEventually as it is buggy and creates new anon user
                        // every time app is opened
                        user.saveInBackground(e1 -> {
                            if (e1 == null) {
                                //User was saved successfully
                            } else {
                                // Print stacktrace of the error
                                e1.printStackTrace();
                            }

                        });
                    }
                } else {
                    // Print stacktrace of the error
                    e.printStackTrace();
                }
            });
        }
    }

How to test this: Setup OkHttpInterceptor for logging outgoing calls to Parse Server and you can validate that the create user call is made only once.

I hope this helps others who bump into this problem in the future 😄

@AlejandroHCruz
Copy link

AlejandroHCruz commented Sep 18, 2018

Great solution! Please take into account that ParseAnonymousUtils.logIn((user, e) -> will return a null ParseUser object if there's no internect connection.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants