Android - API Request Callback after onDestroy - android

I hope I can explain this well ...
I am trying to understand better how to handle HTTP callbacks in Android, so I have created a simple app that uses Volley for HTTP requests. It only has a button that triggers an HTTP request to a service that, basically, just updates a number in a database and sends it in the JSON response after 5 seconds. The Activity gets the response and displays the response in a TextView. I am testing it in a real device that has enabled the "Don't keep activities" option in Settings - Developer Options.
This is the scenario I am testing:
Start App.
Tap the button that triggers the HTTP request.
Inmediately after tapping the button, tap the device's home button to send the app to background. onDestroy method is called because of the "Don't keep activities" option.
Wait a few seconds for the HTTP response. I can see the device gets it because it is printed in the logcat monitor and the database is updated.
Before running the callback, I check that the activity is still alive. Since the activity has been destroyed, the callback is ignored. If the app is restored from background, there is no crash but the Network Response is missed. Also, if I tap the button again, it sends a new HTTP request and increases the number again ...
So, the questions are:
Which are the best practices to deliver network responses to the UI? I mean, if instead of a simple operation let's say it was a register form and I get a phone call or something that forces me to send the app to background, where anything can happens, how can I make sure to not miss the network callback? Is there something that could delay the callback execution until the app is again in foreground?
Is there a way to save a Bundle like the one in onSaveInstanceState after onDestroy has been called and restore it when app is again in foreground?
Let's say the information that the HTTP response contains is sensitive. Is there a recommended way to handle this case? I was thinking to save the response in the internal storage and check for it when the app is again in foreground, but I don't know if it is possible to do that after onDestroy has been called, or if it not a good idea with sensitive data.
Thanks in advance!

1)YOu can never miss the network callback. You'll be called even if you're in the background, unless your entire app (not just the activity is killed). You'll just get the callback while backgrounded.
2)No. If you need the result of a network call the next time the activity starts like that, I suggest you use a Loader to load the data. That way you can query for the Loader results next time, and start the request only if needed.
3)Do what I suggested in 2 and there's no need for this question, its all in app memory.

Related

MVP: Continue async http request or cancel?

