分享cocos2d-x在安卓平台webview点击返回键之后闪退问题的解决方案

0. 描述

目前WebView闪退相关bug有两处:一个是WebView正在打开的情况下点击返回键退出游戏。另一个是WebView关闭之后在游戏中点返回键闪退游戏。下面分别描述一下具体表现,导致这个问题的原因和修复方法。

1. WebView正在打开的状态下点击返回键退出游戏

  • 具体表现: WebView打开一个网页之后点击返回键直接退出游戏回到大厅

  • 问题原因: 这可以说是不算bug吧,只是cocos2dx没有WebView的返回键事件处理好。安卓平台的WebView返回键的默认行为就是退出进程。

  • 解决方法:我们给webveiw注册一下回调事件,当keycode为返回键的时候给自己的逻辑层传递时间做相关操作,然后返回true吞噬这个事件就可以了。

// 决绝方案
// org.cocos2dx.lib.Cocos2dxWebView 类里面重写下面方法
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        // do my stuff
        return true;
    }
    return false;
}

2.weview关闭之后在游戏中点返回键闪退游戏

  • 具体表现: WebView打开一个网页,然后触摸一下webveiw(点击网页上的任意一个点),然后关闭WebView(在我们项目就是关闭界面销毁lua里面对应的WebView节点),然后在游戏中点击返回键,这个时候游戏闪退了,你再icon进来的时候可能看到的是黑屏或者你在平台层的一个启动图。

  • 问题的原因: 一般游戏中安卓层的焦点在GLSurfaceView,但是你打开WebView点击之后焦点是在WebView,当你关闭WebView的时候貌似焦点并没有回到GLSurfaceView还是出了其他原因,就是渲染进程给崩了(我是怀疑没有回到GLSurfaceView但是我调用Cocos2dxActivity.getCurrentFocus函数的时候返回的却是GLSurfaceView)。

  • 解决方法: 这里有两种解决方案,第一个是我在网上看到的,很多人想到了这个,但会引发一些问题。而第二个解决方案可以成功解决这个bug。

1. 第一个解决方案(不建议采用,或者不能采用,):

引发的问题是你的webview点击网页里面的输入框的时候没法弹出系统软键盘

//  org.cocos2dx.lib.Cocos2dxWebView类的Cocos2dxWebView 方法里面修改下面一行
this.setFocusableInTouchMode(false);

2. 第二个解决方案:

原理就是当你关闭WebView的时候判断下还有没有WebView正在显示,如果没有就让GlSurfaceView请求获取一下焦点。当然,这只是解决了我的问题,改完之后还是需要好好测的。

//  org.cocos2dx.lib.Cocos2dxWebView.Cocos2dxWebViewHelper 类里面的removeWebView改成这样
public static void removeWebView(final int index) {
    sCocos2dxActivity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            Cocos2dxWebView webView = webViews.get(index);
            if (webView != null) {
                webViews.remove(index);
                sLayout.removeView(webView);
                webView.destroy();
            }
            // 修复WebView销毁之后点击返回键崩溃的bug
            boolean isHaveVisibleWebView = false;
            for (int i = 0; i < webViews.size(); i++) {
                if (webViews.get(i).getVisibility() == View.VISIBLE) {
                    isHaveVisibleWebView = true;
                    break;
                }
            }
            if (!isHaveVisibleWebView) {
                Cocos2dxGLSurfaceView.getInstance().requestFocus();
            }
        }
    });
}

3. 总结

第一个问题其实我们这边是去年修复的,第二个问题前几天才发现,其实影响还是挺大的,安卓层的代码又不能热更。我看四五年前有人在问题这个问题,几个月前还有人在问。我就贴到这里,希望对各位有所帮助。

2赞