Android使用的webcview中带有音乐播放控件,在关闭或分享时处于界面不可见状态下,声音仍在播放的问题解决
一. 问题出现原因
我们在做APP分享时,分享webview加载带有音乐播放控件的网页.当弹出分享界面,webview的网页处于后台状态或关闭该网页时,音乐声仍在播放.出现该类现象使我们所不能容忍,也会给用户一个不好的印象,网上有几种解决办法,但都有不尽如意的地方,今天,我们就来说说如何更好地解决它,我也会把网上一些热心大牛所给的一些解决方法,所存在弊端的地方也会给大家点出来.如果大家有遇到该类似情况的,那么你就可以解决它啦!
二.解决方法
@Override protected void onPause() { super.onPause(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { mWebView.onPause(); } } @Override protected void onResume() { super.onResume(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { mWebView.onResume(); } hideKeyBoard(); } @Override protected void onDestroy() { super.onDestroy(); mWebView.resumeTimers(); mWebView.destroy(); }
如果网页中的加载的是视频,我们在 onPause() ,onResume(),onDestroy(),是可以很好地暂停播放的,但如果是在网页中加载的是声音或者音乐的话,我们会发现这样不能控制它.通过查阅资料,我们发现这是Android的一个BUG,但因为Android的音乐流,音效流,电话声音是互不干涉的,且通过获取焦点来进行播放,多数情况下我们播放音乐都是使用 STREAM_MUSIC 音频流。
@Override protected void onPause() { super.onPause(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { mWebView.onPause(); } //让音乐控件失去焦点来禁止掉声音的播放 if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.ECLAIR_MR1) { } else { try { audioManager = (AudioManager) getSystemService(InterDetailActivity.this.AUDIO_SERVICE); int i = 0; do { int result = audioManager.requestAudioFocus(listener , AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { Log.d("AudioManager", "I get Audio right: "); break; } i++; } while (i < 10); } catch (Exception ex) { ex.printStackTrace(); } } }
对控制音乐播放控件的 焦点是否改变进行监听
OnAudioFocusChangeListener listener = new OnAudioFocusChangeListener() { @Override public void onAudioFocusChange(int focusChange) { Log.d("audioManager", "onAudioFocusChange: " + focusChange); } };
这时候,你会发现,我们在正常打开该webview,音乐控件播放,点击分享弹出分享编辑页面,或者锁屏使网页界面不可见状态,音乐声音也跟着没有了,然后我们再返回到带有音乐控件的网页,但是问题来了,音乐控件的转动播放却没有声音,而我们要的是,在这个网页可见的时候要有音乐的,这是因为,之前做的播放控件失去焦点,禁止掉了声音,这时我们只需要在onResue()或onRestar()中,让该H5页面再重新刷新下,音乐就播放出来了
@Override protected void onRestart() { super.onRestart(); mWebView.reload(); } @Override protected void onResume() { super.onResume(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { mWebView.onResume(); // mWebView.reload(); } }
但上面也说了,这时在我们正常操作的时候,问题已经解决了,对,这只是正常操作下的,那怎样不正常操作呢?举个例子:如果你打开该H5网页后,快速又点击了分享按钮,这时候h5网页已经进入了后台,但你会发现,声音又出现了,这是因为,当你进入该网页,嵌在网页的视频或音乐播放控件是需要一定时间加载的,在还没加载出来的时候点击了分享使其处于不可见状态后,控件才加载好,音乐声也就出来了.那有如何解决这个问题呢?
网上查了许多资料 ,也给出了一些解决办法:
web.pauseTimers(); web.stopLoading(); web.loadData("<a></a>", "text/html", "utf-8");
但这些方法都不能达到满意的效果
web.pauseTimers(); 这个方法不仅仅针对当前的webview而是全局的全应用程序的webview,它会暂停所有webview的layout,如果你的APP中有两个地方或入口打开一个带音乐播放控件的网页,就会出现,在其中一个页面暂停后,会把另一个入口的网页也禁止掉.且音乐不能播放或者resumeTimers ()不能唤醒.如果该网页是类似多个页面可滑动翻页的话,则也不能滑动进行翻页了.这该效果也不是我们想要的,我们不希望我们应用中,不同地方或入口间会互相影响.
web.stopLoading();这个方法根本没有作用;
web.loadData("<a></a>", "text/html", "utf-8");
这个方法,已进入H5网页快速点击分享,在后台没有声音了,但当我们再回到网页界面,该网页空白了,没有了数据,更没有音乐的播放控件了,使用mWebView.reload();也不能刷新出来,我们需要mWebView.loadUrl(....)再重新加载一次这个h5网址.依然是刚才的例子,这是一个可滑动翻页的H5页面,如果分享前我们滑动到第三个页面,点击的分享,WebView.loadUrl()后会又回到第一页.这也不是我们想要的,我们要的是,滑动到那个页面,最后还回到那个页面.
现在我们该真正的解决这个问题了,而常见的几种情况,我们也都说了,也解释了
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); initView(); } @Override protected void onRestart() { super.onRestart(); mWebView.reload(); } @Override protected void onResume() { super.onResume(); isPause = false; hideKeyBoard(); } @Override protected void onPause() { super.onPause(); isPause = true; requestAudioFocus(); } @Override protected void onDestroy() { super.onDestroy(); mWebView.destroy(); mAudioManager.abandonAudioFocus(audioFocusChangeListener);
private void requestAudioFocus() { int result = mAudioManager.requestAudioFocus(audioFocusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { Log.e(TAG, "audio focus been granted"); } } private OnAudioFocusChangeListener audioFocusChangeListener = new OnAudioFocusChangeListener() { @Override public void onAudioFocusChange(int focusChange) { Log.e(TAG, "focusChange: " + focusChange); if (isPause && focusChange == AudioManager.AUDIOFOCUS_LOSS) { requestAudioFocus(); } } };
好了,这样我们就可以解决问题了,是不是很简单?重要的地方就是在焦点改变的监听时进行该操作
if (isPause && focusChange == AudioManager.AUDIOFOCUS_LOSS) { requestAudioFocus(); }
这个问题到此就结束了,希望能有帮助!