以下代码来自该项目。
使用该MediaRecorder
控件时可能需要很长时间,因此作者MediaRecorder
在服务中运行,您可以看到代码B。
播放音频也许也是很长时间的操作,所以我认为作者应该MediaPlayer
在服务中运行,但是为什么Code A不这样做?
代码A
public final class MediaPlayerHolder implements PlayerAdapter {
public static final int PLAYBACK_POSITION_REFRESH_INTERVAL_MS = 1000;
private MediaPlayer mMediaPlayer;
@Override
public void play() {
if (mMediaPlayer != null && !mMediaPlayer.isPlaying()) {
mMediaPlayer.start();
if (mPlaybackInfoListener != null) {
mPlaybackInfoListener.onStateChanged(PlaybackInfoListener.State.PLAYING);
}
startUpdatingCallbackWithPosition();
}
}
...
}
代码B
public class RecordingService extends Service {
public class LocalBinder extends Binder {
public RecordingService getService() {
return RecordingService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
public void startRecording(int duration) {
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);
...
}
}
使用服务的目的是让您的代码在后台运行,您可以执行不需要用户界面的操作,甚至可以使代码在活动的onDestoy()方法之外运行。即使关闭了应用程序的活动,音乐播放器也可以通过这种方式收听音乐。
有3种服务类型:
为什么在服务中使用代码B,而在服务中却没有?
从“绑定服务”概述中:
绑定服务是客户端服务器界面中的服务器。它允许组件(例如活动)绑定到服务,发送请求,接收响应以及执行进程间通信(IPC)。绑定服务通常仅在为另一个应用程序组件提供服务时才存在,并且不会无限期地在后台运行。
换句话说,它允许与其他应用程序或跨单独的进程进行通信。这就是作者使用服务的主要原因。它与性能无关。
关于效果:
代码不能说明性能。
从服务概述中:
注意:服务在其托管过程的主线程中运行;除非另行指定,否则该服务不会创建自己的线程,也不会在单独的进程中运行。您应该在服务内的单独线程上运行任何阻止操作,以避免应用程序无响应(ANR)错误。
因此,仅使用服务并不能保证性能。在代码B中,我们有方法startRecording(),该方法将初始化MediaRecorder并为Recording设置一些参数。这并不意味着该方法将在服务启动后立即运行。作者使用了绑定服务,您可以通过以下方法判断:
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
这意味着绑定到它的任何组件(例如活动或另一个进程都可以调用其方法startRecording())。请检查绑定服务链接以获取更多信息。在项目中,可以从RecordViewModel.startRecording()调用它。
如果您担心性能。代码B应该在startRecording(int duration)内启动一个新线程。有很多方法可以做到这一点。这是一个:
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();
}
至于代码A,唯一发生的事情是对MediaPlayer.start()的调用,该调用已经在内部启动了一个新线程。
从MediaPlayer类的源代码:
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();
}
}
如果代码A的性能令人担忧,则应在MediaPlayerHolder.loadMedia(String path)中使用单独的线程。
因此,回答您的问题。不,您不需要在服务中运行MediaPlayer。
问候
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句