Android中屏幕旋转时停止音频播放并实现仅自动播放一次的方案
解决屏幕旋转时音频仅播放一次的问题
屏幕旋转会触发Android Activity的销毁与重建,你的onCreate方法会被重复执行,这就是导致音频重复播放的核心原因。以下是几种可行的解决方案,按需选择:
方案1:用ViewModel保存播放状态(推荐)
ViewModel会在Activity重建时保留实例,不会随Activity销毁而消失,刚好用来记录播放状态和持有MediaPlayer实例。
- 创建ViewModel类:
class AudioViewModel : ViewModel() { var mediaPlayer: MediaPlayer? = null var hasPlayed = false // ViewModel销毁时释放资源,避免内存泄漏 override fun onCleared() { super.onCleared() mediaPlayer?.release() mediaPlayer = null } }
- 在MainActivity中使用:
class MainActivity : AppCompatActivity() { private lateinit var audioViewModel: AudioViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) audioViewModel = ViewModelProvider(this)[AudioViewModel::class.java] // 仅在未播放过的情况下初始化并播放 if (!audioViewModel.hasPlayed) { audioViewModel.mediaPlayer = MediaPlayer.create(this, R.raw.your_audio) audioViewModel.mediaPlayer?.start() audioViewModel.hasPlayed = true } } override fun onDestroy() { super.onDestroy() // 只有当Activity不是因配置变化(如旋转)销毁时,才手动释放资源 if (!isChangingConfigurations) { audioViewModel.mediaPlayer?.release() audioViewModel.mediaPlayer = null } } }
方案2:用SharedPreferences持久化播放状态
如果需要实现即使APP退出重启也不再播放的效果,用SharedPreferences记录播放状态更合适。
class MainActivity : AppCompatActivity() { private var mediaPlayer: MediaPlayer? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val sharedPref = getPreferences(Context.MODE_PRIVATE) val hasPlayed = sharedPref.getBoolean("audio_played_flag", false) if (!hasPlayed) { mediaPlayer = MediaPlayer.create(this, R.raw.your_audio) mediaPlayer?.start() // 可选:等音频播放完成后再标记已播放 mediaPlayer?.setOnCompletionListener { sharedPref.edit().putBoolean("audio_played_flag", true).apply() } // 或者:立即标记已播放(不管音频是否播放完成,只触发一次播放) // sharedPref.edit().putBoolean("audio_played_flag", true).apply() } } override fun onDestroy() { super.onDestroy() mediaPlayer?.release() mediaPlayer = null } }
方案3:禁止Activity旋转时重建
通过配置让Activity在屏幕旋转时不销毁重建,这样onCreate只会执行一次。
- 在
AndroidManifest.xml中修改MainActivity的配置:
<activity android:name=".MainActivity" android:configChanges="orientation|screenSize|smallestScreenSize"> <!-- 其他配置 --> </activity>
- (可选)如果需要处理旋转后的UI调整,重写
onConfigurationChanged:
override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) // 这里可以处理横竖屏切换后的UI适配,比如更换布局 }
方案4:用后台Service播放音频
如果需要音频在后台持续播放,或者完全脱离Activity生命周期控制,用Service是最优解。
- 创建Service类:
class AudioPlayService : Service() { private var mediaPlayer: MediaPlayer? = null var hasPlayed = false override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { if (!hasPlayed) { mediaPlayer = MediaPlayer.create(this, R.raw.your_audio) mediaPlayer?.start() hasPlayed = true // 音频播放完成后自动停止服务 mediaPlayer?.setOnCompletionListener { stopSelf() } } return START_NOT_STICKY } override fun onDestroy() { super.onDestroy() mediaPlayer?.release() mediaPlayer = null } override fun onBind(intent: Intent): IBinder? { return null } }
- 在
AndroidManifest.xml中注册Service:
<service android:name=".AudioPlayService" />
- 在MainActivity中启动Service(结合ViewModel或SharedPreferences避免重复启动):
class MainActivity : AppCompatActivity() { private lateinit var audioViewModel: AudioViewModel override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) audioViewModel = ViewModelProvider(this)[AudioViewModel::class.java] if (!audioViewModel.hasPlayed) { startService(Intent(this, AudioPlayService::class.java)) audioViewModel.hasPlayed = true } } }
内容的提问来源于stack exchange,提问作者ANT T
相关产品推荐
相关产品推荐

