I am working on firebase for the first time, read about offline capabilities of firebase , tested two scenarios :
scenario 1 (working):
offline mode, writing data to firebase database.
press back button(closed app)
went online, data got added to the firebase database.
scenario 2 ( not working):
offline mode, writing data to firebase database
close app
remove app from background(killed the application)
went online, data not getting added
I added this line:
Firebase.getDefaultConfig().setPersistenceEnabled(true);
how to handle scenario 2 ? Do I need to handle this scenario through local database?
Are you using Firebase.getDefaultConfig().setPersistenceEnabled(true); and keepSynced(true)?
Because in Firebase documentation says that keepSynced(true) it's who make the "magic" happens (together with setPersistenceEnabled(true)):
By calling keepSynced(true) on a location, the data for that location will automatically be downloaded and kept in sync, even when no listeners are attached for that location. Additionally, while a location is kept synced, it will not be evicted from the persistent disk cache.
So, if you're not using it, you're not persisting your database locally and then when you "kill" the application, there will not be any database to query from when your app is opened again.
I guess your using some service to sync the data, It will not work for 2nd scenario. For that when user turn on data services you will receive a broadcast receiver, from that check service is not running then start the service.
No need to handle scenario 2 using local database . Use Firebase.getDefaultConfig().setPersistenceEnabled(true) in application class and make android:name="yourapplicationclass" in manifest file.
to handle sync while change network ie online/offline use transaction handler to handle local sync to firebase database since some tome data is not pushed to firebase server.Like this I used inside network change method and solved this issue:
mDatabase.runTransaction(new Transaction.Handler() {
#Override
public Transaction.Result doTransaction(MutableData mutableData) {
if(mutableData.getValue() == null) {
mutableData.setValue(1);
} else {
mutableData.setValue((Long) mutableData.getValue() + 1);
}
return Transaction.success(mutableData); //we can also abort by calling Transaction.abort()
}
#Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {
}
});
Related
Firebase realtime database doesn't load the query result nor call onCancelled method.
For the past month I've been facing a problem with database queries that seems to take forever to load.
In the production version of my app, thanks to crashylicts and firabase events i was able to detect that some sessions are not able to complete the query neither return any exception or error... the request simple "vanishes"
Since feb/march I started getting lots of complaints in google play that users were facing a "extremly long login time" and since i didnt change anything in the apps logic related to that i started monitore and look for errors
The average login time to the app is 6 seconds with 90% of the sessions being bellow 10 seconds... (ignoring the time user takes to fill the login form)
But some users would wait over 1 minute and the login wouldn't finish... these users would often get bored and close the app or try to clean data or reinstall
From what i debugged the dead end was the firebase query to the user profile.... very simple query using a previous known userid and obtaining a few persistent data from user [8 fields between strings and long... no nested data]
something like
FirebaseDatabase.getInstance().getReference("any/node").addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
//not called
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
//neither
}
});
Does anyone know what might be the problem?
I am currently making a call to my server to make a change in the Datastore and listening for another change to it. I do not receive any new changes from the DB despite the database being changed correctly on the backend.
I recently upgraded amplify from 1.4.2 to 1.6.8 and this is when the issue started to show up.
Amplify.DataStore.observe(Profile::class.java,
{ observationCancelable ->
//ERROR
},
{ changedItem ->
when (changedItem.item().state) {
//DO Business logic
}
},
{ exception ->
//ERROR
},
{
}
)
When I query the datastore I am getting outdated results that are not the same as the data on DynamoDB. Is there any way to figure out why the local datastore is not being updated? Could it be an issue with the configuration with the server? Or is there some setup step that I have missed?
Edit: Added some extra details below
So a few more details I wanted to add to this that seem way more relevant as well as updates based on my research. I am switching between endpoints(dev to testing environments). It would seem that the dev environment is working fine with the application, using the datastore correctly and doing the proper AppSync. But in the new testing environment, when the app starts, it gets the latest version of the datastore but it fails to do any AppSync despite being able to make changes to the backend.
Here is an error I am getting when the app attempts to subscribe to the Profile object in the back end
amplify:aws-datastore: Unauthorized failure for ON_CREATE Profile
amplify:aws-datastore: Releasing latch due to an error: Subscription error for Profile: [GraphQLResponse.Error{message='Not Authorized to access onCreateProfile on type Subscription', locations='null', path='null', extensions='{errorType=Unauthorized}'}]
Is there some config file that I should be looking at to compare with to make sure that the endpoints match or some access key that the app needs?
I'm building an Android application which has to work offline for weeks, but can sync immediately with a remote DB as it goes online.
My question is can Firestore be a good option for this? How long does Firestore keep its offline cache?
Firestore can be configured to persist data for such disconnected/offline usage. I recommend that you read the enable offline persistence section in the docs, which contains this sample of enabling this feature:
FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
.setPersistenceEnabled(true)
.build();
db.setFirestoreSettings(settings);
This persistence is actually enabled by default on Android and iOS, so the call above is not needed.
Your Android code that interact with the database will be the same whether you're connected or not, since the SDK simply works the same. If you want to detect whether data is coming from the cache (and thus potentially stale), read the section Listen to offline data in the docs.
The data in the cache does not expire after a certain amount of time. The only two reasons data is removed from the cache:
The data has been removed from the server, in which case the client will remove it from the disk cache.
The client needs to purge its disk cache to make space for more recent data.
EDIT-25/5/2020: Francesco is correct, the docs link given in the comment does clarify that. It seems the cache size has been changed, by default it has been decreased to 40MB.
OLD: The following answer follows the official guide in the following link:
Handling Cache size
FirebaseFirestoreSettings settings = new FirebaseFirestoreSettings.Builder()
.setCacheSizeBytes(FirebaseFirestoreSettings.CACHE_SIZE_UNLIMITED)
.build();
db.setFirestoreSettings(settings);
The above code has a flag set for setCacheSize(), which will prevent your cache from
being cleared. You can also specify the same in size. If you do not set this by default the size is 100MB.
As per the guide, there is a method to check if the data you query came from cache or the firestore. Also the moment your device is back online the firestore refreshes the cache, and keeps the data synchronized.
To answer your question, as you have to work with offline data for weeks, i suggest every time the data is fetched to store it in json/xml formats, as storing huge amount of data in cache is not a really good approach when thought of in terms of performance.
I hope i helped you clear some things out.
If you listen to data in Cloud Firestore, you will get immediate snapshots of cached data and also updates when your app is able to connect online:
final DocumentReference docRef = db.collection("cities").document("SF");
docRef.addSnapshotListener(new EventListener<DocumentSnapshot>() {
#Override
public void onEvent(#Nullable DocumentSnapshot snapshot,
#Nullable FirebaseFirestoreException e) {
if (e != null) {
Log.w(TAG, "Listen failed.", e);
return;
}
// Determine if the data came from the server or from cache
String source = snapshot != null && snapshot.getMetadata().hasPendingWrites()
? "Local" : "Server";
// Read the data
if (snapshot != null && snapshot.exists()) {
Log.d(TAG, source + " data: " + snapshot.getData());
} else {
Log.d(TAG, source + " data: null");
}
}
});
Persistence is enabled by default so this behavior does not require any configuration.
Tried to use the azure mobile app for my cordova project but the problem is when i am offline and i enter the data, the data is stored locally and upon going online the data is synced to the database, but
while we enter a record offline, close the app then reopen the app and again add the record the latest record is overwritten to the local db and the earlier records are lost while syncing to the azure database.
syncContext = client.getSyncContext();
// Define an overly simplified push handler that discards
// local changes whenever there is an error or conflict.
// Note that a real world push handler will have to take action according
// to the nature of conflict.
syncContext.pushHandler = {
onConflict: function (pushError) {
return pushError.cancelAndDiscard();
},
onError: function (pushError) {
return pushError.cancelAndDiscard();
}
};
return syncContext.initialize(store);
});
Anyways got the answer to the problem had to replace
pushError.cancelAndDiscard();
call to
pushError.appendAndDiscard();
and worked excellent as required for me
I'm writing an android app which uses firebase database as backend. I need to push notify a particular device when a field in the database gets updated. I've been searching and found examples to do it using php, other servers or the firebase console. Do I really need to get another server?
Updated on 2017-07-02
Since March 2017 Firebase offers Cloud Functions for Firebase, which allows you to run JavaScript functions on Google's servers in response to events in Firebase (such as a database update). The first sample use-case is Notify users (using Cloud Messaging) when something interesting happens, so I recommend reading more about it.
You don't need to send push notification. Because Firebase provides real time syncing of Firebase database. When you add a listener to the database in client it will be called upon every change and can fully control it.
this is an example of registering a change listener:
// Write a message to the database
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("message");
myRef.setValue("Hello, World!");
// Read from the database
myRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
String value = dataSnapshot.getValue(String.class);
Log.d(TAG, "Value is: " + value);
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w(TAG, "Failed to read value.", error.toException());
}
});