1

I have my Android app using the Parse server for backend service. A number of users are currently using my Android app. However, some particular users faced the problem at app installation that an object is not created in the Installation table even after log-in.

When I took a look at the problem from my Android app with some Analytics code, I found that ParseInstallation.getCurrentInstallation().getObjectId() returns null for the user even though Parse initialization process is completed properly. With the Analytics code, I checked the method every 10 seconds for 10 minutes after Parse initialization, but that method always returned null for the particular user.

// Parse initialization in the onCreate() of Application class
Parse.enableLocalDatastore(this);
Parse.initialize(new Parse.Configuration.Builder(this)
        .applicationId(getString(R.string.parse_app_id))
        .clientKey(getString(R.string.parse_client_key))
        .server(getString(R.string.parse_server_api))
        .build());
ParseUser.enableAutomaticUser();
ParseACL.setDefaultACL(new ParseACL(), true);

// After Log-In, Save the installation.
// (My app user normally would come here 20 ~ 30 seconds or long after the above Parse initialization.) 
ParseInstallation installation = ParseInstallation.getCurrentInstallation();
if (!TextUtils.isEmpty(installation.getObjectId()) { // installation.getObjectId() returns null for the particular user.
    installation.put("GCMSenderId", getString(R.string.fcm_sender_id));
    installation.saveInBackground(
        // will associate the Installation with the User in new SaveCallback()
    );
}

// build.gradle(Module: app)
implementation 'com.github.parse-community.Parse-SDK-Android:parse:1.18.5' 
implementation 'com.github.parse-community.Parse-SDK-Android:fcm:1.18.5'

Most users get valid ObjectId and work correctly without any problem. However, once a user encounters the problem, the object is no longer created in the Installation table for the user, even though the user installs the app again.

I do not know if this is a fundamental problem with the Parse server.

Any advice will be helpful to me.

Jay
  • 75
  • 1
  • 7
  • Can you share the complete code for `installation.saveInBackground(...);` ? – Davi Macêdo Jul 11 '19 at 19:34
  • @Davi Macêdo `installation.saveInBackground(...);` can not be done because `installation.getObjectId()` retuns null. – Jay Jul 12 '19 at 00:02
  • I didn't get it. If `installation.getObjectId()` is null, `TextUtils.isEmpty(installation.getObjectId())` is true, so the program goes into the if and will execute the `installation.saveInBackground(...);`. Isn't it? – Davi Macêdo Jul 12 '19 at 02:11
  • @Davi Macêdo I was mistaken in the code. I modified the example code above. – Jay Jul 12 '19 at 02:42

2 Answers2

1

I think that the objectId is null because the installation is not saved for some reason. I'd recommend you to go with the following code and check again:

// Parse initialization in the onCreate() of Application class
Parse.enableLocalDatastore(this);
Parse.initialize(new Parse.Configuration.Builder(this)
        .applicationId(getString(R.string.parse_app_id))
        .clientKey(getString(R.string.parse_client_key))
        .server(getString(R.string.parse_server_api))
        .build());
ParseUser.enableAutomaticUser();
ParseACL.setDefaultACL(new ParseACL(), true);

// After Log-In, Save the installation.
// (My app user normally would come here 20 ~ 30 seconds or long after the above Parse initialization.) 
ParseInstallation installation = ParseInstallation.getCurrentInstallation();
if (TextUtils.isEmpty(installation.getObjectId())) { // installation.getObjectId() returns null for the particular user.
    installation.save();
}
installation.put("GCMSenderId", getString(R.string.fcm_sender_id));
installation.saveInBackground(
    // will associate the Installation with the User in new SaveCallback()
);

// build.gradle(Module: app)
implementation 'com.github.parse-community.Parse-SDK-Android:parse:1.18.5' 
implementation 'com.github.parse-community.Parse-SDK-Android:fcm:1.18.5'
Davi Macêdo
  • 2,954
  • 1
  • 8
  • 11
  • It is not easy to reproduce the case that `installation.getObjectId()` returns null in my smartphones. Are you sure that objectId, deviceToken and tokenType will have a valid string value in the Installation table after `installation.save()` is called? – Jay Jul 12 '19 at 08:27
  • It should have. Do you have any other piece of code in your app in which you save the installation? – Davi Macêdo Jul 12 '19 at 17:05
  • @ Davi Macêdo No. I think that the saving method should be handled in just one piece of code because a reduplication may cause a conflict in saving the installation. – Jay Jul 13 '19 at 01:08
  • I think you are good with this code. Make some tests and check it out. – Davi Macêdo Jul 13 '19 at 02:19
  • I followed your recommendation, but I found a particular user who encountered the problem. Just after the `installation.save()`, `installation.getObjectId()` returns a valid string value. However, unfortunately, both `installation.get("deviceToken")` and `installation.get("pushType")` still returned null. With the Analytics code, I checked the deviceToken and pushType every 5 seconds for 6 minutes after the `installation.save()`, but both always returned null. – Jay Jul 13 '19 at 13:45
  • From my smartphone, I finally found the root cause of the problem that the deviceToken and the pushType returned null. If the phone user activates the Power Saving in the phone settings, the deviceToken and the pushType continually returns null. Regarding the problem that `getObjectId()` returns null, I am still taking a look at the result of my app users. – Jay Jul 13 '19 at 15:07
  • I left the result in the other answer below because the comment was longer. – Jay Jul 26 '19 at 14:47
1

Here are the results of using Davi Macêdo's hint:

After installation.save(), sometimes installation.get("deviceToken") returned null. So I used an iteration routine to wait for installation.get("deviceToken") to return a valid value. And then I called installation.saveInBackground(). Over the 10 days, I've been watching the results of my app users and it seems to be working well so far.

If you use the Parse Client on a battery-powered device such as an Android phone, you will face a similar problem like me. The most important point is that installation.get("deviceToken") returns null more often when the phone is in the power save mode. So before calling both installation.save() and installation.saveInBackground(), you need to make sure that the phone is not in the power save mode and is in good internet connection.

BTW, with the help of Davi, I solved the problem. Thanks to Davi.

If there are any additional problems, I will share with you.

Jay
  • 75
  • 1
  • 7