strongloop-community/loopback-sdk-android

How to check if an installation exists

crandmck opened this issue · 5 comments

From https://groups.google.com/forum/#!topic/loopbackjs/Rz4kyjp_rq0/discussion.

Looking at the LocalInstallation class in the loopback-android repo, there is a save method but not really any others that interface with the loopback API AFAIK. I'm interested in a check exists method (/api/installations/{id}/exists). In particular, I'd like to have it so I can keep track of users who download an android app but haven't yet created an account.. That is, save installations before they can be associated with a userId (setting userId to -1 or something like that). To know whether or not to update the installation on the front screen (pre-login), setting the userId to -1, I need to know whether or not the installation exists already to avoid overwriting a user id that could still be associated with a user that is logged out or "Inactive".

  • Is writing a method in that class what you'd recommend?
  • If so, would the code look something like this?
    public void checkExists(final ObjectCallback callback) {
        ModelRepository<Model> repository =
                loopbackAdapter.createRepository("installation");
        final Model model = repository.createModel(
                BeanUtil.getProperties(this, false, false));      // I'm assuming this takes care of SharedPreferences id stuff..

        model.checkExists(new ObjectCallback() {      // checkExists would have to be written in Model.java
            @Override
            public void onSuccess() {
                result = model.exists();            // exists method would have to be written too.. 
                callback.onSuccess(boolean result);
            }

            @Override
            public void onError(Throwable t) {
                if (t instanceof HttpResponseException) {
                     // something graceful here.. 
                }
                callback.onError(t);
            }
        });
    }

If this is the way to go about it, happy to give it a shot. Wanted to check first before I dive in tho. Also wouldn't be very hard to write some Android code that just checks the server with a background task, however figured I'd try to use the loopback android library as much as possible to minimize code..

From Miroslav
The current implementation of LocalInstallation class should already support your use case, at least in my opinion:

  • at startup, create a new LocalInstallation instance, fill all properties except userId and call save()
  • after login, create a new LocalInstallation instance, fill all properties including userId and call save()
  • after logout, create a new LocalInstallation instance, fill all properties, set userId to null, and call save()

LocalInstance is storing the installationId in SharedPreferences, thus the save() method is always updating the same server instance of Installation model.

To know whether or not to update the installation on the front screen (pre-login), setting the userId to -1, I need to know whether or not the installation exists already to avoid overwriting a user id that could still be associated with a user that is logged out or "Inactive".

Every Installation instance is assigned a unique id bound the the copy of the application on a single device. No two devices share the same installation ids.

I don't understand why the "exists" check is needed to prevent overriding user ids. Could you please explain this in more detail? It's possible I am missing something here.

Perhaps what is needed is a better integration of LocalInstallation with authorization, so that LocalInstallation automatically fills the id of the user which is currently authenticated with the app? This should be IMO done on the server - when a local installation is create or updated, the userId should be overriden with the value from the access token.

Great call. By using null for userId at startup (not setting it at all, instead of setting to -1), eliminates need for exists call. Better solution, thanks.

Just to recap for anyone in future. Made two minor tweaks, but these steps are a solid way to do it as you suggested:

  • at startup, create a new LocalInstallation instance, fill all properties except userId and call save()
  • after login, create a new LocalInstallation instance, fill all properties including userId and call save()
  • after logout, create a new LocalInstallation instance, fill all properties, set userId to null, and call save() NOTE: I don't set userId back to null here.. Just set installation to inactive. Figure it will be nice to know the last user who was logged in on a device. Likely will not use ever, but just in case I wanted to figure out demographics for people who logged out might be useful. Can still associate logged out devices with the last user logged in this way.

By doing it this way it covers every case I can think of:

  • first startup -> installation created with userid null, device token and object id created, status inactive
  • login -> installation updated by setting userid and status to active (I actually make this call from our main non-loopback server that does login, figure more reliable network connection)
  • logout -> installation updated to inactive (userId not changed, not overwriting last user logged in on a specific device to null)

There was one edge case where I had to add extra call: already logged in on new device (broken/lost phone recovery sort of thing, where old shared preferences make it to new device) -> update device token

Need to prioritize.

IMO, we should improve by doc by including this info:

  • at startup, create a new LocalInstallation instance, fill all properties except userId and call save()
  • after login, create a new LocalInstallation instance, fill all properties including userId and call save()
  • after logout, create a new LocalInstallation instance, fill all properties, set userId to null, and call save() NOTE: I don't set userId back to null here.. Just set installation to inactive. Figure it will be nice to know the last user who was logged in on a device. Likely will not use ever, but just in case I wanted to figure out demographics for people who logged out might be useful. Can still associate logged out devices with the last user logged in this way.

By doing it this way it covers every case I can think of:

  • first startup -> installation created with userid null, device token and object id created, status inactive
  • login -> installation updated by setting userid and status to active (I actually make this call from our main non-loopback server that does login, figure more reliable network connection)
  • logout -> installation updated to inactive (userId not changed, not overwriting last user logged in on a specific device to null)

There was one edge case where I had to add extra call: already logged in on new device (broken/lost phone recovery sort of thing, where old shared preferences make it to new device) -> update device token

I moved the new content to a separate article Working with the LocalInstallation class.
Other than that, LGTM.