Cocos2d-x 3.x Android Native Activity JNI 연동하기

 Cocos2d-x 가 3.x가 되면서 기본적으로 아래 그림과 같이 안드로이드 자바 소스부분은 필요치 않게 변경이 되었습니다. 이는 안드로이드 Native Activity를 사용하게 되면서 이렇게 되었는데요, 이 부분에 있어서 요즘 이슈가 있는거 같아 R&D를 해봤습니다.


 이렇게 새로운 프로젝트를 만들면 떡하니 nojava.txt가 있어서 당황하실 수 있습니다. 사실 java 파일을 넣어도 작업이 될 듯은 하네요. 해보진 않았지만요.

 아래 정리할 내용은 Cocos2d-x 3.x에 간단하게 네이티브 액티비티와 간단한 JNI 처리하는 내용인데요, 사실 어떻게보면 기존에 정리했던 Cococs2d-x 1.x나 2.x 에서 처리했던 JNI 연동GLThread 이슈 처리와 비슷합니다. 왜냐면 Cocos2d-x에서 하듯이 정석?으로 안하고 간단히 샘플로 정리한 것이기 때문이죠. 정석은 밑에서 잠깐 소개하겠습니다. 또한 현재 3.0 alpha1까지 나왔는데 alpha0과는 폴더구조가 다릅니다. 아래 내용은 alpha1으로 진행한 내용입니다.

 먼저 project-creator을 통해 아래와 같이 프로젝트명은 BasicNativeActivityJNI, 패키지명은 com.westwoodforever.sample.nativeactivityjni 로 만들었습니다.


 C++에서 안드로이드 자바를 호출하기 위해 cocos2d-x-3.0alpha1\cocos\2d\platform\android\jni\Java_org_cocos2dx_lib_Cocos2dxHelper.cpp 를 수정해야 합니다.


void BasicJNICallTest(const char* pszMsg)
{
    JniMethodInfo t;
    //#define  CLASS_NAME "org/cocos2dx/lib/Cocos2dxHelper"
    if (JniHelper::getStaticMethodInfo(t, CLASS_NAME
        , "AndroidJNIFuncCallTestFromCocos2dx3_0"
        , "(Ljava/lang/String;)V")) {
        jstring stringArg1;

        stringArg1 = t.env->NewStringUTF(pszMsg);
        t.env->CallStaticVoidMethod(t.classID, t.methodID, stringArg1);

        t.env->DeleteLocalRef(stringArg1);
        t.env->DeleteLocalRef(t.classID);
    }
}

 위와 같은 내용을 추가합니다. Cocos2dxHelper java파일의 AndroidJNIFuncCallTestFromCocos2dx3_0 이라는 함수를 호출해줍니다. 인자로 스트링 하나 넘기게 했습니다.

extern void BasicJNICallTest(const char* pszMsg);

 Java_org_cocos2dx_lib_Cocos2dxHelper.h 파일에는 위 내용을 추가합니다.


 이제 자바쪽에 JNI로 호출하는 함수를 정의합니다. 아래 그림과 같이 libcocos2dx/src/org.cocos2dx.lib에 있는 Cocos2dxHelper.java를 편집해야합니다.



public static void AndroidJNIFuncCallTestFromCocos2dx3_0(String strTest) {
nativeCocos2dx30CPPFunc(strTest + "->");
}

public static native void nativeCocos2dx30CPPFunc(String text);

 위 내용을 추가합니다. 단순히 인자로 받은 스트링에 -> 를 추가해서 C++에 있는 네이티브 함수를 호출해줍니다.


