I need to record uncompressed audio from the microphone continuously (hours) in an Android app, process the audio and visualise the result in a plot. If the app loses focus, the plotting can (and should) stop, but the recording and the analysis shouldn't.
I'm not sure I got the right steps, so this is the implementation I have in mind:
A RecordActivity handles the view, in particular plotting the results as they arrive and handling the button presses. A record button starts a RecordService
A RecordService service initialises an android.media.AudioRecord and on its AudioRecord.OnRecordPositionUpdateListener reads in the buffer, saves it to file and analyses its contents. The result of the analysis is stored.
The RecordService uses a PendingIntent to communicate the results of the analysis to the RecordActivity, which updates the plot.
When the users presses the stop button, RecordActivity kills the service by calling stopService.
My questions are:
Is it right to use a service for this or can I just use an activity?
Is it right to use a started service rather than a bound one?
What parts of this process should be handled by a different thread (or even process)? The AudioRecording? (The analysis obviously depending on the requirements). The entire service?
Should the service being a Foreground service?
In general, is this structure correct?
A Service is a good solution, what I don't understand is why you're using a PendingIntent. Maybe you should consider using LocalBroadcast and normal Intent
In this case, since the service is bound to the lifecycle of the Activity, I suggest to use a bounded Service :)
Well...it depends. If the AudioRecording implementation has its own thread (as I guess in Android), then it's not strictly required to use a thread. But if you write many datas to filesystem, it could be better to start a thread inside the service and handle your logic there (remember that services are not thread)
It depends by your design. If you pause your Service logic when the app goes to background, it's not necessary. But if you need your service even when the app goes in background, then it's better to use a foreground Service
In general, I believe it's a good solution
Related
I know this look like tons of question around SO. But it's not (although I can also be wrong).
I have a long running Service (running in a separate thread using blutooth socket pooling for data in a OBD2 adapter every 5 seconds).
This Service is running in the same process and is a Foreground Service.
The user start this Service through an Activity. It then connect to the Bluetooth device and start pooling and saving data to a SQLiteDataBase.
The user can then minimize the activity and do other stuff.
When he returns (if ever, he can stop the service through a notification area button) to the application it checks if the Service is running and if so, it starts another Activity which show the data that is being pulled from the OBD2.
My question is, between this visualization Activity and the Service should I use and by this I mean the recommended or the right one:
LocalBroadcast? This is actually what I am using. Every time the service pull some data, it sends a broadcast with the data everytime it was pulled. Then in the onReceive method call runOnUiThread to update the respective View.
Messenger? As far as I know (never used it) I should send a Messenger from the Activity to the Service (much like a Handler) and in the Service it should send the Messages with the data pulled. But from this I would get a RemoteObjectException if the Activity was destroyed (like I said, the user could just minimized the activity and then it got GCed). So, I would probably need a way of sending the Messenger to the Service every time the Activity gets created and check if it's ok to use the messenger form the Service every time (if that's even possible, I've never used this).
BindService? Should I bind to the service when I open the Activity and then get the data directly from methods in the Service? But this would probably mean I would have another thread in the Activity gets this data from the Service every time, right?
Handler? (for a moment now I realize don't know the difference between Messenger and Handler, should it be that "use Messenger when Service runs in another process and Handler otherwise)
I've seen/read a lot of answers here in SO and through the web in general.
But in the end I don't see a ultimate answer for my case. But I'm sorry if this is just because I couldn't figure it out.
Thanks in advance!
EDIT: forgot to mention, I would rather make use only support libraries and android framework stuff, I'm still learning Android and I want to understand what's happening within its own classes.
I am finishing my current activity using finish(). This is calling onPause automatically. I want to finish activity without onPause being called. My activity is running a song service so i want song to stop when app is in background but dont want it to stop when user goes from one activity into another in my app. I cant do stopService and startService in between activities because then there is a momentary lag in between the sounds.
A Service is an application component that can perform long-running operations in the background and does not provide a user interface
google docs
The background Service is agnostic of which Activity is running or any discontinuity between them.
The two types, "bound" and "started" are supposed to have different persistence characteristics but in practice (not stress testing) I find the bound Service does not clobbered for lack of system memory and is much easier to implement (despite tutorials claiming otherwise). It uses some IPC abstraction that appears as though it is being directly invoked from the Activity. The same can't be said of the "started" variety (unless it is also bound) which is IMO a closer approximation to the traditional service I would associate with web-servers (or anything that is already going to be experiencing not insignificant delays- such as due to network transmission).
(Lecture over) I see you are calling finish(). You need some way to shut down the Service from your Activity. Just make sure to branch aways from doing so when not intended. Code would be helpful but I can assure you this is how media players work.
I want to achieve following goals:
Record Audio
Send Audio to Server
Play Audio
I know that First 2 tasks are possible by Using Service as I've done that in one of the previous apps but when it comes to playing an audio file, it needs to be triggered from an Activity.
Because accessing Activity from Service can be achieved by using BroadcastReceiver but what about accessing method of a Service from an Activity?
So, now comes the question: Whether to go for Service itself for Playing the audio also(triggered from activity) OR to use IntentService.
Documentation says,
No easy or direct way to interact with user interface directly from IntentService.
and
Any tasks started using IntentService cannot be interrupted
I may want to stop recording ant time and play it any time.
Which would suit t he requirement best --> Service OR IntentService ??
Any suggestions will be highly appreciated.
I would use a Service rather than an IntentService for what you need.
In particular, use a bound Service which allows two-way communication between the Activity which binds to it and from the Service to the Activity.
The IntentService class is designed for one-shot operations using its own worker thread, once the work on the thread is complete, the thread terminates and the IntentService calls stopSelf() to terminate itself. This means any user interaction between the user (via an Activity) and an IntentService is problematic.
A bound Service on the other hand will exist until it is either explicitly stopped or untill the last bound component unbinds. This allows for longer term interaction.
For playback, the fact a Service runs on the UI thread isn't an issue if you use something like MediaPlayerwhich handles its own thread for playback purposes.
Further to this, if you use a bound Service, MediaPlayer and MediaController, you can control play, stop, pause, seek etc from the Activity.
EDIT: For further information see... Bound Services
I would like to create an Android application with real-time monitoring functions. One monitoring function is to audit the audio flow. The other function is to interact with a peripheral sensor. These monitoring functions can be triggered by others.
Besides, in order to save power consumption, the audio function will be running in a polling mode, i.e. sleep for a certain amount of time and wake for a certain amount of time.
I am considering how to design the Android application.
Whether to design the audio function as a Service or an Activity?
The problem is if it is designed as an Activity, the audio function will be off if screen turns off after a period of time.
How to design the polling function? Use an AlarmManager or a inner-thread with Timer?
My goal is to save the power consumption as much as possible. Thanks.
I would recommend following
a) Use a Service. Activity is short lived entity (it works only while it's on the screen)
b) Make the service foreground (read this: http://developer.android.com/reference/android/app/Service.html#startForeground(int, android.app.Notification). This will decrease the chance that system will kill your service
c) In the service, start a thread and do everything you need in the thread.
d) If you want execute periodically, just do Thread.sleep() in the thread (when Thread sleeps it doesn't consume CPU cycles).
I believe c) and d) is preferable to AlarmManager.
Here is piece from documentation (http://developer.android.com/reference/android/app/AlarmManager.html) : "Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler."
Since your application running it's better to have some permanently running thread and execute something on it. Generally speaking Handler, HandlerThread, MessageQueue are just convenience classes for more complex message handling and scheduling. It looks like your case is quite simple and usual Thread should be enough.
Concurring with Victor, you definitely want to use a Service, and pin it into memory by calling startForeground()
However I suggest you look into utilizing the built in system Handler ; place your functionality in a Runnable and call mhandler.postDelayed(myRunnable, <some point in future>) ; this will allow the android framework to make the most of power management.
That's a service.
And you may want some extra robustness: the service can be killed and NOT restarted later, even being a foreground service. That will stop your monitoring.
Start your service from the UI. If you want the service to survive device reboot, also start it from a BroadcastReceiver for android.intent.action.BOOT_COMPLETED.
Create a thread in the service as described in other answers here.
Additionally, use Alarm Manager to periodically start your service again. Multiple startService() calls are OK. If already running, the service will keep running. But if it's been forgotten by the system, say, after a series of low resource conditions, it will be restarted now.
Schedule those alarms responsibly: to be a good citizen, set the absolutely minimal frequency. After all, Android had some good reasons to kill the service.
With some services, even more steps may be needed, but in this case this approach seems to be sufficient.
I have got a list of Music Titles in a ListView.
I can click on each item to play the Music through a MediaPlayer in a Service.
Now I want to implement 2 Features:
Music ProgressBar which is showing the current position in the song
The service shall continue playing when Song is over with the next song in the list
So how can I update the UI from a background service?
(I know there are some solutions on Stackoverflow but they seem to me a little bit of an overkill to send a Broadcast each Second from the Service i.e.)
Do I have to use Binding? What is the benefit of Binding?
Right now I just start the service with an Intent (startService(intent)) which contains the Song path.
What about the 2nd question? How can I do that?
I guess you built the service by yourself. Thus you know how it is built and how to get access to a mediaPlayer reference. What you need to do is to transform your service into a bound service. Maybe you will want your service to be started via startService (otherwise the bound service won't survive your activity), but afterwards, you will have to bind to it from inside your activity.
Once you are bound, you will get a IBinder (that you will define) and will be able to export the mediaPlayer reference to the bound activity through this IBinder. Afterwards, everything is quite straightforward, plug a listener on the media player and update your UI (in the UI thread !).
Also, you will need your service to be put forward.
I was solving very similar issues, however, I did the mixing/playing part myself.
The code for the android player-service part is at -github-
For communication between application and the service (it should be a foreground service with a notification in status bar, otherwise it can be silently killed / paused quite frequently) I experimented with different approaches and ended up with
Activity -> Service - using Messenger
Service -> Activity / anything - using BroadcastReceiver
The code on github is not too big (less than 500 lines total including imports) to give you an inspiration...
Btw. it also shows a service binding that does not kill service on activity exit.