安卓cocos2dx游戲啟動(dòng)時(shí)授權(quán)彈窗申請(qǐng)導(dǎo)致的閃屏

復(fù)現(xiàn)步驟:
1.安裝好apk
2.啟動(dòng)app -> Splash頁(yè)面 -> 申請(qǐng)授權(quán)彈窗
3.同意或者拒接 -> 退出彈窗 -> 屏幕閃爍

Log:
運(yùn)行中出現(xiàn)GL Error 0x0506

初步排查發(fā)現(xiàn)導(dǎo)致該問(wèn)題的原因是CCDirector::mainLoop()函數(shù)中 _invalid 標(biāo)識(shí)為true導(dǎo)致未執(zhí)行 drawScene() 方法:

void Director::mainLoop()
{

    if (_purgeDirectorInNextLoop)
    {
        _purgeDirectorInNextLoop = false;
        purgeDirector();
    }
    else if (_restartDirectorInNextLoop)
    {
        _restartDirectorInNextLoop = false;
        restartDirector();
    }
    else if (! _invalid)
    {
        drawScene();
     
        // release the objects
        PoolManager::getInstance()->getCurrentPool()->clear();
    }
}

排查為什么_invalid標(biāo)識(shí)會(huì)變?yōu)?code>true,發(fā)現(xiàn)修改該變量的地方為:

void Director::startAnimation()
{
    _invalid = false;
}

void Director::stopAnimation()
{
    _invalid = true;
}

繼續(xù)往下!

// AppDelegate.cpp
void AppDelegate::applicationDidEnterBackground()
{
    Director::getInstance()->stopAnimation();
}

void AppDelegate::applicationWillEnterForeground()
{
    Director::getInstance()->startAnimation();
}

// Java_org_cocos2dx_lib_Cocos2dxRenderer.cpp
JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnResume() {
    static bool firstTime = true;
    if (Director::getInstance()->getOpenGLView()) {
        // don't invoke at first to keep the same logic as iOS
        // can refer to https://github.com/cocos2d/cocos2d-x/issues/14206
        if (!firstTime)
            Application::getInstance()->applicationWillEnterForeground();

        firstTime = false;
    }
}

JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnPause() {
    if (Director::getInstance()->getOpenGLView()) {
            Application::getInstance()->applicationDidEnterBackground();
    }
}

// Cocos2dxRenderer.java
public void handleOnPause() {
    Cocos2dxRenderer.nativeOnPause();
}

public void handleOnResume() {
    Cocos2dxRenderer.nativeOnResume();
}

// Cocos2dxGLSurfaceView.java
@Override
public void onResume() {
    Log.d(TAG, "onResume()");
    super.onResume();
    this.setRenderMode(RENDERMODE_CONTINUOUSLY);
    this.queueEvent(new Runnable() {
        @Override
        public void run() {
            Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleOnResume();
        }
    });
}

@Override
public void onPause() {
    Log.d(TAG, "onPause()");
    this.queueEvent(new Runnable() {
        @Override
        public void run() {
            Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleOnPause();
        }
    });
    this.setRenderMode(RENDERMODE_WHEN_DIRTY);
    // super.onPause();
}

由此我們可以得出結(jié)論,是因?yàn)槭跈?quán)彈窗彈出觸發(fā)Cocos2dxGLSurfaceView.onPause()方法,導(dǎo)致_invalidtrue

那么問(wèn)題來(lái)了,為什么彈框消失的時(shí)候觸發(fā)的Cocos2dxGLSurfaceView.onResume()不會(huì)把_invalid還原為false呢?

根據(jù)流程我發(fā)現(xiàn)Cocos2d引擎源碼在Java_org_cocos2dx_lib_Cocos2dxRenderer.java的JNI函數(shù)JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnResume()方法里設(shè)置了一個(gè)靜態(tài)變量static bool firstTime = true;
當(dāng)?shù)谝淮螆?zhí)行該函數(shù)的時(shí)候會(huì)跳過(guò)執(zhí)行applicationWillEnterForeground()方法,那么我們接下來(lái)只需要判斷彈框消失后觸發(fā)的Cocos2dxGLSurfaceView.onResume()是不是程序運(yùn)行的第一次調(diào)用,而測(cè)試結(jié)果確實(shí)如此?。?!

到此,我們定位到了該問(wèn)題的產(chǎn)生邏輯,那么接下來(lái)如何解決這個(gè)問(wèn)題就簡(jiǎn)單多了。

解決思路選擇其中之一即可:
1.在JNI方法JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnResume()中做特殊處理:
定義布爾類(lèi)型類(lèi)成員變量bool isPause = false,當(dāng)執(zhí)行nativeOnPause()時(shí)把isPause置為true,再添加判斷條件
if (!firstTime || isPause)

2.在Cocos2dxActivity中處理:

private void resumeIfHasFocus() {
    if(hasFocus) {  // 取消hasFocus判斷條件
        this.hideVirtualButton();
        Cocos2dxHelper.onResume();
        mGLSurfaceView.onResume();
    }
}

當(dāng)然還有其他解決思路,同時(shí),不同的項(xiàng)目上述的解決方案可能會(huì)導(dǎo)致一些其他問(wèn)題,需要根據(jù)具體項(xiàng)目測(cè)試。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容