Service OR IntentService playing audio after recording - android

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

Related

How to prevent Service from being destroyed before it finishes its work

How do I keep a service from being destroyed before it finishes its work? I'm using WakefulIntentService to insure that the device doesn't fall asleep while the work is being done. But I'm not sure this will even work. In one particular place I'm creating a MediaPlayer to play a sound, but after working a few times I start getting exceptions about the thread being dead, and looking in the log I see that the service's onDestruct function is being called before the media player has a chance to do its work.
In one particular place I'm creating a MediaPlayer to play a sound
Any form of IntentService is not suitable for that scenario. An IntentService is destroyed once onHandleIntent() returns (or, in the case of WakefulIntentService, when doWakefulWork() returns). Do not do anything in an IntentService that will last beyond the onHandleIntent() call.
Instead, use a regular Service, where you manage your own WakeLock, releasing it and stopping the service when the media playback is completed (via an OnCompletionListener).
(and, FWIW, I would recommend JobIntentService over my WakefulIntentService, for scenarios where a wakeful IntentService is the appropriate solution)
You can use a Foreground Service but the trade-off will be you will have to show a foreground notification in Android status bar, OR you can use JobIntentService which is same as intentservice but instead of running the service directly it uses Jobs to run the service.

Recording audio continuously and updating the view

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

How to self stop a service started with BIND_AUTO_CREATE?

There is some long processing that need to be completed, so I put it in a service. The activity must be able to connect to the service, show the user current results from the service. So I start the service with start Service and later call bind Service (with BIND_AUTO_CREATE) as in LocalService from http://developer.android.com/reference/android/app/Service.html#ServiceLifecycle. I want it to run until its job is done, and then self stop, even if client is still connected to it. (or determine the client to unbind) Is any way to do it with the sample LocalService?
I was considering passing a handler to the service so that it can send messages back to the activity, but I don't want the activity to get leaked. I am just getting used with services, so maybe I am misusing something.
EDIT: The workload consists of several threads, synchronized and run in parallel, so I guess is not a good candidate for intent service. Some data analysis is done in background service, and when the user restarts the activity that started the service, it should display some graphics according to current values computed by background service. All background processing is triggered at the beginning, and need only inspection later on, when activity connects to it. Android should not be able to stop the service. When the job is finished, the service should be able to terminate even if the activity is connected to it.
I just recorded a callback with the service. If the activity is not connected to service, it sets the callback to null. In this callback I call stopService() and then finish() on the activity. I am not sure that it is the best method, but it works fine for me.
If you want a service to be stopped when it is finished, I think what you are looking for is IntentService, they work as services, but run in another thread and when they are completed they dissappear.
Check this out
EDIT: NickT link is better, check that out! :)

Why do we need to create android service

This is very basic question but I am unable to figure it out because as I read that Service runs on main thread. So why do we need to create a Service? and because for intense CPU task we need to create Async task or thread in Service then why don't we create them in activity or application class?
I wanted to create a service which will continuously perform a set of task when it is started. I can't find any method in Service which will run in loop. Is there is such method? or do I have to create a thread in service to set a loop?
why don't we create them in activity or application class?
You can, but it depends of task you want to accomplish. The main characteristic of a Service is that it runs in background, decoupled from Activity life cycle.
Imagine the following situation, you are working on a Media Player application and would like to let the users play music, even when they exit the application, in background.
Now, if you put the media player logic in Activity, then when users will leave the app, the music will stop, as this will terminate the media player. That is not good, we want the music to continue playing in background when they leave the app. Well, in order to achieve this, you should put the playing logic in a Service.
Also, take a look over IntentService class, which provides its own worker thread, so you shouldn't define your own.
I can't find any method in Service which will run in loop. Is there
is such method?
No, there isn't. You either start the service again, or, create a loop inside the service.

How to communicate between Music Playback Service and UI Thread

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.

Categories

Resources