In my phone when minimize aplicatoin then the Android destroy activity.
In Developer options I turn "Don't keep activities".
I try to implement MVP.
I have a activity with button.
Steps:
User click button
As result activity call method from Presenter: presenter.dowanloadFile(). This is a async http request. The size of file is about 10 MB.
Show progress
After 10 seconds user get success http response
Presenter call method from view: view.hideProgress
OK. This case work fine. Nice.
But suppose the next case:
User click button
As result activity call method from Presenter: presenter.dowanloadFile(). This is a async http request.
Show progress
After 2 seconds user minimize application
As result activity is destroy (because turn Don't keep activities)
After 3 second user return to application
As result create new activity
After 5 seconds user get success http response
Presenter call method from view: view.hideProgress
The question is:
Is I need to continue http request when user minimize application (item 4). Or I must cancel current http request. And when user again return to application I must again start new async http request?
I want the next: When user return to application and if http request success finish then to show result. If the request is not finish then continue to wait http response.
It depends on what you want to happen? It seems like it's wasteful to cancel a request that is expensive (10 seconds is a lot), however you also need to consider what "cancel" mean in the context of an HTTP request.
For example, if cancelling a request, only prevents results from being delivered. Than means that your file was actually uploaded but you don't get callbacks anymore for that request result. Also be careful if your upload thread has a reference to your view, it will be leaked till the upload is done.
If you don't really care about the request, you can just cancel it. Assuming your server is smart enough to identify another request for the same file, so you don't duplicate it if your activity was re-created.
Another option would be not cancelling the request. Then you would need some mechanism of having your "presenter" survive the Activity re-creation.
There are numerous ways of doing that:
Having a cache for your presenters and not re-creating it if it exists in the cache.
Using headless fragments, which are basically are fragments with setRetainInstance(true) to survive an activity re-creation.
Moving your upload logic to a background Service or JobScheduler, and having your presenter/view only subscribe to the state of the upload process, but not actually own it.
You can investigate each option individually when you decide what is the most convenient for your application.

I want a rest call to happen in android if the app is killed by OS or removed from recent app list

I have to add the following feature in my android application.
There is a client, when the client logs into the application, clicks a button to make themselves available to the user by going online. When he clicks the button a rest call is made, and which change the DB status(status changed to online) and make him online.
Now my problem is I want to make the client unavailable(offline) if the app is getting forced close or removed by android from the background due to low memory or removed by the user from the recent app. If any of these situations occur I do a rest call to handle the situation.
In the normal scenario if he is online he can simply click the button again to make a rest call which will change his status to unavailable(offline) in DB.
NOTE: I don't want to use onPause() or onStop() method because I want the client to be online even if he navigates out of the application and comes back.
In principle you can't because there's always a case when user can get disconnected without feedback (e.g. losing signal, battery).
IMO you should look for ways to detect the timeout from the server side, similar to socket.io disconnect() outlined in this SO answer.

Send POST request when back button is pressed or before app is killed

First part
I have to send a post request to the server only when the the activity is done with. It may be because back button was pressed or app is closed. Does the method isFinishing called when back button is pressed?
Second part
What should i do for situation where app has suddenly crashed and it is unable to send the data?
By the way i am using volley for all the network operations.
isFinishing isn't called, it's a check you can make to see what caused the Activity to finish. See here. What you mean is onDestroy. You can put your POST request there, but arguably, that is not the best situation and timing to perform HTTP calls.
If an app crashes it crashes. You can't stop the crash to perform other actions, because it's a crash.
You should consider using the disk as cache for the data you want to send, and in an event of a crash, when the app is loaded next time, read the data from the disk and send it.

Using an intentService or are there better ways?

I'm creating an app that will do the following:
If a mail comes in with a messageword. It needs to start to locate the phone by GPS functionality. after that it must show the result to the user.
I already have it working with using a broadcastreceiver for fetch the message. After that is starts an Activity. If don the userinterface is updated.
I have here two problems:
1) if the screen rotates all variables are set to zero... well can solve that with saving variables at onPause() and read those values at onResume()
2) if the user use the backbutton... the thread is cancelled.
Actually I want that the user can't cancel the GPS-action.
Is it a good idea to use an Intentservice for this?!
-message comes in
-BroadcastReceiver fetch the message and start the intentService
-if the processing is done... I can start an activity with the results (and the service is closed automaticly after the processing is done?!
Is there maybe a better way to attack the problem?
You certainly can and should use an IntentService for long running operations in the background. However, if the user backed out of your activity, they most probably did this for a reason, and popping up an activity with results they might not care about anymore, might not be such a good strategy. You could cache the result instead, and show it next time the user opens your activity.

When the app goes to background during an AsyncTask execution what should it do?

I have an application that uses AsyncTasks to make calls to a REST server.
Imagine that during a loading period (this is, the AsyncTask going to the REST server and gets data to the next screen) the user presses Home.
What is recommended:
Cancel the current AsyncTask(s) and restart when resuming the Activity
or
Continue the AsyncTasks but avoiding the startActivity by checking if the app is on background (to avoid the foreground of the new activity after sending the app to background). And onResume sending to the next activity
Worst case scenarios that you should foresee:
The app goes to background and is killed due to lack of memory
The asynctask fails due to timeout or other REST error
After both, the user goes back to the app...
Well I ll recommend Service which should use AsyncTask to do its work. Service will insulate your activity from orientation change or user exiting. AsycnTask will insulate from the UI thread being blocked. But do make sure to exit Service when you are done with REST api.
This will give you best of both. Also if you are not using DB as a local cache then you can try that too. So even if the user goes away, the service will store the fetched data in the DB and when the user comes back you can quickly display the screen.
EDIT: Just want to add IntentService are easy to implement.
Try Design Patterns for REST clients on Android by Google for more exhaustive explanation
Using AsyncTasks can get really messy during a configuration change. From personal experience I would recommend going down the IntentService/ResultReceiver route instead.
See this post for more info:
Restful API service
I guess what you want to know is which way is better from a users perspective. From my experience, a user expects the app to continue the download in the background, because if he presses home, he normaly either wants to check some other apps in between or he pressed it unintentionaly and wants to go back into your app as soon as possible. If a user wants to cancel the download, he normaly presses the back button or a specific button to cancel that is somewhere on the screen of your app. So as the user normaly wants to continue using the app, the more convenient behaviour of your app is to continue downloading data and hopefully already display the downloaded data to the user when he gets back into your app.
From a technical perspective, I would not use a service. I would just leave the AsyncTask running. And in the worst case when the app gets killed inbetween, the app automatically goes into the starting activity when the user gets back to the app, because the app is restarted anyway. In the case that the asynctask fails, you can check if the data has been succesfuly downloaded and if not showing the starting activity. You can easily implement this with storing the downloaded data in a variable which's initial value is null. If the variable is still null after downloading, the AsyncTask failed and you have to go into the starting activity. I think this is a pretty robust implementation.
downloading continues as does the android market app, but it shows a notification with the option to cancel. You can implement this, using a service to download.

Categories

Resources