きょこみのーと

技術に関係ないほうのブログ

cocos2d-xでAndroid側でGLSafirceViewをonPauseするとエラーる

やりたいこと

Androidでcocos2d-xを表示しているActivity上でIn-app Billing v3のActivityDialogを上に表示したかった。

エラー内容

課金のDialogActivityが上に表示されるとonPause()が実行されてCCApplication.cppで以下のエラーが発生した。

E/cocos2d-x assert(4410): /Applications/cocos2d-x-2.1.4/projects/HelloWorldProjct/proj.android/../../../cocos2dx/platform/android/CCApplication.cpp function:sharedApplication line:60

ソースを追って見てみるとassertで落とされてる様子。 つまり、実装方法が悪いっぽい。

CCApplication.cpp

CCApplication* CCApplication::sharedApplication()
{
    CCAssert(sm_pSharedApplication, "");
    return sm_pSharedApplication;
}

どこからシングルトンのCCApplicationを呼んで落ちているのか? ひたすらログを貼っつけて調査した結果。

Cocos2dxActivity.java

@Override
protected void onPause() {
    super.onPause();

    Cocos2dxHelper.onPause();
    this.mGLSurfaceView.onPause(); // ★ここ
}

Cocos2dxGLSurfaceView.java

@Override
public void onPause() {
    this.queueEvent(new Runnable() {
        @Override
        public void run() {
            Cocos2dxGLSurfaceView.this.mCocos2dxRenderer.handleOnPause(); // ★ここ
        }
    });

    //super.onPause();
}

Cocos2dxRenderer.java

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

Java_org_cocos2dx_lib_Cocos2dxRenderer.cpp

JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnPause() {

    CCApplication::sharedApplication()->applicationDidEnterBackground(); // ★ここやね
    
    CCNotificationCenter::sharedNotificationCenter()->postNotification(EVENT_COME_TO_BACKGROUND, NULL);
}

JNIで呼ばれたタイミングですでにCCApplicationが死んでいる?というのはどうも考えにくい。。。 というわけで、上記にログを仕込んでみる。

Java_org_cocos2dx_lib_Cocos2dxRenderer.cpp

JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeOnPause() {
    
    CCLog("CCApplication = %s", sm_pSharedApplication); // ★追加
    
    CCApplication::sharedApplication()->applicationDidEnterBackground(); 
    
    CCNotificationCenter::sharedNotificationCenter()->postNotification(EVENT_COME_TO_BACKGROUND, NULL);
}

実行してみる

08-29 11:28:40.484: D/HelloWorldProjct(5030): Upgrade button clicked; launching purchase flow for upgrade.
08-29 11:28:40.488: D/IabHelper(5030): Starting async operation: launchPurchaseFlow
08-29 11:28:40.542: D/HelloWorldProjct(5030): #################### onPause
08-29 11:28:40.542: D/MyCocos2dxActivity(5030): Cocos2dxHelper.onPause()
08-29 11:28:40.542: D/cocos2d-x debug info(5030): CCApplication = (null)
08-29 11:28:40.542: E/cocos2d-x assert(5030): /Applications/cocos2d-x-2.1.4/projects/HelloWorldProjct/proj.android/../../../cocos2dx/platform/android/CCApplication.cpp function:sharedApplication line:62

見事落ちた。。。nullってます。

とまあ、ここまで追って理解。 アプリ起動時(onCreateメソッド内)にてWebViewを前面表示し、GLSurfaceViewを非表示にしていたのですが、どうやらこれが原因で、GLThread側の初期処理が終わってなかったみたいです・・・

mGLSurfaceView.setVisibility(View.GONE);

対処方法

最初に表示するSceneの表示終了時にJava側のメソッドを呼び出してそこで画面を非表示にするように修正しました。

呼び出し順のログ

08-29 14:25:22.230: D/cocos2d-x debug info(1203): ######## init
08-29 14:25:22.265: W/GLThread(1203): onSurfaceChanged(480, 800)
08-29 14:25:22.269: D/cocos2d-x debug info(1203): ######## onEnter
08-29 14:25:22.269: D/cocos2d-x debug info(1203): ######## onEnterTransitionDidFinish
08-29 14:25:22.269: D/HelloWorldProjct(1203): onInitSceneEnter! ThreadName = GLThread 12

HelloWorldScene.cpp

void HelloWorld::onEnter()
{
    CCLayer::onEnter(); // super呼び出し

    CCLog("######## onEnter");
}

void HelloWorld::onEnterTransitionDidFinish()
{
    CCLayer::onEnterTransitionDidFinish(); // super呼び出し

    CCLog("######## onEnterTransitionDidFinish");
    // Java呼び出し
    NativeLauncher::launchNativeInitSceneFinish();
}

見事落ちなくなりました。