Android充电连接时MediaPlayer重复播放声音问题求助
解决Android充电提示音重复播放的问题
嘿,我来帮你搞定这个重复播放的问题~ 你的代码里主要有两个核心问题:一是ACTION_BATTERY_CHANGED广播会被系统频繁触发(不止插拔充电线时,电量变化、状态微调都会发),二是你的状态标记逻辑和MediaPlayer管理不够严谨。下面是具体的解决方案:
问题根源分析
ACTION_BATTERY_CHANGED是粘性广播,系统会在很多场景下发送它(比如电池从99%到100%、充电状态从快充切换到普通充),这会导致你的onCharge()/onDisconnect()被多次调用。- 你现在的
playedOnceOn是在播放完成后才设为true,如果广播在播放过程中再次触发,就会重复播放。 - MediaPlayer每次都重新创建,没有及时释放,不仅浪费资源,也可能导致多个实例同时播放。
修正后的代码方案
package com.mccharginggimmick; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.media.MediaPlayer; import android.os.BatteryManager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.ImageView; public class MainActivity extends AppCompatActivity { IntentFilter intentFilter; BroadcastReceiver broadcastReceiver; MediaPlayer mediaPlayer; // 统一用一个MediaPlayer实例,避免重复创建 boolean lastChargingState = false; // 记录上一次的充电状态,用来判断状态是否变化 ImageView imageView; @Override protected void onCreate(Bundle savedInstanceState) { View decorView = getWindow().getDecorView(); int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN; decorView.setSystemUiVisibility(uiOptions); super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); imageView = findViewById(R.id.imageView); intentFilter = new IntentFilter(Intent.ACTION_BATTERY_CHANGED); broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { int status = intent.getIntExtra(BatteryManager.EXTRA_STATUS, -1); boolean isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING || status == BatteryManager.BATTERY_STATUS_FULL; // 只有当充电状态发生变化时,才执行对应的操作 if (isCharging != lastChargingState) { lastChargingState = isCharging; if (isCharging) { playChargeSound(); } else { playDisconnectSound(); } } } }; registerReceiver(broadcastReceiver, intentFilter); } private void playChargeSound() { // 先释放之前的MediaPlayer资源 releaseMediaPlayer(); imageView.setVisibility(View.INVISIBLE); mediaPlayer = MediaPlayer.create(this, R.raw.btnon); mediaPlayer.start(); mediaPlayer.setOnCompletionListener(mp -> releaseMediaPlayer()); } private void playDisconnectSound() { // 先释放之前的MediaPlayer资源 releaseMediaPlayer(); imageView.setVisibility(View.VISIBLE); mediaPlayer = MediaPlayer.create(this, R.raw.btnoff); mediaPlayer.start(); mediaPlayer.setOnCompletionListener(mp -> releaseMediaPlayer()); } // 统一的MediaPlayer释放方法,避免内存泄漏和重复播放 private void releaseMediaPlayer() { if (mediaPlayer != null) { if (mediaPlayer.isPlaying()) { mediaPlayer.stop(); } mediaPlayer.release(); mediaPlayer = null; } } @Override protected void onDestroy() { super.onDestroy(); // 页面销毁时记得注销广播和释放MediaPlayer if (broadcastReceiver != null) { unregisterReceiver(broadcastReceiver); } releaseMediaPlayer(); } }
关键优化点说明
- 状态变化判断:新增
lastChargingState变量,只有当当前充电状态和上一次不同时才触发播放,彻底避免重复触发。 - MediaPlayer统一管理:只用一个MediaPlayer实例,每次播放前先释放旧资源,防止多个实例同时播放,也减少内存占用。
- 生命周期完善:在
onDestroy()里注销广播和释放MediaPlayer,避免内存泄漏。 - 移除冗余标记:不再需要
playedOnceOn/playedOnceOff,因为状态变化判断已经保证了只有状态切换时才播放。
这样修改后,不管是首次连接充电线还是快速插拔,都只会播放一次提示音啦~
内容的提问来源于stack exchange,提问作者Paul E
相关产品推荐
相关产品推荐

