在 Android Studio 的服务中是否需要 运行 MediaPlayer?
Do I need to run MediaPlayer in a service in Android Studio?
以下代码来自project.
可能是我用MediaRecorder
控件的时候操作时间比较长,所以作者运行 MediaRecorder
在一个服务中,可以看到代码B.
可能播放一段音频也是很长时间的操作,所以我觉得作者应该运行 MediaPlayer
在一个服务中,但是代码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);
...
}
}
使用Service的目的是让你的代码运行在后台,你可以进行不需要用户界面的操作,甚至还有你的代码运行 ] 超出 activity 的 onDestoy() 方法。这就是音乐播放器允许您在关闭应用程序 Activity.
后仍能听音乐的方式
有 3 种服务类型:
为什么服务中有代码 B 而代码 A 没有?
来自绑定服务概述:
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.
换句话说,它允许与其他应用程序或跨不同进程进行通信。这就是作者使用该服务的主要原因。与性能无关。
关于性能:
代码 B 不考虑性能。
来自 Service 概述:
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.
所以仅仅使用服务并不能保证性能。在代码 B 中,我们有方法 startRecording(),它初始化 MediaRecorder 并为 Recording 设置一些参数。这并不意味着此方法将在服务启动后立即 运行 。作者使用了Bound Service,可以通过以下方式判断:
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
这意味着绑定到它的任何组件(例如 activity 或其他进程都可以调用其方法 startRecording() )。请查看绑定服务 link 了解更多信息。在项目中,这是从 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 class 源代码:
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(字符串路径)应该使用单独的线程。
所以回答你的问题。不,您不需要 运行 服务中的 MediaPlayer。这取决于您的要求。
此致
以下代码来自project.
可能是我用MediaRecorder
控件的时候操作时间比较长,所以作者运行 MediaRecorder
在一个服务中,可以看到代码B.
可能播放一段音频也是很长时间的操作,所以我觉得作者应该运行 MediaPlayer
在一个服务中,但是代码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);
...
}
}
使用Service的目的是让你的代码运行在后台,你可以进行不需要用户界面的操作,甚至还有你的代码运行 ] 超出 activity 的 onDestoy() 方法。这就是音乐播放器允许您在关闭应用程序 Activity.
后仍能听音乐的方式有 3 种服务类型:
为什么服务中有代码 B 而代码 A 没有?
来自绑定服务概述:
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.
换句话说,它允许与其他应用程序或跨不同进程进行通信。这就是作者使用该服务的主要原因。与性能无关。
关于性能:
代码 B 不考虑性能。
来自 Service 概述:
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.
所以仅仅使用服务并不能保证性能。在代码 B 中,我们有方法 startRecording(),它初始化 MediaRecorder 并为 Recording 设置一些参数。这并不意味着此方法将在服务启动后立即 运行 。作者使用了Bound Service,可以通过以下方式判断:
@Override
public IBinder onBind(Intent intent) {
return myBinder;
}
这意味着绑定到它的任何组件(例如 activity 或其他进程都可以调用其方法 startRecording() )。请查看绑定服务 link 了解更多信息。在项目中,这是从 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 class 源代码:
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(字符串路径)应该使用单独的线程。
所以回答你的问题。不,您不需要 运行 服务中的 MediaPlayer。这取决于您的要求。
此致