I need help designing a solution to a problem specific to long running background tasks.
Background:
I have an app with activity that displays a list of files.
The files can each be downloaded. Each downloaded file can have an update.
The updates, if any, are fired as notifications with update now button. The app has an activity that shows the updates for each file.
Clicking on update now in either place triggers a background job downloading the file and update the progress in UI in both the places (depending on where the user is).
The user can update/download a max of 4 files simultaneously.
Design:
I have a GCM setup with WakefulBroadcastReceiver, that starts a IntentService to notify any updates.
The update/download is a Runnable - DownloadRunnable.java
A singleton class, MyDownloadManager has a static method startDownload() that starts the DownloadRunnable with a specific url.
Problem:
How do I update the progress in both notifications and activity while downloading the update?
How do I extend the design to run concurrent downloads and update progress to the corresponding item?
I would move the download task into a service.
I would not implement it myself, instead I would use the DownloadManager System service, see doc and usage example.
In your UI you can query the download status inside a background thread, see this SO question: Show Download progress inside activity using DownloadManager. Different to the solution I would use an AsyncTask instead.
This allows you to perfom downloads in parallel. In the activity you can show the current progress by polling in a background thread, but I am not sure what you mean with the notification? The DownloadManager shows a notification when starts with downloading.
Your downloads will be much stabler instead of using an own implementation, since DownloadManager can deal with connection loss and will perform a retry.
I would suggest to use Android's DownloadManager. This is the Download manager that the whole OS uses. U'll receive broadcast when the download is completed using ACTION_DOWNLOAD_COMPLETE.
Try this tutorial:
http://blog.vogella.com/2011/06/14/android-downloadmanager-example/
Related
I'm working with realtime database where I want my activities to run even no one is using the app.
swipeRefresh.setOnRefreshListener {
// code
binding.swipeRefresh.isRefreshing = false
}
From the above code, the user needs to swipe to refresh, I want it to be the same but in background and it does itself.
That means the activity is like a 'refresh' in the background every five seconds.
It's not possible to keep an app running while it's not being used. Android app processes will be killed by Android when the user is no longer using the app, and this can't be prevented. Android does this to save resources and allow other apps to run when they are being used. I suggest reading the documentation to understand how it works.
Your app should isntead simply query the database again when it's launched and rebuild the UI.
I'm attempting to add a MediaBrowserService for Android Auto to an existing media-player app. The app has a single activity which manages the MediaSession, Callbacks and related state. It has been set up so that it emits events, which the background MediaBrowserService consumes and uses to build its content tree.
This all works fine when the flow is like:
Start my app -> Start Android Auto -> Browse media
However, it falls flat on its face when the flow is:
Start Android Auto -> Browse media
...as in, when the app is not started and running in the background prior to when Android Auto is launched.
The problem appears to be that although my MediaBrowserService will be automatically launched by Android Auto, it does not create a corresponding instance of my app's Activity when it does so (which means no events to inform the MediaBrowserService, and consequently no content available in Android Auto).
Ideally it seems like the MediaBrowserService needs to be able to check and see if the app's "main" Activity is running, and spawn a new instance if/when it is not. But not sure if that's possible, and it tends to feel like it's the wrong approach to take here.
What's the correct way to work around this issue? I don't want to replicate all of the app's MediaSession handling and playback-related code in the MediaBrowserService implementation. That should be kept as lightweight as possible. Is there a way to ensure that the app's Activity is always running whenever the MediaBrowserService is active?
The answer to this was refactoring. Lots and lots of refactoring.
In a nutshell, Android expects Activities to be used to fill a particular architectural niche. Specifically, the niche where you're displaying an interface to the user via the device's screen. Other use-cases, such as having a 'headless' Activity running in the background, appear to be neither expected nor supported.
Thus the answer was to take all of the app's playback-related code out of the Activity, move it into a background Service, and provide an API for passing on the relevant commands (and receiving data, state updates and so on) either from/to the foreground Activity (if/when the user is interacting with the app's UI) or from/to the MediaBrowserService (if/when the user is interacting through Android Auto's UI). Starting the service is something that can be easily done from either context, if/when needed.
That appears to be the solution. It certainly can be tedious if you've got a nontrivial existing codebase you're working with. Far better to anticipate this sort of issue, and architect your app accordingly from the start; keep things that aren't directly pertinent to your app's UI outside of your Activity implementation(s).
I have a use cases (which might appear as a very common use case). I want to download some files from my server and show the progress on a Fragment. For implementing the download part, what is the prescribed way? I have two ways in my mind by which we might implement this:
Using an IntentServicein the background and downloading all the files there. The service would sends out broadcasts to update the UI on my Fragment.
OR
I use the design pattern mentioned in this url. Here, the background task is run using a separate fragment and using setRetainInstance(true), so that we ensure that the process is still running in the background and is not restarted once the activity gets started due to configuration changes.
I see both of the above as possible solutions in case of downloading files. But, which one is a better solution. If one is better than the other then what are the scenarios in which the other solution is used?
I'm trying to implement an android app where I can send commands to a server that controls a robot. The problem is quite "simple": I would like to keep a connection and communicate with the thread-service-task to send messages to the server, and get the responses to update UI and keep the user with the related information from the robot sensor.
So, what should be my decision? I know its probably duplicated. But I didnt find my same problem, cause I want to extend the question:
Is there any way to run a background process on an activity, change activity and keep it going? (Activity or fragment, I would go for fragments in the future).
Thanks in advance for any help!
The best solution for this is probably a Service.
A very good article on Services, including how to communicate with a background service via either Intents or broadcast events can be found at http://www.vogella.com/tutorials/AndroidServices/article.html
One typical model for your situation is to use:
Service for long running communication (taking "orders" from a queue
BroadcastReceiver to be notified about asynchronous events handled by Service
Activity to handle UI
One reference to consider looking at is here
Here is a Reference Code that uses an Android App , Arduino to Control a Bot. You can see its Structure thats what i have used in my robot as well. AsynkTasks wont be a good option in this aspect. Using a Service is a goodIdea for Long Running Communication
https://code.google.com/p/mover-bot/
Here is a Live Demo of This Android Controlled Robot.
Mover Bot
Do your work in Background and notify the result to UI thread.
Go through this for more detailed overview.
AsyncTask
It is a helper class around Thread and Handler for making threading and easy for you. Just do your task in background and publish result in UI thread.
http://developer.android.com/reference/android/os/AsyncTask.html
Thread
Use basic concept of threading in java, create your own thread pool do your task and publish your result in UI thread using handler. Mainlly, used when you need more longer running task while your ui is visible (for simple background task asynctask). It will take time in implementation but provide you more control over task management.
https://developer.android.com/training/multiple-threads/create-threadpool.html
Service
Services are used when you have more longer running task and also you want your ui to be independent from your task.
Here in your case i would prefer you should use a service for communication and use binder or broadcast manager for reflecting change in UI.
http://developer.android.com/guide/components/services.html
I am having an AsyncTask to play media and I am using a Service for it. The problem is that when my AsyncTask (in the Service) is running, another part of the app that I used an AsyncTask to communicate with web server is not working until playing finishes. (Playing media not buffering it).
I have already tried removing the AsyncTask and using a new Thread but I can't update the UI in this mode.
What should I do to fix it?
You probably don't want both an Asynctask and a Service. Services are designed for long running background tasks. 'Asynctask's are designed to easily launch a new thread, perform some long-running task, and then send data to the UI thread.
There is only one UI thread, so, if you're updating the UI, you are blocking user interaction.
If you're streaming music, you would probably want a Service to spawn a new Thread so that it can constantly be downloading songs in the background. If, for example, the user presses a button and it loads a video, you might instead want an Asynctask to perform the download.
Generally, one might use an Asynctask to download a media file on user request (or, if you're downloading in the background, a Service might be used for this). Then the data is exchagned and the video file can be played using Android's MediaPlayertools:
http://developer.android.com/guide/topics/media/mediaplayer.html
Remember that, unlike with an Asynctask, creating a Service does not automatically mean that you have created a new Thread. Services can run on the UI thread. Generally speaking, though, most use cases for Services require that they launch a new Thread to do their work.
Finally i used a service and a handler to create post delay