I have a requirement in my Android app, that makes an HTTP request to the server to perform a long running task. The architecture on the server is that; the HTTP request returns immediately with a transaction ID. What I need next is to poll the server to check whether the job has completed and once completed show the result to the user.
When the first HTTP task completes I show a UI Fragment which has a progress bar asking the user to wait while the task completes. Ideally, I would like to show the result to the user on the same Fragment once the task has been done. But I would also need to consider situations where the user might press the Home button or move out of the app/screen in some way.
My current solution is:
Poll every 10-15s with some sort of exponential backoff, as long as
the activity is still attached.
The server sends a push notification regarding task completion - but
I'm worried about reliability of this.
Is there a better way to achieve this? If so, what would be a good design pattern for this? Are there any libraries available that handles this scenario?
Related
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 have a situation where I have to do a server call from Android and based on the result of the call ( result would be either true or false) I want to proceed ahead in the code flow and pop a Dialog based on this result. Till the call is complete I don’t wish to proceed ahead in the code flow or logic. In short, I want to carry out a sync operation
At the server side, I will receive a HTTP Post request from android client and based on the parameters in the POST I do some processing by fetching values from the DB and return back true or false to android client.
To carry this out correctly on Android side, I researched and got two options.
Using Handler with AsyncTask does not work in my case because if
I use AsyncTask with Handler, the task result will arrive
sometime in future in Handler and the calling function will return
immediately whereas I want the calling function invoking
AsyncTask to finish i.e. wait till the server returns backs before I
proceed ahead .
The other option that I came across was to use
AsyncTask get() method . Since I am not carrying out a long running
task and rather performing a simple calculation on serverside, this
may not cause a an ANR situation even if I block the UI thread.
Are there any better options of carrying this out ? Is AsyncTask get() here actually one of the correct uses of get() ?
Im currently using GAE from Android. I have a search operation which performs what might be a long running query on the datastore (called from AsyncTask). The user has an option to logout from the app while this process is still running. Without an option to cancel this request the actual logout has to wait until the process finishes and the control is back to the client (which, as i said, can take a few seconds).
Is there a way to cancel a call to a GAE endpoint while the server is running and return the control to the client ? Thanks.
p.s.
Obviously, cancelling the AsyncTask only is not enough.
Personally, I put the server comm in a service so that requests can (usually) finish regardless of what the user does. In your case, could you let the user log out, but also let the request complete?
Otherwise, I don't know how to cleanly interrupt an endpoint request. Unfortunately, the actual blocking operation is buried in the endpoints (Google API Client library) code and no cancel operation is exposed that I'm aware of.
When you write that cancelling the task - AsyncTask.cancel(boolean mayInterruptIfRunning) - is not enough, is that because you've tried it and it doesn't interrupt a blocked operation.
No, Google Endpoints use servlets and servlets have no (standard) way of telling a running request to cancel it's work. You will need to build something proprietary.
For example: in your long-running process on server you in it's main loop check if user is still logged in (via a flag in the datastore or memcache). If this flag tells you that user is logged out, then you cancel the processing and return. Also a login/logout procedure must appropriately set this flag.
I need to make a batch of HTTP requests and feed the responses to a ListView one by one. I am using an async task and running a for loop of requests in a doBackgroundProcess method. Is that a correct approach? If not, please guide me to the best practise.
It's not entirely clear what you're trying to do. If you're doing the following:
Collect a set of HTTP requests
Send them.
Get back the results.
Post to an adapter backing a list view
Wait for the user to initiate the next set of HTTP requests
then I suggest you look into an IntentService. If your Activity goes into the background for any reason, AsyncTask will stop, but IntentService continues until it's done all its work.
I'd even suggest you stick your HTTP results in a content provider. It's best to persist data that takes a long time to retrieve. Your users will like you for it! You can also stop when you lose connectivity, and then re-start where you left off, if you have the data already. And if connectivity isn't available at the start, you can show users the most recent results.
Remember that the network isn't always available.
One feature of my application is to retrieve live data (JSON object) every 2 sec and display it (only while app is in foreground). I am executing an async task for every 2 sec. But this is making the app slow. I have searched for alternative, but i only got C2DM option. I can't use it because of server limitations. Could you please tell me an alternative or effective way for polling?
One option, if you have control of your server, is that you can switch to something like Comet (long-held http requests) to avoid the necessity of ongoing polling requests.
change the execution of the async task from every two sec to after getting the response for previous update you can initiate it in onpostexecute function... this will make your ui faster
also try using gzip so that the data gets transferred faster do not pool async task
your ui is getting slower as an async task is shot up before the previous one ore ones have completed