Android播放音樂時,在設定中調節鈴聲大小或者設定鈴聲的時候提示音與音樂一起播放
最開始遇到這個問題的思路是在選擇音樂時發送一條廣播給music然后讓它暫停音樂
代碼如下:
public class MainActivity extends AppCompatActivity {
private static boolean flagMusic;
private AudioManager audioManager = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
boolean vIsActive = audioManager.isMusicActive();
if (vIsActive) {
Toast.makeText(getApplicationContext(), "有音樂在播放", Toast.LENGTH_SHORT).show();
flagMusic = true;//記錄音樂播放狀態 true為正在播放 ,反之
pauseMusic();//暫停音樂播放
} else {
Toast.makeText(getApplicationContext(), "沒有音樂在播放", Toast.LENGTH_SHORT).show();
flagMusic = false;
}
}
private void pauseMusic() {
Intent freshIntent = new Intent();
freshIntent.setAction("com.android.music.musicservicecommand.pause");
freshIntent.putExtra("command", "pause");
sendBroadcast(freshIntent);
}
private void continuMusic() {
Intent freshIntent = new Intent();
freshIntent.setAction("com.android.music.musicservicecommand.togglepause");
freshIntent.putExtra("command", "togglepause");
sendBroadcast(freshIntent);
}
@Override
protected void onStart() {
super.onStart();
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
boolean vIsActive = audioManager.isMusicActive();
if (vIsActive) {
Toast.makeText(getApplicationContext(), "有音樂在播放", Toast.LENGTH_SHORT).show();
flagMusic = true;//記錄音樂播放狀態 true為正在播放 ,反之
pauseMusic();//暫停音樂播放
} else {
Toast.makeText(getApplicationContext(), "沒有音樂在播放", Toast.LENGTH_SHORT).show();
flagMusic = false;
}
}
@Override
protected void onPause() {
super.onPause();
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
boolean vIsActive = audioManager.isMusicActive();
if (!vIsActive) {
Toast.makeText(getApplicationContext(), "有音樂在播放", Toast.LENGTH_SHORT).show();
flagMusic = true;//記錄音樂播放狀態 true為正在播放 ,反之
continuMusic();//暫停音樂播放
} else {
Toast.makeText(getApplicationContext(), "沒有音樂在播放", Toast.LENGTH_SHORT).show();
flagMusic = false;
}
}
@Override
protected void onDestroy() {
super.onDestroy();
audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
boolean vIsActive = audioManager.isMusicActive();
if (!vIsActive) {
Toast.makeText(getApplicationContext(), "有音樂在播放", Toast.LENGTH_SHORT).show();
flagMusic = true;//記錄音樂播放狀態 true為正在播放 ,反之
continuMusic();//暫停音樂播放
} else {
Toast.makeText(getApplicationContext(), "沒有音樂在播放", Toast.LENGTH_SHORT).show();
flagMusic = false;
}
}
}
但是這個只針對自帶音樂app生效 所以換了個思路
在設定調節音量的時候獲取音頻焦點 調節結束的時候松開之后釋放音頻焦點
這樣在調節的時候就可以暫停音樂 松開之后音樂自動就開始播放了
首先在原始碼中找到對應的類:
/frameworks/base/core/java/android/preference/SeekBarVolumizer.java
類應是調節音量的SeekBar
首先來看Seekar的三個回呼函式:
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
mHandler.sendEmptyMessageDelayed(1,500);
//開始調節SeekBar的時候會呼叫這里
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
//調節SeekBar結束的時候會呼叫這里
}
我們來看一下AOSP中的原始碼:
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
if (fromTouch) {
postSetVolume(progress);
}
if (mCallback != null) {
mCallback.onProgressChanged(seekBar, progress, fromTouch);
}
}
private void postSetVolume(int progress) {
if (mHandler == null) return;
// Do the volume changing separately to give responsive UI
mLastProgress = progress;
mHandler.removeMessages(MSG_SET_STREAM_VOLUME);
mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_STREAM_VOLUME));
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
postStartSample();//松開SeekBar的時候播放提示音
}
方法其實很簡單,在onStartTrackingTouch()的時候獲取到音頻焦點
在onStopTrackingTouch()時釋放焦點
這樣在滑動SeekBar的時候后臺的音樂會暫停,松開SeekBar的時候音樂就繼續播放了,代碼如下:
public void onStartTrackingTouch(SeekBar seekBar) {
mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
}
public void onStopTrackingTouch(SeekBar seekBar) {
mAudioManager.abandonAudioFocus(mAudioFocusListener);
postStartSample();
Log.e("SeekBarVolumizer","Start to play cue music");
}
private AudioManager.OnAudioFocusChangeListener mAudioFocusListener = new AudioManager.OnAudioFocusChangeListener() {
public void onAudioFocusChange(int focusChange) {
Log.d(TAG, "onAudioFocusChange:" + focusChange );
switch (focusChange) {
case AudioManager.AUDIOFOCUS_LOSS:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT:
case AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK:
break;
}
}
};
但是 當你編譯好之后會發現 松開SeekBar的時候 后臺的音樂會和調節音量后的提示音一起播放了
原因是因為在系統播放提示音的時候沒有去**requestAudioFocus()而直接去播放了提示音
順著postStartSample();**往下找會發現:
private void postStartSample() {
if (mHandler == null) return;
mHandler.removeMessages(MSG_START_SAMPLE);
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_START_SAMPLE),
isSamplePlaying() ? CHECK_RINGTONE_PLAYBACK_DELAY_MS : 0);
}
發送了一條MSG_START_SAMPLE,最后執行的代碼如下:
private void onStartSample() {
if (!isSamplePlaying()) {
if (mCallback != null) {
mCallback.onSampleStarting(this);
}
synchronized (this) {
if (mRingtone != null) {
try {
mRingtone.setAudioAttributes(new AudioAttributes.Builder(mRingtone
.getAudioAttributes())
.setFlags(AudioAttributes.FLAG_BYPASS_MUTE)
.build());
mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_RING, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); //獲得音頻焦點
mRingtone.play(); //播放提示音
mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_INIT_WAITING),1000); //延遲1秒鐘之后釋放焦點
} catch (Throwable e) {
Log.w(TAG, "Error playing ringtone, stream " + mStreamType, e);
}
}
}
}
}
**handleMessage()**如下:
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_SET_STREAM_VOLUME:
if (mMuted && mLastProgress > 0) {
mAudioManager.adjustStreamVolume(mStreamType, AudioManager.ADJUST_UNMUTE, 0);
} else if (!mMuted && mLastProgress == 0) {
mAudioManager.adjustStreamVolume(mStreamType, AudioManager.ADJUST_MUTE, 0);
}
mAudioManager.setStreamVolume(mStreamType, mLastProgress,
AudioManager.FLAG_SHOW_UI_WARNINGS);
break;
case MSG_START_SAMPLE:
onStartSample();
break;
case MSG_STOP_SAMPLE:
onStopSample();
break;
case MSG_INIT_SAMPLE:
onInitSample();
break;
case MSG_INIT_WAITING:
mAudioManager.abandonAudioFocus(mAudioFocusListener);
break;
default:
Log.e(TAG, "invalid SeekBarVolumizer message: "+msg.what);
}
return true;
}
這樣滑動SeekBar的時候音樂會暫停下來 松開SeekBar之后播放提示音 一秒之后音樂就會繼續播放啦
(≧▽≦)
參考文章:
https://blog.csdn.net/actor1999/article/details/80402222
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/256406.html
標籤:其他
