You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中屏幕旋转时停止音频播放并实现仅自动播放一次的方案

解决屏幕旋转时音频仅播放一次的问题

屏幕旋转会触发Android Activity的销毁与重建,你的onCreate方法会被重复执行,这就是导致音频重复播放的核心原因。以下是几种可行的解决方案,按需选择:

方案1:用ViewModel保存播放状态(推荐)

ViewModel会在Activity重建时保留实例,不会随Activity销毁而消失,刚好用来记录播放状态和持有MediaPlayer实例。

  1. 创建ViewModel类:
class AudioViewModel : ViewModel() {
    var mediaPlayer: MediaPlayer? = null
    var hasPlayed = false

    // ViewModel销毁时释放资源,避免内存泄漏
    override fun onCleared() {
        super.onCleared()
        mediaPlayer?.release()
        mediaPlayer = null
    }
}
  1. 在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只会执行一次。

  1. 在AndroidManifest.xml中修改MainActivity的配置:
<activity android:name=".MainActivity"
    android:configChanges="orientation|screenSize|smallestScreenSize">
    <!-- 其他配置 -->
</activity>
  1. (可选)如果需要处理旋转后的UI调整,重写onConfigurationChanged:
override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    // 这里可以处理横竖屏切换后的UI适配,比如更换布局
}

方案4:用后台Service播放音频

如果需要音频在后台持续播放,或者完全脱离Activity生命周期控制,用Service是最优解。

  1. 创建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
    }
}
  1. 在AndroidManifest.xml中注册Service:
<service android:name=".AudioPlayService" />
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 16:30:56