管理 MediaPlayer 状态和资源
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
本文档介绍了两个可能存在陷阱的方面。
管理状态
MediaPlayer
是基于状态的。也就是说,它具有内部状态,您在编写代码时必须始终注意,某些操作仅在播放器处于特定状态时才有效。如果您在错误的状态下执行某项操作,则系统可能会抛出异常或导致其他不良行为。
MediaPlayer
类文档中的状态图说明了哪些方法可将 MediaPlayer
从一种状态变为另一种状态。例如:
此时,如图所示,您可以通过调用 start()
、pause()
和 seekTo()
等方法在 Started
、Paused
和 PlaybackCompleted
状态之间切换。
不过请注意,当您调用 stop()
时,除非您再次准备 MediaPlayer
,否则将无法再次调用 start()
。
在编写与 MediaPlayer
对象互动的代码时,请始终牢记该状态图,因为从错误的状态调用其方法是导致错误的常见原因。
释放 MediaPlayer
MediaPlayer
会占用宝贵的系统资源。因此,您应该始终采取额外的预防措施,确保 MediaPlayer
实例保留的时间不会过长。完成该操作后,您应始终调用 release()
以确保分配给它的所有系统资源均已正确释放。
例如,如果您使用的是 MediaPlayer
,并且您的 activity 收到对 onStop()
的调用,则必须释放 MediaPlayer
,因为在 activity 未与用户互动时保留它没有意义(除非您在后台播放媒体,下一部分将对此进行讨论)。
当然,当 activity 恢复或重启时,您需要先创建一个新的 MediaPlayer
并再次完成准备工作,然后才能恢复播放。
以下代码段介绍了如何释放并取消 MediaPlayer
:
Kotlin
mediaPlayer?.release()
mediaPlayer = null
Java
mediaPlayer.release();
mediaPlayer = null;
例如,思考一下:如果您忘记在 activity 停止时释放 MediaPlayer
,但是在 activity 重新启动时新建一个 MediaPlayer,则可能会出现哪些问题。当用户更改屏幕方向(或以其他方式更改设备配置)时,系统会默认重启 activity。当用户在纵向和横向之间来回旋转设备时,您可能会快速耗尽所有系统资源,因为每次更改屏幕方向时,您都会创建一个新的 MediaPlayer
,但从未释放。
如需详细了解运行时重启,请参阅处理运行时更改。
您可能想知道:当用户离开您的 activity 后仍继续播放“后台媒体”(这与内置音乐应用的行为十分相似)会发生什么。在这种情况下,您需要的是由 Service 控制的 MediaPlayer
,如下一部分中所述
了解详情
Jetpack Media3 是应用中播放媒体的推荐解决方案。了解详情。
以下页面介绍了有关录制、存储以及播放音频和视频的主题:
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-07-27。
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-07-27。"],[],[],null,["# Manage MediaPlayer state and resources\n\nThis document covers two areas with potential pitfalls.\n\n- **State.** With \"Medialayer\\`, certain operations are valid only in specific\n states. Incorrect operations can cause exceptions or unexpected behavior.\n\n- **Resources** When you make configuration changes, such as screen rotation,\n You must release a `MediaPlayer` object to free up system resources and\n avoid resource exhaustion.\n\nManage state\n------------\n\n[`MediaPlayer`](/reference/android/media/MediaPlayer) is state-based. That is, it has an\ninternal state that you must\nalways be aware of when you write your code, because certain operations are only\nvalid when the player is in specific states. If you perform an operation while\nin the wrong state, the system may throw an exception or cause other undesirable\nbehaviors.\n\nThe state diagram in the [`MediaPlayer`](/reference/android/media/MediaPlayer) class documentation clarifies\nwhich methods move the [`MediaPlayer`](/reference/android/media/MediaPlayer) from one state\nto another. For example:\n\n- When you create a new [`MediaPlayer`](/reference/android/media/MediaPlayer), it is in the *Idle* state.\n- You initialize it by calling[`setDataSource()`](/reference/android/media/MediaPlayer#setDataSource(android.content.Context,%20android.net.Uri)), which changes it to the *Initialized* state.\n- You prepare it using either the [`prepare()`](/reference/android/media/MediaPlayer#prepare()) or [`prepareAsync()`](/reference/android/media/MediaPlayer#prepareAsync()) method.\n- When the [`MediaPlayer`](/reference/android/media/MediaPlayer) is done preparing, it enters the `Prepared` state, which means you can call [`start()`](/reference/android/media/MediaPlayer#start()) to make it play the media.\n\nAt that point, as the diagram illustrates, you can move between the `Started`,\n`Paused` and `PlaybackCompleted` states by calling such methods as\n[`start()`](/reference/android/media/MediaPlayer#start()), [`pause()`](/reference/android/media/MediaPlayer#pause()), and [`seekTo()`](/reference/android/media/MediaPlayer#seekTo(int)), among others.\n\nWhen you call [`stop()`](/reference/android/media/MediaPlayer#stop()), however, notice that you cannot call [`start()`](/reference/android/media/MediaPlayer#start())\nagain until you prepare the [`MediaPlayer`](/reference/android/media/MediaPlayer) again.\n\nAlways keep [the state diagram](/static/images/mediaplayer_state_diagram.gif) in mind when writing code that interacts with\na [`MediaPlayer`](/reference/android/media/MediaPlayer) object, because calling its methods from the wrong state is\na common cause of bugs.\n\nRelease the MediaPlayer\n-----------------------\n\nA [`MediaPlayer`](/reference/android/media/MediaPlayer) can consume valuable system resources. Therefore, you\nshould always take extra precautions to make sure you are not hanging on to a\n[`MediaPlayer`](/reference/android/media/MediaPlayer) instance longer than necessary. When you are done with it,\nyou should always call [`release()`](/reference/android/media/MediaPlayer#release()) to make sure any system resources\nallocated to it are properly released.\n\nFor example, if you are using a [`MediaPlayer`](/reference/android/media/MediaPlayer) and your activity receives a\ncall to [`onStop()`](/reference/android/app/Activity#onStop()), you must release the [`MediaPlayer`](/reference/android/media/MediaPlayer), because it\nmakes little sense to hold on to it while your activity is not interacting with\nthe user (unless you are playing media in the background, which is discussed in\nthe next section).\n\nWhen your activity is resumed or restarted, of course, you need to create a new\n[`MediaPlayer`](/reference/android/media/MediaPlayer) and prepare it again before resuming playback.\n\nHere's how you should release and then nullify your [`MediaPlayer`](/reference/android/media/MediaPlayer): \n\n### Kotlin\n\n mediaPlayer?.release()\n mediaPlayer = null\n\n### Java\n\n mediaPlayer.release();\n mediaPlayer = null;\n\nAs an example, consider the problems that arise if you forget to release the\n[`MediaPlayer`](/reference/android/media/MediaPlayer) when your activity stops, but create a new one when the\nactivity starts again. When the user changes the screen orientation (or changes\nthe device configuration in another way), the system restarts the activity by\ndefault. You might quickly consume all of the system resources as the user\nrotates the device back and forth between portrait and landscape, because at\neach orientation change, you create a new [`MediaPlayer`](/reference/android/media/MediaPlayer) that you never\nrelease.\n\nFor more information about runtime restarts, see [Handling Runtime Changes](/guide/topics/resources/runtime-changes).\n\nYou may be wondering what happens if you want to continue playing \"background\nmedia\" even when the user leaves your activity, much in the same way that the\nbuilt-in Music application behaves. In this case, what you need is a\n[`MediaPlayer`](/reference/android/media/MediaPlayer) controlled by a Service, as discussed in the next section\n\nLearn more\n----------\n\nJetpack Media3 is the recommended solution for media playback in your app. [Read\nmore](/media/media3) about it.\n\nThese pages cover topics relating to recording, storing, and playing back audio\nand video:\n\n- [Supported Media Formats](/guide/topics/media/media-formats)\n- [MediaRecorder](/guide/topics/media/mediarecorder)\n- [Data Storage](/guide/topics/data/data-storage)"]]