Android : App Visit Count using Firebase Database

Pratik Butani :

I wanted to count app visits whenever any user open the app. I have done following code which is working successfully only when INTERNET IS ON

I have used FirebaseDatabase.getInstance().setPersistenceEnabled(true); for storing data offline and also used myRef.keepSynced(true); to keep syncing.

Here is the code:

    // COUNTER PART
    FirebaseDatabase database = FirebaseDatabase.getInstance();
    DatabaseReference myRef = database.getReference("counter");
    myRef.keepSynced(true);
    myRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            Log.i("FB", "Snapshot: " + dataSnapshot);
            long val = (long) dataSnapshot.getValue() + 1;
            myRef.setValue(val);
            mainBinding.contentLayout.textViewCounterVisits.setVisibility(View.VISIBLE);
            mainBinding.contentLayout.textViewCounterVisits.setText(getString(R.string.total_visits, val));
        }

        @Override
        public void onCancelled(@NonNull DatabaseError error) {
            Log.e("FB", "Error: " + error);
        }
    });

PROBLEM:

When I open the app offline for multiple times its counting offline. When I turned on the Internet, It's just syncing with updated data but I wanted to update count by adding new counts.

For example:

  • Count is 105

  • App 1 - Opening for 10 times (offline)

  • App 2 - Opening for 15 times (online)

  • Now count is 120

  • App 1 goes online and opening app and count is updating 121.

I think it should be 131 if we count all.

Alex Mamo :

I think it should be 131 if we count all.

If the mechanism is genuine as you describd, no, it shouldn't be not even 121, it should be 116 and that's the normal behaviour, since you are using the same counter for both apps. Here is the mechanism:

  • Count is 105
  • App 1 - Opening for 10 times (offline) -> Count is still 105
  • App 2 - Opening for 15 times (online) -> Count is 120 (105 + 15)

While App 1 is offline, it only has knowledge of the initial count of 105 and of those 10 increase operations that were queued. By the time the App 1 comes online, it takes 115 and it overrides the existing 120 value that is in the database at that time. So now, the counter in the database has the value of 115. When App 1 is opened again, the counter will be increased to 116.

This "strage" behaviour takes place because App 1 while offline, doesn't know what App 2 is doing while online and vice versa. Generally speaking, when it comes to incrementing counters in a multi user environment, that's not the way you should go ahead with. In such cases, to have consistent data, you should use transactions, as explained in my answer from the following post:

But be aware that Firebase transactions are not supported for offline use. The transactions can't be cached or saved for later use. This is because a transaction absolutely requires round trip communications with server in order to ensure that the code inside the transaction completes successfully.

So in my opinion, you should increment that count field only when the user is online and using a transaction operation.

P.S. If you consider at some point in time to try using Cloud Firestore, there you can find a very useful increment operation method named FieldValue.increment().

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=323299&siteId=1