I am using Firestore in my app. According to the documentation, it supports offline data persistence and when the network is on again, Firestore synchronizes changes.
Here is my code.
FirebaseFirestore db = FirebaseFirestore.getInstance();
User user = new User();
db.collection("users").document("doc").set(user);
It works as expected: it caches locally if the network is off and synchronizes when the network is on again. But I keep getting this warning:
W/ManagedChannelImpl: [{0}] Failed to resolve name. status={1}
This post says it is due to no internet connection. If Firestore supports offline persistence, why do I get this warning? How to get rid of this warning?
It works as expected: it cashes locally if the network is off and synchronizes when the network is on again.
That's the expected behaviour.
But I keep getting this warning:
W/ManagedChannelImpl: [{0}] Failed to resolve name. status={1}
This post says it is due to no internet connection.
That post it right, it's because of no internet connection.
If Firestore supports offline persistence, why do I get this warning?
You get it because between the time when you regain the internet connection and the time when the listener actually becomes active, there is an amout of time in which your client is not connected to the server. That's the reason why that warning is printed out multiple times without stopping unless the network is on and the client is synchronized again with the server.
The reason that the retries aren't happening so quickly as you expect is because the code that performs the retries is using a so called exponential backoff algorithm. This means that this code prevents all the retries that can happen on user's device so quickly in favor of performance. Too many retries can also affect the user by consuming too much bandwith of the his data plan.
When you are listening for changes in a Cloud Firestore database and you have some network disconnects, this what is happening and unfortunately there isn't much you can do. You don't have any control on how Firebase Firestore SDK manages its connections.
How to get rid off this warning?
IMO, since it's only a warning and not an Exception and it is displayed only for a few seconds till the connection is reestablished, you can simply ignore it.
But if you really want to get rid of it, the code below might help you. Please note, that I haven't tested yet.
InstantiatingGrpcChannelProvider channelProvider = InstantiatingGrpcChannelProvider.newBuilder()
.setKeepAliveTime(Duration.ofSeconds(60L))
.setKeepAliveTimeout(Duration.ofMinutes(5L))
.build();
FirestoreOptions firestoreOptions = FirestoreOptions.newBuilder()
.setChannelProvider(channelProvider).build();
FirebaseOptions firebaseOptions = new FirebaseOptions.Builder()
.setCredentials(credentials).setFirestoreOptions(firestoreOptions)
.setConnectTimeout(5000).setReadTimeout(5000).build();
FirebaseApp firebaseApp = FirebaseApp.initializeApp(firebaseOptions);
Firestore firestore = FirestoreClient.getFirestore(firebaseApp);
Related
I want to change user status to show either he is online or not. I want to change user status to false in database when User close application or when he loses connection with server.
As a method is available named as onDisconnect() .I have used that method to update user status by using following code .
HashMap<String,Object> user_online_status=new HashMap<String,Object>();
user_online_status.put("online",true);
DatabaseReference firebaseDatabase=FirebaseDatabase.getInstance().getReference().child("Users").child(userId);
firebaseDatabase.updateChildren(user_online_status);
//then to show user offline
user_online_status.put("online",false);
firebaseDatabase.onDisconnect().updateChildren(user_online_status);
I do that task but as it is on client side and If we want to monitor user connection with server and when connection is terminated node should be updated by Server Instead of Client.How can we change node value from server as User lose connection with server?
There are two ways the user can get disconnected from the Firebase Database.
a clean disconnect, where the client sends a signal to the server before it disconnects.
a dirty (for lack of a better term) disconnect, where the connection gets closed before the client can send a signal.
In the case of a clean disconnect, your onDisconnect handlers will immediately fire and thus your database will immediately be updated.
In the case of a dirty disconnect, Firebase depends on the socket layer to signal when the remote client is gone. This may take anywhere up to a few minutes. But eventually the server will detect/decide that the client is gone, and your onDisconnect handlers will fire.
A small note in your data structure: you that there is a 1:1 relation between a user and a connection. That is unfortunately not the case.
A user may be connected from multiple devices. If they now disconnect from one of those devices, the onDisconnect from that device will set online to false while they may still be connected on another device.
Mobile devices/networks have a habit of going through occasional disconnect/reconnect cycles. This means that you may have multiple connections, even on a single device. In case of a dirty disconnect, the onDisconnect handler may be fired much later, when you've already set online to true for the new connection. In such a case, your lingering onDisconnect handler will set online to false while the user may already be reconnected.
All this is to say that you should not rely on having a 1:1 relation between a user and their connection(s). The samples in the Firebase documentation treat connections as a collection and assume that the user is connected as long as there is any "connect ID" (generated by push()) left for that user. I recommend you do the same to prevent hard to debug race conditions and connection problems.
Since couple of weeks this exception appears sometimes on my App:
Non-fatal Exception: com.facebook.FacebookAuthorizationException: CONNECTION_FAILURE: TigonError(2): TigonLigerErrorDomain(2) AsyncSocketException: connect failed (immediately), type = Socket not open, errno = 101 (Network is unreachable)
at com.facebook.login.LoginManager.onActivityResult(LoginManager.java:218)
at com.facebook.login.LoginManager$1.onActivityResult(LoginManager.java:173)
at com.facebook.internal.CallbackManagerImpl.onActivityResult(CallbackManagerImpl.java:95)
at com.myapp.util.connect.FacebookConnect.onActivityResult(FacebookConnect.java:338)
Facebook SDK: 4.27.0
Android version's impacted: 4.4.2 and 7 (Crashlytics informations)
Have you got some ideas guys about this exception?
Thank you very much
UPDATE
I wrote a ticket on Facebook support, and after several messages, the last is:
Hi Anthony, thanks for the additional details. Looking at the data for your app,
there don't seem to be any failed API calls logged for your app. This indicates
that the login attempts failed before they reached our servers, and confirms
that this was indeed due to network errors.
I agree that it's not the ideal experience for users to have to retry their
login attempt, but in the case of network-related issues like this, this is the
best approach. I would recommend prompting the user to check their device
connectivity and initialize the login flow again.
From debugging this, it's unlikely that this is due to compatibility issues with
Retrofit, though I can't rule it out with certainty. It's more likely that the
affected users simply experienced a temporary drop in connectivity.
I'll mark this as closed since there doesn't seem to be a bug within the
Facebook SDK, but if you're able to get any information that would indicate
otherwise (for example, a way to consistently reproduce the error on a device
that has full internet connectivity), please let me know and I'll be glad to
help look into this again.
This exception means that user of your app is experiencing problems with his Internet connection. It is a problem that all the developers should care when making network calls, but it is especially important for mobile devices (the quality of mobile internet can be significantly low). Unfortunately netwok errors cannot be eliminated completely.
The common way of solving such a problem is making retries: either on the side of the app (retrying, showing user an error only after several network errors), either on the side of the user (suggesting user to try once more).
Firebase Realtime database has a function goOffline, goOnline which can manage the connection manually. But, Firestore doesn't have these methods.
Does Firestore return exception something like NETWORK_ERROR when device lost connection with server? If it doesn't, how can I manage Firestore connection manually when device can't connect to internet and reconnected. (e.g. Airplane mode, Bad wifi)
In my case, I don't use persistence mode.
Does Firestore return exception something like NETWORK_ERROR when
device lost connection with server?
You have use addOnFailureListener which uses OnFailureListener that can just gives you an Exception object to find the cause or message behind the exception via getCause or getMessage and further can apply String checks like contains etc to verify the cause but currently there is no standard way provided by FirebaseFirestore.
how can I manage Firestore connection manually when device can't connect to internet and reconnected. (e.g. Airplane mode, Bad wifi)
You can check the connectivity yourself also at desired places before executing firebase code
I'm trying to figure out how to handle intermittent network connectivity in regards to Amazon SQS on Android. I need to send messages every 10 minutes (or so) and would like any messages that cannot be delivered due to network issues be sent at the earliest time when the network is restored. My hosted service orders messages so getting a few queued messages at once is no issue, but having messages be completely dropped is a problem.
AFAIK, my retry policy is set to retry up to 25 times and then give up. Obviously this is not a great solution, but I didn't see any hooks for network connectivity callbacks or any option to have it retry when the connection is restored if the cause of the error is due to network issues.
The only alternative I can think of (using what I know about this API) is to implement a VERY long-lasting back off strategy and hope the user gets network again with X amount of time, but that seems incorrect.
ClientConfiguration ccfg = new ClientConfiguration();
ccfg.setRetryPolicy(new RetryPolicy(null, null, 25, false));
AmazonSQSClient client = new
AmazonSQSClient(params[0].credentialsProvider, ccfg);
Setting the retry policy is not going to help you in this case.
What you might need to do is:
Cache sqs messages when network is not reachable on mobile.(either file or db).
Implement a network change listener on android and trigger sqs calls when the networks changes from unreachable to reachable.
Take a look at https://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html
i am trying to develop a cordova(3.5.0) project in android platform and in that i have to check network connection availability before each API call. for that i am using 'navigator.connection.type',and some times it return 0. why this is happening? plz help me for solving this trouble
Without some more details I can only guess.. There are some conditions which may cause this.
navigator.connection.type = 0 -> connection type unknown.
So you may have a connection, you may not it simply hasn't been determined yet, or because of privileges the device isn't saying.
Are you calling this check too early? ie before deviceready
In our app we do not check the connection each time but we handle it this way:
by making the API request anyway, knowing that its possible to fail, we set a timeout and error handling. If it fails by error or timeout we check connection type and then ping the server with a simple "hello" "acknowledge" request. Its a super small request that we figure will work or if it timeouts again the connection must be so poor it might as well be disconnected.
This is because there are really two types of connection you need to check. Many miss this!
And also because its navigator totally lies some times... :/
Just because wifi is on and connected and navigator tells you this, it doesn't mean you will have a connection to the outside world. You need to check the network hardware (which is all navigator will tell you) but you must also check network connectivity, if this is something you are sensitive about.