JNIEXPORT void JNICALL Java_org_cocos2dx_lib_Cocos2dxHelper_nativeCocos2dx30CPPFunc(JNIEnv* env, jobject thiz, jstring strJNIMsg)
{
        string strMsg = JniHelper::jstring2string(strJNIMsg);
        string strFinal = strMsg + "Android JNI Call Test";
        showDialogJNI(strFinal.c_str(), "WestwoodForever");
}

 이제 다시 Java_org_cocos2dx_lib_Cocos2dxHelper.cpp 파일입니다. 위와 같은 내용을 extern "C" { } 안에 추가해줍니다. 안드로이드에서 받은 스트링에 내용을 추가해서 다시 안드로이드에서 메시지 박스 호출을 진행합니다.

// include 추가
#include "jni/Java_org_cocos2dx_lib_Cocos2dxHelper.h"

void HelloWorld::menuCloseCallback(Object* pSender)
{
    //Director::getInstance()->end();
    BasicJNICallTest("Cocos2d-x3.0 JNI NativeC++");

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
    exit(0);
#endif
}

 마지막으로 HelloWorldScene.cpp에 종료 버튼 처리를 위와같이 수정해줍니다.

 이제 아래와 같이 build_native.py를 한번 실행해서 C++을 빌드해주고 이클립스에서는 libcocos2dx와 샘플 프로젝트를 빌드 후 실행해줍니다.



 그리고 실행하면 아래와 같은 결과를 볼 수 있습니다. 결과적으로 C++ 스트링 "Cocos2d-x3.0 JNI NativeC++" + 안드로이드 스트링 "->" + C++ 스트링 "Android JNI Call Test"를 가지고 안드로이드 메시지 박스를 출력했습니다.



 지금까지 정리한 것을 가지고 프로젝트를 진행하는데 별 무리는 없을 듯 합니다. Cocos2d-x 3.x 버전 엔진딴에서 안드로이드 JNI 처리를 어떻게 했는지는 아래 그림과 같이 cocos\2d\platform\android 폴더에 있는 파일들을 분석해보시면 알 수 있습니다.



 하지만 위에서도 말했듯이 이건 샘플수준이고 별로 건들기 싫은? Cococs2d-x 엔진 소스를 건들어줘야 하는 문제가 있습니다. Cocos2d-x 3.x 가 만들어놓은 틀안에서 이런 플러그인 작업을 하실려면 PluginManager 라는 것을 활용해서 해줘야 합니다. 이미 많은 플러그인들이 아래와 같이 통합되어 있습니다. 또한 plugin\samples\HelloPlugins 도 있으니 참고하시면 좋구요.


 기본 구조는 플러그인 안드로이드 이클립스 프로젝트를 만들고 네이티브에서 사용하는 CPP 구조와 안드로이드 실제 플러그인 기능을 처리하는 java 파일들, JNI처리를 해줘야하는 protocol C++ 파일들을 처리해줘야 합니다. 기존에 그냥 안드로이드 Activity에서 처리하던 것을 의존성이 적게 하려고 이런식의 구조를 잡은 것 같습니다.

 여담이지만 작년에 했던 Cocos2d-x 프레임워크가 위에서 설명한 PluginManager와 비슷한 구조로 작업을 했었습니다.

 액티비티에는 PluginManager 역할을 하는 JniMapper라는 클래스를 한줄 초기화 해주고



 JniMapper에서 C++과의 플러그인 메시지 처리를 해줬습니다.



 저도 아래와 같이 플러그인들을 protocol로 만들어 처리했구요.




 실제 JNI를 처리하는 파일도 따로 있었습니다. 이렇게해서 C++에서 사용하는 static lib인 framework.o 파일과 자바에서도 framework.jar로 따로 빼서 처리 했었죠.



 PluginManager를 사용하는 방법은 아래 링크로 대체합니다. 저도 여유가 생기면 추가 정리를 해보겠습니다.

How to Integrate a 3rd party SDK into Plugin-X
Plugin-X Integration Guide for Android
How to do Java things with Android Native Activity

이 블로그의 인기 게시물

CMake Windows에 설치하기

Unity3D 안드로이드 Keystore 생성하기

Unity3D iOS Plugin 만들어 연동하기