Creator3.x 的 Game.EVENT_PAUSE 在弹出新的Activity时没有触发的解决办法

本文采用Cocos Creator 3.8.1

项目需求

我需要监控游戏Activity的onPause/onResume状态,发现engine有Game.EVENT_PAUSE事件,自然想到这样处理:

game.on(Game.EVENT_PAUSE, ()={ }, this);

测试发现以上的代码,当锁屏或者返回Home时,的确是可以触发的。

但是发现当游戏弹出一个新的Activity时(比如广告一般都是一个新的Activity),CocosGameActivity的确触发了onPause,但是却没有触发Game.EVENT_PAUSE,感觉像是踩中了一个BUG,问了几个朋友都没有深究过这块,于是只能硬着头皮,看看源码这附近的逻辑,也许能找打答案。

排查定位

顺着业务代码往上找,打一个Android 调试包,在Chrome中打开调试链接(不懂的需要自己看文档,这里不再赘述)

在业务代码下好断点,等游戏启动之后,然后锁屏,此时触发了断点

image

直接看堆栈的源头,竟然是hide

image

然后我尝试着追踪了下EVENT_HIDE的逻辑,竟然也是同样的地方。

image

到这里基本上已经确认了,就是因为底层逻辑是将hide/pause的逻辑公用导致的问题。

排查插曲

其实排查最初我是没有头绪的,简单调试了Java层后,感觉像是C++层触发的Pause,于是尝试了搜索了一些pause/resume的关键字,尝试着分析了下

如上图,我尝试在resume里面添加了log,但是游戏运行的时候无论怎么操作都没有触发打印,我感觉可能是CC_LOG_DEBUG的问题,尝试在init/run函数里面添加log,这样log是如期打印出来了

image

再看看Engine::resume没有任何实现,多半是这里的确没有触发,engine后续版本不知道有实现没。

修复

知道是jsb层在公用pause/hide,我就没有在追是谁在触发jsb.onPause

下边就是解决如何我的需求了,本想着复用上边的SystemInfo.emit("hide"),顺便简单了解了下这个systemInfo,因为他最后导出了systemInfo变量,并且好像也没有被engine暴漏出去,因此游戏脚本好像也没有办法拿到这个变量,即使暴漏了,还要想想Java层怎么调用到这里,因为你的源头肯定是在Java层的onPause回调,深层次的也懒得继续研究了,牵扯到jsb就头疼,这已经是硬着头皮看了好多了。

还是简单粗暴点,直接在Java层的通知游戏即可

@Override
protected void onPause() {
    super.onPause();
    SDKWrapper.shared().onPause();
    CocosHelper.runOnGameThread(new Runnable() {
        @Override
        public void run() {
            CocosJavascriptJavaBridge.evalString("window.onActivityPause&&window.onActivityPause();");
        }
    });
}

然后在游戏里面接收处理下

const ActivityPause = "activityPause";
// @ts-ignore
window.onActivityPause = () => {
    game.emit(ActivityPause);
}

这里我通过game.emit分发了出去,因为考虑到可能使用的地方比较多,哪里用到哪里注册就行了,至此,完美满足项目需求。

最后

希望官方后续版本能完善下这个逻辑,我看到了TODO

我的公众号,不定期分享个人的cocos开发经验
image

个人掘金干货, 最近2年的工作经验分享

2赞

未看先赞 :partying_face: :partying_face: :partying_face: