I am restructuring my code to use ActivityResultContracts, and I've been able to recreate the old way of doing things with onActivityResult by passing in "codes" with my Intents and just passing them back from the called activity. Everything is working fine, but how would I manage to do that with App Updates, even the Google documentation is still using onActivityResult to check for app updates.
After looking at it for the past few days, it does not seem like it is possible to forgo using onActivityResult; the cancel response is only returned to that method. If you have a listener setup to check for resumed downloads, you will get a response there (as onResume is called when the calling activity is moved back to the foreground) but you only get that an update is available and the install status is unknown (which coincidentally is the same value as cancelled, and you can't do anything there as you get the same values on the initial call to check for an update). I don't see the point in deprecating a method you're still required to use, but oh well.
Related
I am adding ValueEventListener in my activity of android.I am worrying if my app crashes or anyhow, onDestroy isn't called then my listeners may not be
removed manually.I also used system.exit in somewhere,I didn't used them in service though .now I am worrying if they aren't removed and my application is closed,will they be still connected and increase my firebase billing?
This is a 'yes but no' answer, according to the documentation, all listeners are registered on the server which invokes a trigger to send the updated information.
Since the listener is not unregistered, it is therefore not 'removed'. Instead, the server will detect that the client has timed out after a few attempts and will stop sending requests.
Effectively they are the same thing, only delayed. relaunching the app will not reconnect to the listeners if the session ID does not match.
When you are using a ValueEventListener, which means that:
Classes implementing this interface can be used to receive events about data changes at a location.
If you are using addValueEventListener(ValueEventListener) method, it means that you are listening for changes in real-time. This also means, that if you don't remove the listener according to the life-cycle of the activity, the listener will remain active, until Android OS will eventually close it. This means that as long as the listener is active, the "onDataChange()" will always fire providing a snapshot of the data at the location the reference is pointing to.
It's true that there is no guarantee that "onDestroy()" will be called. So most likely you should consider using addListenerForSingleValueEvent():
Add a listener for a single change in the data at this location.
Case in which there is no lister that has to be removed.
According to your problem. You are passing a callback to get the data changes. So simply follow the Activity lifecycle, onResume() you can set the callback listener & onStop() remove the callback listener. If your app crash, there is no guarantee that your activity going to maintain the lifecycle, so you must handle the crash at your own. Simply use try catch
I am very new to Cloud Firestore and have some doubts regarding the querylistener read count. As most of the answer suggested on stack overflow that, we should attach the listener in onStart() and detach in OnStop() in the Android activity. I am building an app in which I have to attach the listener on Dashboard Activity and the user will navigate back and forth between dashboard and other activity frequently.
So,
when the user navigates to another activity the listener will be detached (onStop()) and if they come back it will be attached again (onStart()). And suppose between this, nothing has changed in documents on the server, will I still be charged for all read count even though nothing has changed on the server?
Should I keep the listener attach and detach only when the user kills the app? By doing this, I will be only charged for the document which is changed while the app is in the foreground and not the all-read count if navigates between Dashboard and other activity.
we should attach the listener in onStart() and detach in OnStop() in the Android activity
If you are attaching a listener for getting real-time updates, yes, you need to remove the listener according to the life-cycle of the activity, as explained in my answer from the following post:
How to set addSnapshotListener and remove in populateViewHolder in RecyclerView Item?
However, if you simply create a get() call, followed by addOnCompleteListener(), there is no listener that needs to be removed.
And to answer your first questions. It depends. If you are using a SnapshotListener and nothing is changed on the server, you'll always read the data from the cache. So you can go back and forth, as long as you want. But also keep in mind, that if the listener is disconnected for more than 30 minutes, you’ll be charged for reads as if we had issued a brand-new query. On the other hand, if you are using get(), you'll be charged with a number of read operation that is equal to the number of documents that you get, every time you call it, even if there is nothing changed on the server.
Why?
In order to provide up-to-date data, the Firestore SDK needs to check the online version of the documents against the cached one. That’s the reason why you are charged, regardless of what exists in the cache or if something is changed or not on the server.
To answer your second question, if you are using a SnapshotListener, you should always consider removing the listener, otherwise, your app will remain synchronized until Android OS will eventually close the app. It doesn't really matter if the app is in the foreground or in the background, if the listener stays active, you'll always be charged accordingly. You can find more info in the following article:
How to drastically reduce the number of reads when no documents are changed in Firestore?
Using the Google Play Location and Settings API a developer can easily check if the Android device's location settings are correct.
The API also supports fixing any settings that are not correct using the startResolutionForResult method. (It calls Activity.startActivityForResult() and provides feedback of users "yes/no" choice in the activities onActivityResult() method.)
This all works fine so far, except that I am calling startResolutionForResult from a fragment. As per this question, an intent needs to called via Fragment.startActivityForResult() for the result to be given to the fragment as well.
Is there any way of getting this result to the fragment? I was half expecting a createIntentForResolutionForResult on the ResultStatus class. Ideally I don't want to modify my containing Activity.
You need to call super.onActivityResult on the Activity and call your Fragment from there. Otherwise its presence is there just for the sake of it and no work is done on the calling method which is startResolutionForResult in this case. Check the source of FragmentActivity.
In my application i want to let users sign in with their google account so i am using google play services. This works - they can login and logout. I also want to find out if the user is signed in the onCreate method when i pass from one activity to another. I am trying to use Google play services isSignedIn function for this but on onCreate method it always return false (because google play service trigger on onStart).
Why do I want it ?
Because, i have two login option. One is google account another is my own login panel. I want to know that is user sign in wtih google or my system or not on onCreate. So i will give direction my flow.
How can i achive this or do you have an alternative suggestion ?
Thank you for answers.
This is due to the Activity lifecycle. Every time an Activity goes into the background, it will get onStop. The Play Games API requires you to disconnect when this happens. When the Activity comes back into the foreground, it gets onStart, and then GameHelper will attempt to reestablish the connection. Until this happens, isSignedIn will return false. When the connection is restored (which should be very fast if the user had already signed in), the onSignInSucceeded callback will be called and from that point on isSignedIn will return true.
It's impossible to know, on onCreate, whether or not the sign-in will succeed. Instead, you should wait for either onSignInSucceeded or onSignInFailed. It is guaranteed that one of those two callbacks will be called shortly after the Activity comes into the foreground.
At that point, you can decide what to do, because it will be clear whether or not the user is signed in with Google+.
I am not certain how your app works but it sounds as though you may be calling GameHelper.onStop at the end of one activity when in fact you want the game to continue in another activity. I don't think you can do this (see the accepted answer here):
Google Play Game Services multiplayer with Activity switching
My app is arranged into fragments and I have one fragment which interacts with GameHelper. Therefore, once I have performed GameHelper.setup and GameHelper.onStart, I am able to call isSignedIn from any method in any fragment and get the correct response.
An alternative approach (which I have used in the past) is to save the result of isSignedIn in a boolean in shared preferences. You can then check this to determine whether the user is signed in or not.
I have a strange problem and hope that someone of you has an idea what happens here.
My app structure is as follows:
I have a main service which registers a broadcast receiver and listens to intents like screen on/off etc. So this service runs indefinitely.
When such an intent is received, I start another service which does the action
Inside this action service I launch an AsyncTask to fetch battery related stats via reflection. After the service is done, it calls stopSelf().
So everything works as expected, except that when the battery related infos have been fetched one time, each subsequent call of the AsyncTask/Reflection methods deliver exactly the same result which has been delivered before.
The battery stats have of course been updated in the meantime, but I do not get the new updated numbers, but always the stats from the first method call.
That is until I go to settings and force stop and restart my app, then I get updated battery statistics again, at least one time, because after that I'm stuck with these numbers again.
So my question:
Could it be that the results of the reflection call are automatically cached somewhere and that each subsequent call doesn't really fetch the new data but just delivers some cached results? What else could be the problem?
I'm thankful for any ideas, I you need some code lemme know :)
Ok, I've found a fix to this :))
The library of Better Battery Stats uses the singleton pattern for a needed class.
It also includes an invalidate() function, which sets the singleton instance to null, so that at the next getInstance() it gets reinitialized.
I'm using now invalidate after each statisitics fetch, and now I get the updated statistics on every call. Although I am still not sure why the Singleton pattern seems to be the root of this issue, it should also work with having one initialized singleton instance...
Well, one does not simply have to understand everything ;-)