I'm building an app that streams music from a web server. The app has foreground service that uses a MediaPlayer for playback.
My code is based on this example: http://developer.android.com/guide/topics/media/mediaplayer.html
In the example, nothing is threaded except the prepareAsync() call. What confuses me is that when I read about the Service class I find this information:
"Caution: A service runs in the main thread of its hosting process—the service does not create its own thread and does not run in a separate process (unless you specify otherwise). This means that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 playback or networking), you should create a new thread within the service to do that work. By using a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with your activities."
The reason I'm asking is that the app some times (usually when loosing connection) freezes the UI when streaming audio. I totally understand that the UI freezes if the service is making CPU intense work, since the activity and the service runs on the same thread. But, should I expect the MediaPlayer to be this intense? That is, should it run on a separate thread?
Unfortunately, calling prepareAsync() is simply not good enough to avoid ANR prompts and your application hanging for a few seconds, especially if you're playing a file from the network. Your best bet is to put your MediaPlayer instance in its own thread, or at the very least execute intensive calls in a Handler (like mediaplayer.start()). I've been using MediaPlayer for over a year and I can tell you it definitely hangs after various calls, depending on the circumstances.
Could the streaming music be causing the main thread to stop until the music has finished streaming? This could be why it is slowing it right down.
I'm no expert and am currently learning myself, but it's worth thinking about.
No if you are doing any network transfer you should keep that in a thread, mediaplayer is not that resource intensive. Keep it on your activity.
Related
After reading around for hours, I am little bit unclear on how an Activity and a Foreground service can co-exists in an android app.
Taking example of a Music Player app -
I create an Activity for displaying the UI and controls for the music player, and the music player gets started into a Foreground service. Based on the articles I have read.
And based on this -
A service runs in the main thread of its hosting process—the service does not create its own thread and does not run in a separate process (unless you specify otherwise). This means that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 playback or networking), you should create a new thread within the service to do that work.
So, now at this time, if I have to perform any actions on UI in my Activity, why will I not see an ANR or any other kind of sluggishness, since the music and user actions are both happening on the UI thread ?
I was going through Bound Service in Android Developer website. I thought I understood the service enough but I just found another way of connecting service through Using a Messenger class especially for local service. There I got confused. Maybe I got the concept wrong.
Here is my understanding of Android Service. You create a service when
You want to do separate jobs in the background.
You want to make it a separate process.
You want to make it run in a lifecycle that's independent of the component that started it.
Confusion is the first item in the list, the definition of the background. Isn't the background a thread or process? I never thought that it can run on the main thread.
Here is the caution of service in the dev pages about.
Caution: A service runs in the main thread of its hosting process—the service does not create its own thread and does not run in a separate process (unless you specify otherwise). This means that, if your service is going to do any CPU intensive work or blocking operations (such as MP3 playback or networking), you should create a new thread within the service to do that work. By using a separate thread, you will reduce the risk of Application Not Responding (ANR) errors and the application's main thread can remain dedicated to user interaction with your activities.
Questions
Why does one choose to use service if the service function will anyway run on the main thread?
Do we have to write a service only to block ANR even if the time-consuming job is done in the main thread? Assume the service is only for my application.
Are there any practical cases or reasons to use a service as private and running in the same thread?
Application main thread is not always the UI thread. For example, when Activity is stopped, the onStop() is invoked, hence the UI thread is taken away from that Activity and moved to another Activity within the same or a different application. However it doesn't mean the application is no longer active, it can continue working in the background until it is closed either by OS or by user. Then who keeps it running in the background? It is the main thread and not the UI thread.
What are services
In Android, a Service is an application component that can perform
long-running operations in the background on the UI thread. By
background, it means that it doesn’t have a user interface. A Service
runs on the main thread of the calling Component’s process by default
(and hence can degrade responsiveness and cause ANRs), hence you
should create a new Thread to perform long running operations. A
Service can also be made to run in a completely different process.
Unlike Activity components, Services do not have any graphical
interfaces. Also Broadcast Receivers are for receiving broadcast
messages (broadcast, multicast, unicast) and perform short tasks
whereas Services are meant to do lengthy processing like streaming
music, network transactions, file I/O, interact with databases, etc.
When a Service is started by an application component like an Activity
it runs in the background and keeps running even if the user switches
to another application or the starting component is itself destroyed
Why use service
Services are given higher priority than other Background processes and
hence it’s less likely that Android will terminate it. Although it can
be configured to restart once there is ample resources available
again. You should go through the different processes and their
priority/important level in the documentation on processes and
threads. Assigning them the same priority as foreground activities is
definitely possible in which case it’ll need to have a visible
notification active (generally used for Services playing music).
Use IntentService if you don't want to fiddle with managing threads on your own. Otherwise, use AsyncTasks.
Please read this excellent article to understand more in detail and also read this answer.
Service basically runs in UI thread or main thread.But,if we are going to perform long running operations in service,we need to create a background thread and perform that task.
But why we have to use service?
Now let's think of Music Application.We need songs to be played continuously even if we leave music app.If we use activities,we can't achieve above requirement.So,service helps in these kind of scenarios.Even if the app is not in foreground, service keeps on running and we are able to listen to songs.This is why we use service even though it runs on main thread.
In short, Services runs on the background of the UI thread.
You can perform tasks like client-server authentication or write to a database where the tasks are done in the background with no graphical interface.
But if you're doing a really long processing tasks that could freeze the interface, you use a service on a separate thread.
eg of a Service on a separate thread is IntentService
I've built a music player which is running on a Service.
I'm preforming various actions as play, pause, next song, previous song etc through a binding to the service from my activity.
It works totally fine.
So to my question:
Is it ideal to put the service on a new thread? I know Service run by default on Main/UI thread.
If not, how do I know when to actually put something on a new thread? Can I put the whole Service instance on new thread or just a part of the code in the Service?
I guess this is called a long running service, shouldnt that be on a own thread to not block the UI?
When debugging I can see this in Logcat: I/Choreographer(691): Skipped 60 frames! The application may be doing too much work on its main thread...
That got me wondering too! :o
As my title says, I'm very confused about this!
You are right, Services are not threads (they do not create a different thread).
When started form an activity they would block the main/UI thread fi running long operations.
you can use IntentService - which start their own thread to perform background long running operations - but that would probably suits a download file task or long running calculation better than playing music.
note that IntentService creates and destroys the thread by itself (when the work is done).
Another option would be to create you own thread manually.
That said, I would consider this article:
http://developer.android.com/guide/topics/media/mediaplayer.html
It talks about a service in the foreground using startForeground() which adds a notification to the status bar, letting the user be aware of the fact that the service is running - as well as promoting the service so it won't get destroyed in case of low memory conditions (it could be - but it will probably be the last one to be closed).
the example is about running media player while taking the main thread blocking into consideration as well as handling system events to pause and play music as expected (using BroadcastReceiver )
Also note this:
http://developer.android.com/guide/components/services.html
Should you use a service or a thread?
A service is simply a component that can run in the background even
when the user is not interacting with your application. Thus, you
should create a service only if that is what you need.
If you need to perform work outside your main thread, but only while
the user is interacting with your application, then you should
probably instead create a new thread and not a service. For example,
if you want to play some music, but only while your activity is
running, you might create a thread in onCreate(), start running it in
onStart(), then stop it in onStop(). Also consider using AsyncTask or
HandlerThread, instead of the traditional Thread class. See the
Processes and Threading document for more information about threads.
Remember that if you do use a service, it still runs in your
application's main thread by default, so you should still create a new
thread within the service if it performs intensive or blocking
operations.
I have doubts when it comes to Services.
I know the service runs in the background, but I thought you necessarily needed to create a thread within the service, otherwise it would block the main thread and you would get an ANR error.
I thought I got it! But then I read this in the Android Developer guide:
…if your service performs intensive or blocking operations while the user interacts with an activity from the same application, the service will slow down activity performance. To avoid impacting application performance, you should start a new thread inside the service.>
The paragraph mentions "intensive or blocking operations", but doesn’t mention an ANR error, it mentions performance. So how a service works?
Supposing an Activity starts a Service. Does the Service run by default in the background of the main thread? Meaning that you can still use your activity while the service is running, but since your Activity and the Service are sharing the main thread’s resources, it would slow down the performance of your activity, and if Service is doing CPU intensive work, it could leave no resources for the activity to use, and eventually you would get an ANR error.
The best practice (but not necessarily, if the service is doing light work) would be to start a new Thread within the Service, now the Activity and the Service are using their own thread’s resources. Then you could close your activity, but Android keeps the service thread alive.
Is that it? Thanks =)
I thought you necessarily needed to create a thread within the service, otherwise it would block the main thread and you would get an ANR error.
Correct.
The paragraph mentions "intensive or blocking operations", but doesn’t mention an ANR error, it mentions performance.
Feel free to file a bug report at http://b.android.com to get them to improve this portion of the documentation. :-)
Does the Service run by default in the background of the main thread?
The lifecycle methods of a Service, such as onCreate() and onStartCommand(), are called on the main application thread. Some services, like IntentService, will provide you with a background thread (e.g., for onHandleIntent()), but that is specific to that particular subclass of Service.
and eventually you would get an ANR error.
Yes.
The best practice (but not necessarily, if the service is doing light work) would be to start a new Thread within the Service, now the Activity and the Service are using their own thread’s resources. Then you could close your activity, but Android keeps the service thread alive.
Basically, yes. Here, "light work" should be less than a millisecond or so. Also, some things that you might do are naturally asynchronous (e.g., playing a song via MediaPlayer), so it may be that the Service itself does not need its own thread, because something else that it is using is doing the threading.
is there any way to leave a thread in background when i close the app in android? I read about a Service but implementing it is too much than i need. Thanks
Hi, is there any way to leave a thread
in background when i close the app in
android?
That will happen by default. That does not mean it is a good idea.
I read about a Service but
implementing it is too much than i
need.
More likely, it is precisely what you need.
If you start a thread in an Activity, then fail to stop that thread, it will run forever, until Android terminates the process, since you have no way of stopping it. The only sort-of acceptable exception is if your thread stops itself, and then you have to be very very careful that it actually does terminate cleanly. On the other hand, you can arrange to stop a running Service whenever you need, from any Activity, and that Service can arrange to stop the thread, so you don't leak the thread indefinitely.
I strongly encourage you to implement a service that manages the thread.
Another reason to use a Service is that the platform will give the process priority to NOT be killed while it is in the background.