新浪微博、QQ空间等一些 APP 有这样的效果(比较常见,就不截视频了):在列表页刷到一个视频的内容,视频自动播放,但是没有声音,如果你正在播放音乐,当视频播放的时候,音乐不会停止;如果点击视频,就进入下一个视频界面,这时候有声音了,播放的音乐也会停止。先说说这样的用户体验:像微博列表会有文字类、图片类、视频类,假如在公共场合突然刷到一个视频并且自动播放,有声音的情况:突然一个声音就冒出来了,然后大家都看着你;没有声音:静静的看着视频,如果感兴趣,带上耳机或者调低声音进入视频界面。
一般播放视频要么是使用第三方的,也有自己封装 mediaplayer 的,先看看官方建议怎么使用 mediaplayer ;官方给出的是播放音频,视频一般采用的 mediaplayyer + textureview ,下面给出最简单代码,具体的自行搜索
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource("yourVideoUrl");
//setSurface 主要是将mediaplayer 和textureview 联系起来,这里仅仅做演示,所以最简单化写出来
mMediaPlayer.setSurface(s);
mMediaPlayer.prepareAsync();
//几个监听事件
mMediaPlayer.setOnBufferingUpdateListener(MediaPlayer.OnBufferingUpdateListener);
mMediaPlayer.setOnCompletionListener(MediaPlayer.OnCompletionListener);
mMediaPlayer.setOnPreparedListener(MediaPlayer.OnPreparedListener);
mMediaPlayer.setOnVideoSizeChangedListener(MediaPlayer.OnVideoSizeChangedListener);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
//开始播放
mMediaPlayer.start();
MediaPlayer 本身提供了调节音量的 api : MediaPlayer.setVolume(float leftVolume, float rightVolume) ,取值范围是(0.0 - 1.0),leftVolume:左音量 ,rightVolume :右音量 。结合本文目的 — 静音,应该设置 :
mMediaPlayer.setVolume( 0f , 0f )
经过测试,的确达到了静音效果。微博视频还有这样的效果,其他APP正在播放音乐,假如在列表视频的时候设置静音,这个时候音乐不会受到影响,会继续播放,点击全屏的时候,音乐停止,播放视频的声音。这个效果怎么实现的呢,请看 AudioFocus
先给出官网地址,也可以自行搜索,音频焦点:手机中有很多声音来源,如果有多个 APP 都同时播放音乐,这样的用户体验想想都怕,音频焦点的作用就是 APP 满足 一些特定条件,就可以获取音频焦点,就像微博播放视频的时候(全屏),音乐会自动停止,视频播放完毕,音乐就自动恢复(不是所有的音乐都会恢复,需要看播放音乐 APP 怎么处理的),这样的前提是播放音乐的 APP 也按照音频焦点。这里说说2个重要的条件
代码使用
AudioManager audioManager = (AudioManager) getSystemService( AUDIO_SERVICE );
audioManager.requestAudioFocus( afChangeListener, AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT );
请求音频焦点,获取音频焦点后,调节音量 setVolume 也会影响系统类型为 AudioManager.STREAM_MUSIC 的音量。官方建议播放完后释放音频焦点,也就是需要的时候就去请求焦点,不需要的就释放焦点
AudioManager audioManager = (AudioManager) getSystemService( AUDIO_SERVICE );
audioManager.abandonAudioFocus( afChangeListener)
释放焦点后,再调节音量 setVolume 就不会影响系统音量了。关于 AudioFocus 还有其他很多作用,具体搜索下,这里的目的主要是实现微博的效果,所以就不细讲。
思路也就明显了,也就是
列表静音: 播放释放假如有音频焦点就释放,并且设置 mMediaPlayer.setVolume( 0f , 0f );
全屏播放:全屏时候请求音频焦点,并且设置声音 mMediaPlayer.setVolume( 1f , 1f ) ,这里的数值看实际情况。
先说说有人说使用 mMediaPlayer.setVolume( ) 调节音量没有作用,据我实际使用中是有效果的,我想没有作用的情况应该是调用 setVolume 位置不对。在源码中
mediaPlayer.release();
mediaPlayer = new MediaPlayer();
这里出现在 JCMediaManager 类中 HANDLER_PREPARE 事件中,也就说,调用时间不对,在这个代码之前设置音量 并不会有作用,只有在 new MediaPlayer() 后 在下次 mediaPlayer.release() 前才有用,因为播放完一段视频或者播放下端视频都会调用 release。
为了不影响 JieCaoVieoPlayer 的源代码或者说以最小的改动实现我们的效果,我们需要继承之前使用的 JCVideoPlayer ,github 上面建议使用 JCVideoPlayerStandard ;如果要达到静音效果,我建议继承 JCVideoPlayerStandard ,并且在继承类添加下面的代码并复写部分代码;当然你也可以在你自己自定义中去添加部分代码。我这里偷懒,就在 demo 中的 mainActivity 中的 MyJCVideoPlayerStandard 设置,代码如下
//静音模式 默认为false
private boolean isSilencePattern = false;
/**
* 设置静音模式
*
* @param isSilencePattern
*/
public void setSilencePattern(boolean isSilencePattern) {
this.isSilencePattern = isSilencePattern;
}
/**
* 设置音量
*
* @param isSilence
*/
public void setVolume(boolean isSilence) {
if (isSilence) {//静音
JCMediaManager.instance().mediaPlayer.setVolume(0f, 0f);
} else {
JCMediaManager.instance().mediaPlayer.setVolume(1f, 1f);
}
}
/**
* 请求或者释放焦点
*
* @param focus
*/
public void setAudioFocus(boolean focus) {
AudioManager mAudioManager = (AudioManager)
getContext().getSystemService(Context.AUDIO_SERVICE);
if (focus) {//请求音频焦点
mAudioManager.requestAudioFocus(onAudioFocusChangeListener,
AudioManager.STREAM_MUSIC,
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
} else {//释放
mAudioManager.abandonAudioFocus(onAudioFocusChangeListener);
}
}
现在就需要知道合理的位置调用合理的方法
在 JCVideoPlayer 中 startVideo 方法中,
出现了请求焦点,所以需要我们在子类中去复写 startVideo
@Override
public void startVideo() {
super.startVideo();
if (isSilencePattern) {
setAudioFocus(false);
}
}
注意这添加的方法需要在 super.startVideo() 下面,如果放在上面会先执行 请求释放焦点,然后去执行 startVideo 中的请求焦点。
上面也说了,需要在合适的位置调用才会生效,为了从一开始播放就静音,就找到开始播放前就设置静音,这里我选择的 onStatePlaying 这个方法,还有其他地方也可以,需要去看源码了解各个方法的作用复写。
@Override
public void onStatePlaying() {
super.onStatePlaying();
//在列表 或者 普通模式下,可以根据实际需求改变
if (isSilencePattern && (currentScreen == SCREEN_LAYOUT_NORMAL ||
currentScreen == SCREEN_LAYOUT_LIST)) {
setVolume(true);
}
}
当是全屏(或者小屏) 需要去请求音频焦点和设置音量,退出全屏(或小屏) 又恢复静音
/**
* 进入全屏
*/
@Override
public void startWindowFullscreen() {
super.startWindowFullscreen();
if (isSilencePattern) {
setAudioFocus(true);
setVolume(false);
}
}
退出全屏
/**
* 退出全屏
*/
@Override
public void playOnThisJcvd() {
super.playOnThisJcvd();
if (isSilencePattern) {
setAudioFocus(false);
setVolume(true);
}
}
经过上面几个步骤,普通列表静音,全屏恢复声音的效果就实现了,如果需要静音模式,在使用 JCVideoPlayerStandard 的时候 调用
mJCVideoPlayerStandard.setSilencePattern(true);
也就加了几句话,就不上传代码了,需要的看看实现过程复制代码即可,时间匆忙,写的不是很清楚,请见谅并指出,这篇的思路来自群里的一位朋友,以前也想达到这种效果,也遇到设置 设置音量不管用,没有认真看源码,在没有经过严格测试下,也得出一些不可靠的结论,这里感谢那位朋友。