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();
}

这个问题到此就结束了,希望能有帮助!

 
原文地址:https://www.cnblogs.com/zhujiabin/p/7886488.html