I have a language translation app that needs to download some initial data on the first run. When the app is first launched, the first step is to get a list of currently supported languages from the server. The user then selects which they wish to install, and the rest of the tables are then downloaded.
I check if the languages are present in the local db, and if not, connect to the server and download them as JSON. The user cannot do anything until this data is retrieved from the server.
If there is no network connection, a dialog should prompt the user to go to their WIFI settings. If there is a network error with the download, another dialog would then prompt the user to retry now, or wait until later. If the download succeeds, a new Intent is launched to send them to choose the languages to install.
I have this mostly functioning (my AlertDialogs aren't showing), but the question is whether this is the proper way to accomplish this. I've currently set it up as an AsyncTask, but I've seen plenty of posts with responses yelling about how an AsyncTask should not be used when the UI depends on it. Fair enough, but an AsyncTask seems to be the recommended method for downloading data.
Is an AsyncTask the correct way to download the data, or is there a preferred alternative?
How to best deal with this on the UI, as it depends on this data? A splash screen? I'd rather not, but it seems something should be there, and I need somewhere to display the AlertDialogs if necessary.
Is an AsyncTask the correct way to download the data, or is there a preferred alternative?
No, AsyncTask is not a good solution for networking because:
You need a component from where you start this task. Activity is not a good choice because your network request will be tied to the UI and it will be hard to handle screen rotations, etc.
AsyncTask works on a global serial executor by default. It will block all other async tasks in the app until it finishes. So you will have to provide your own executor to avoid that.
The process level would be Background Process according to http://developer.android.com/guide/components/processes-and-threads.html
With a Service you can achieve Service Process which is better.
Use Service instead. You can implement any threading you want inside. You can use a regular Thread, a ThreadPoolExecutor, a Handler, or some third party solution. Service provides you great flexibility.
Regarding your second question, take a look at material design spec first: https://www.google.com/design/spec/material-design/introduction.html
Come up with some ideas and then ask a separate question if that is still not clear.
Related
What would be the best approach for download on Android. You would be using AsyncTask or Service. I see several example being made of two ways, but what would be the best approach?
That's not the right question to ask, and the answer may be both. An AsyncTask is a separate thread of execution. A Service is just a piece of your app that runs in the background and can live past the end of an Activity.
You need to download any files on a non-UI thread, so either a Thread or AsyncTask is necessary whether you use a Service or not. So you'll always use one of those two. The question of whether or not to also use a service is a question of whether you need the file downloaded even if the user goes to another Activity (there's a few other reasons why you may want to use a Service, but this is the main one).
i suggest ,it depends upon the size of file.for small content file ,asynch is great but if is gonna be a longer task then you can go for service because service also comes with restart feature (start_sticky) in case user kill your app or your app got killed by the android os(LMK : low memory killer) in case of memory crises
I'm building a program which interfaces with a device which runs its own internal web server. I communicate with the device via a web API.
Basically what happens is that a GUI is presented to the user, where the user can make certain modifications to the device. These changes are communicated to the device, and results are returned through XML. The device needs to converse with the program in the background more or less continually (say every 15s or so) to update certain values to the user.
My structure that I'm envisioning is something like this:
UI - Main - Networking - XML Parser.
I'm looking for advice on how to manage these. I understand the UI thread should be separate to provide a smooth experience to users. I also understand that the networking should be at least an asynchronous task. I'm not so sure about how to handle their interaction, and make sure things are happening smoothly and effectively.
My idea is that Main will handle passing data around, telling the networker to send specific messages or changes, passing the returned XML to the parser, and then passing the parsed values to UI for handling.
I'm curious though for advice beyond that.
Have a look at creating a service that is created with your Activity. Without knowing the details of your plan, a Service looks like the optimal solution to perform all the heavy work.
UPDATE:
You could have the calls to web API run in a Service and, when needed, update the UI through an interface. You would have to instruct the Service to run on its own thread, so thread safety is an issue, but less trouble in the long run than using an AsyncTask.
Have a thought about using Google C2DM.
In your case,
Pros -> Less battery use, coordinated network traffic, Don't have to run a continues service and doesn't have the potential of being killed when the device runs out of resources.
Cons -> You have to post the results manually back to your internal server, and server should know which request the device is replying to. Communication is disconnected and may not be real-time. Requires a google account on the device and Google market.
Problem
Throughout my app I need to download files. In some cases I only need one-way communication, basically communicating with the Activity that a download has finished. In other cases, I need to be able to communicate to the background process to cancel the download, then relay back to the Activity once that task has been complete (two-way communication).
Stipulations
In all cases, a download is only associated with one Activity, so a Service seems unnecessary since I don't need to keep a download running in the background while the user does other things. The user is always blocked while the download is occurring. The download process should be Activity-independent (not specialized for one Activity...reuseable). It would be ideal to have one solution that meets all requirements.
Use cases
The two cases I have right now are as follows:
A user is shown a ProgressDialog while a file is being downloaded. Once the file completes downloading, the user proceeds to the next Activity. Progress does not need to be shown.
A user is shown a ProgressBar while a large file is being downloaded. There is a Cancel button to abort downloading the file. Pressing the Cancel button should signal to the background process to abort downloading the file, then inform the Activity once that action has been performed. Progress needs to be shown while downloading the file.
What I've tried
My original implementation was a separate class, ran in a thread, that passed in a Context that would broadcast progress. This allowed communication from the background process to the Activity, but not vise-versa.
I attempted a Service, but from various articles I read, determined my needs did not justify a Service, as the user needed to be blocked while the download was occurring. I had never implemented a Service before, so I also ran into communication problems (probably poor implementation).
What would be ideal
A two-way BroadcastReceiver. Is that possible? I like being able to register for a BroadcastReceiver if I want to get feedback from the background process, or not if I don't care. I already have a method in a class that takes in an InputStream and a File and makes the transfer, so that method is being reused everywhere that needs to download a file right now.
What you want to do is use an AsyncTask. Read these here on Stackoverflow:
Download a file with Android, and showing the progress in a ProgressDialog
and
Cancelling file download with httpclient and asynctask
Besides AsyncTask, you can also use Loaders.
They do pretty much what you need to do and I think they are available since android 1.6 with android compatibility package [related post]. I think this is your best option :)
I have a task which I need to run in the background in my Android app. It reads data over the network and populates a database. It can take several minutes to run.
Once it's started, it needs to complete successfully without interruption. (Otherwise I'll end up with a broken half-populated database.) I realise I can never guarantee it will always complete, but I want to make it as hard as possible for the system to kill off this task. For safety I guess I will have it populate a temporary database, and then only swap out the old database for the new one on successful completion of the import.
It's a modal operation; it does not make sense for the user to be interacting with the app while the import is in progress.
My first attempt is using an ASyncTask with a Progress dialog to achieve the modality, but this obviously breaks the "don't interrupt" requirement. I could work around the screen-rotation issue with ASyncTasks, but I don't think that goes far enough.
At the moment I'm not sure if this should be an ASyncTask, a Service, an IntentService, some combination of these, or something else entirely. Can you help me decide?
I'd run it as a service and additionally I'd also have a clean SQLite DB on my server populated with the data the clients are going to retrieve so I can generate a kind of signature. Have the clients check for the correct signature of the DB. If the signature is not matching the servers signature then reinitialize the database filling process.
This is just an idea tho. I have no idea whether it'd be possible with what you are trying to do or not.
You are better off with services in that case. The Android runtime will leave it alone working as long as enough memory is available. In the case it kills the service, you can save the state in a bundle, and the system will restart the process as soon as possible, so you can resume the process, if possible for your solution:
Android Fundamentals, Service Section
Then it is easy to communicate with the service, like showing the progress/ notifications etc, using a handle registry like proposes by Mark Bredy in his Android Service Prototype
I'm designing an android app which will need to do the following steps:
user pushes a button or otherwise indicates to "sync data".
sync process will use REST web services to move data to and from the server.
the data will be stored locally in a sqlite database.
the sync process should provide status updates/messages to the UI
the user should not be allowed to wander off to other parts of the application and do more work during the sync process.
The first time the sync process runs, it may take 10-20 minutes.
After the initial sync, less data will be transferred and stored and
I expect the process to take 1-2 minutes or less.
I've been doing a lot of reading about android's AsyncTask and various examples of using a Service ... But I don't fully understand the design considerations and trade-offs of choosing one design over the other. I currently have my demo project stubbed out using an AsyncTask. After watching (most of) Developing Android REST client applications: http://code.google.com/events/io/2010/sessions/developing-RESTful-android-apps.html# I'm left confused the design patterns described here feel overly
complex, perhaps because I just "don't get it" yet.
I come from a java, spring, web and desktop application background. Thinking and designing in terms of a handheld device is quite new to me. (What happens when the screen layout is changed? What happens when the phone rings while I'm running a sync?) Taking 2 steps back, if the initial sync IS going to be such a long running process, is there a better way for me to think about the problem->solution, the user experience, the user expectations of an application running on a phone?
Would love to hear from some more experienced android developers out there who have already wrestled with these questions.
In my opinion this is the most tricky/hard part of a mainstream/average Android development. For instance on BlackBerry this is IN TIMES easier.
Definitely you need to use a Service.
AsyncTask does not suit, because it is tightly "bound" to your Activity via a Context handle (otherwise you would not be able to update UI of the Activity from your AsyncTask). However an Activity can be killed by OS once the Activity went in background. An example reason of going to background can be an incoming call - user switches to Phone application so your Activity becomes invisible. In this case (depending on the current RAM state) OS may decide to kill one of the background (invisible to the user) activities.
Some devs workaround this by arranging a static stuff for having a long-running actions inside of. Some recommend to use Application instance. This is because static stuff and Application exist while the whole app process exists. However those are incorrect workarounds. Processes in Android are also may be killed when OS decides it is time to. Android OS have its own considerations about what it can kill and in what order. All processes are devided to 5 levels of "killability". Here is the doc where those levels are specified. It is interesting to read there:
Because a process running a service is
ranked higher than one with background
activities, an activity that initiates
a long-running operation might do well
to start a service for that operation,
rather than simply spawn a thread —
particularly if the operation will
likely outlast the activity. Examples
of this are playing music in the
background and uploading a picture
taken by the camera to a web site.
Using a service guarantees that the
operation will have at least "service
process" priority, regardless of what
happens to the activity.
Your Activity where users initiate a long-running action should show a ProgressDialog to make sure user does not do anything else while the action is running. The guide is here.
Also, you'd most likely want to use the NotificationManager for notifying the user about your long-running action completion (or failure) if your Activity is currently invisible. Here is the NotificationManager info to start from.
There are multiple considerations that you must weigh in order to best decide how to approach your situation. It sounds like you need a good comparison between the two approaches... So here is a list of similarities, and differences and additional considerations that must be taken into account when working on a handheld device.
A Service is a part of your Application that has no UI. It may be called by a UI(Activity) to be started, or may be started by any other component of your Application. When developing, you have the freedom to place it on a different thread, or even run it in a different Task or Process. This allows you to ultimately separate it from your UI. Additionally, you may start the Service to run independently (startService) or bind your activity to it (bindService) depending upon your needs. By using custom Handlers, you can set callbacks to update the UI with your progress. A Service does not necessarily end if a User changes Activities, but may be ended at ANY time by the OS.
A AsyncTask is always instantiated from the UI thread. It only allows specific callbacks, but simplifies the process of multi-threading for the purposes of relatively short transactions (as compared to dedicated separate threaded services) that are inherently tied to actions performed by an Activity. Whenever a User changes Activities, the AsyncTask is put on "pause" and may even die because there is no UI thread for your Activity any longer.
The thing that I would be most concerned about is if the app is going to take 10-20 minutes the first time, I would ASSUME that the User will either change tasks temporarily or set the phone down until it completes (which can cause all of the same complications if the phone sleeps). Given this consideration, a threaded service bound to your activity may be your best choice. To protect your UI, I would make a Progress Dialog for your Activity that receives your progress callbacks. This limits user input in YOUR app and allows your service to continue the way that it needs to. Then override the Activity onResume to check the status of your Service and if it is running. Then you can reset the Dialog immediately.
Given that this is my preferred method, I would also take into account that the OS may kill the App at any time anyway. So make sure to have some way to detect an incomplete or partial sync. Then you may resume automatically when your Activity or Service restarts.
With AsyncTask if the user goes to another Activity you can't transfer that object to the other Activity so it dies. There are tricks you can play when say the user rotates the screen or something like that, but that doesn't extend to general purpose destruction. AsyncTask can randomly die.
Google Sync is run as a Service in the background because syncing can take a while to complete. You might need to follow their path and create your own sync service that you can communicate with. Here is some thoughts how to accomplish that:
http://mylifewithandroid.blogspot.com/2008/01/about-binders.html
You can definitely communicate between Service and Activity, but it's tricky to do it right.
The choice is mainly dependent on the app design. Since both AsyncTask and IntentService stands their ground, what you may want from the app(user experience) is more important and then choose either or both. Some scenarios are mentioned below (mostly what I experienced while developing apps)
Assume apps that have feeds pages - where more than one api calls are made to make the page presentable ( /getFriends, /getDates, /getPictures etc.) you can warp all such api calls to a single AsyncTask with executor which is multithreaded and the sequence of execution doesn't matter. In contrast to IntentService which runs all calls in sequence in a single worker thread. For a high end device with multi-core the call from AsyncTask is more effective. And if you start the AsyncTask on UI thread then updating IU is a piece of cakes(read less boiler plate code). And even if an user leaves the page, with intelligent use of not holding on to the context the app doesn't crash.
Assuming you are trying to write an app which doesn't need the user to be on view/activity/fragment and the total execution time to show something is not mission critical (assume sync service or user notification/alarm) then IntentService is a better choice. (no hassle to start Asynctask on UI thread so that you don't need to write a Handler to force changes on UI etc. etc. and less boiler plate code)
From my experience - write small app for both and compare the pros and cons to get a better idea. (p.s I'd suggest take a look at the iosched app from google to get a better idea - they use both Asynctask and IntentService)
I tend to prefer the IntentService + BroadcastReceiver combo because they give you a really strong degree of control
You definitely have to make sure the UI is running if you are updating something on the screen. ASyncTask crashes were at once reported to be one of the top causes of Android crashes. This can be avoided by keeping some sort of "activityIsAlive" variable and skipping or delaying a UI update if the activity is dead.
The IntentService + BroadcastReceiver combo is a little more resistant to the crash because most tutorials tell you to shut off the BroadcastReceiver onPause or onStop. If you do not do this, again you'll have to turn off the UI update. There's a runOnUiThread command somewhere that will help you do UI updates.
The IntentService + BroadcastReceiver combo is also more extensible. You can create functions and extend BroadcastReceiver to make a more elegant REST processing solution. However, it does require more plumbing vs an ASyncTask
If you do delay the UI update, you may be able to rig it on OnWindowFocusChangedListener. When that function receives true, it means that the UI is alive.
tldr; Make sure the Activity and/or Fragment is alive before updating the UI if you are running something in the background
2015 Edit: check out Loaders as well. A little harder to grasp because there's a lot going on behind the scenes