The purpose of using a Service is to have your code run on the background, you can do operations that don't require a user interface and even have your code run beyond the onDestoy() method of an activity. This is how music players allow you to listen to music even after you have closed the Application's Activity.
There are 3 types of services:
Foreground Service
Background Service
Bound Service
Why is Code B in a Service but Code A is not?
From the Bound services overview:
A bound service is the server in a client-server interface. It allows
components (such as activities) to bind to the service, send requests,
receive responses, and perform interprocess communication (IPC). A
bound service typically lives only while it serves another application
component and does not run in the background indefinitely.
In other words it allows communication with other applications or across separate processes. And that's the main reason the author would use the Service. It has nothing to do with performance.
About performance:
Code B does not account for performance.
From the Service overview:
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. You should run any blocking
operations on a separate thread within the service to avoid
Application Not Responding (ANR) errors.
So merely using a Service does not guarantee performance. In Code B we have the method startRecording(), which initializes MediaRecorder and sets some paramaters for the Recording. This doesn't not mean that this method will run as soon as the service starts. The Author has used a Bound Service, you can tell by the method:
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
Which means that any component that binds to it (such as an activity or another process can call its method startRecording() ). Please check the Bound Service link for more info. In the project this gets called from RecordViewModel.startRecording().
If you are worried about performance. Code B should start a new Thread inside startRecording(int duration). There are many ways to do it. Here is one:
public void startRecording(int duration) {
( new Thread( new Runnable() {
@Override
public void run() {
setFileNameAndPath();
mRecorder = new MediaRecorder();
mRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
mRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
mRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mRecorder.setOutputFile(mFilePath);
mRecorder.setMaxDuration(duration); // set the max duration, after which the Service is stopped
mRecorder.setAudioChannels(1);
mRecorder.setAudioSamplingRate(44100);
mRecorder.setAudioEncodingBitRate(192000);
...
}
}) ).start();
}
As for Code A the only thing happening there is the call to MediaPlayer.start(), which already starts a new thread internally.
From the MediaPlayer class source code:
public void start() throws IllegalStateException {
//FIXME use lambda to pass startImpl to superclass
final int delay = getStartDelayMs();
if (delay == 0) {
startImpl();
} else {
new Thread() {
public void run() {
try {
Thread.sleep(delay);
} catch (InterruptedException e) {
e.printStackTrace();
}
baseSetStartDelayMs(0);
try {
startImpl();
} catch (IllegalStateException e) {
// fail silently for a state exception when it is happening after
// a delayed start, as the player state could have changed between the
// call to start() and the execution of startImpl()
}
}
}.start();
}
}
If performance is of concern with Code A, then MediaPlayerHolder.loadMedia(String path) is where a separate Thread should be used.
So to answer your question. No, you do not need to run MediaPlayer in a Service. It depends on your requirements.
Regards