facebook twitter hatena line email

Cocos2dx/AndroidNative連携/コールバック配列

提供: 初心者エンジニアの簡易メモ
2017年4月10日 (月) 18:31時点におけるAdmin (トーク | 投稿記録)による版 (ページの作成:「==サンプルコード== Delegateを使ったコールバックでクラスの配列を返すサンプル -Classes/SampleDelegate.h #ifndef Helloworld_SampleDelegate_h...」)

(差分) ←前の版 | 最新版 (差分) | 次の版→ (差分)
移動: 案内検索

サンプルコード

Delegateを使ったコールバックでクラスの配列を返すサンプル

-Classes/SampleDelegate.h

#ifndef Helloworld_SampleDelegate_h
#define Helloworld_SampleDelegate_h
#include "CCSampleInit.h"
#include <vector>
class SampleDelegate
{
public:
    virtual void onSampleInitsLoaded(std::vector<CCSampleInit*> sampleInits) = 0;
};
#endif

SampleDelegate.cppは不要

-Classes/NativeLauncher.h

#ifndef Helloworld_NativeLauncher_h
#define Helloworld_NativeLauncher_h
extern "C" {
    class NativeLauncher
    {
    public:
        static void launchOnSampleInitsLoaded();
        static void setDelegate(SampleDelegate*);
        static SampleDelegate* getDelegate();
    };
}
#endif

-Classes/NativeLauncher.cpp

#include "NativeLauncher.h"
#include <jni.h>
#include "platform/android/jni/JniHelper.h"
#include "SampleDelegate.h"
#define CLASS_NAME "org/cocos2dx/cpp/AppActivity"
extern "C" {
   SampleDelegate* mDelegate;
  void NativeLauncher::launchOnSampleInitsLoaded()
   {
       cocos2d::JniMethodInfo t;
       if (cocos2d::JniHelper::getStaticMethodInfo(t, CLASS_NAME, "launchOnSampleInitsLoaded", "()V")) {
           t.env->CallStaticVoidMethod(t.classID, t.methodID);
           t.env->DeleteLocalRef(t.classID);
       }
   }
   void NativeLauncher::setDelegate(SampleDelegate* delegate)
   {
       mDelegate = delegate;
   }
   SampleDelegate* NativeLauncher::getDelegate()
   {
       return mDelegate;
   }
}

-Classes/com_example_helloworld_SampleBridge.h

#include <jni.h>
#ifndef _Included_com_example_helloworld_SampleBridge
#define _Included_com_example_helloworld_SampleBridge
extern "C" {
    JNIEXPORT void JNICALL Java_com_example_helloworld_SampleBridge_cocosOnSampleInitsLoaded(JNIEnv*, jobject, jobjectArray);
}
#endif // com_example_helloworld_SampleBridge

-Classes/com_example_helloworld_SampleBridge.cpp

#include "cocos2d.h"
#include "com_example_helloworld_SampleBridge.h"
#include "NativeLauncher.h"
#include "CCSampleInit.h"
#include <vector>
USING_NS_CC;
extern "C" {
   JNIEXPORT void JNICALL Java_com_example_helloworld_SampleBridge_cocosOnSampleInitsLoaded(JNIEnv* env, jobject thiz, jobjectArray jsampleInits) {
       log("success cocosOnSampleInitsLoaded");
       std::vector<CCSampleInit*> sampleInits;
       SampleDelegate* listener = NativeLauncher::getDelegate();
       if (listener != NULL) {
           int cntSampleInit = env->GetArrayLength(jsampleInits);
           for (int i = 0; i < cntSampleInit; i++) {
               jobject jsampleInitElement = env->GetObjectArrayElement(jsampleInits, i);
               jclass jsampleInit = env->FindClass("com/example/helloworld/SampleInit");
               jfieldID fidName = env->GetFieldID(jsampleInit, "name", "Ljava/lang/String;");
               jfieldID fidLevel = env->GetFieldID(jsampleInit, "level", "I");
               jstring jName = (jstring)env->GetObjectField(jsampleInitElement, fidName);
               const char* utfName = env->GetStringUTFChars(jName, 0);
               CCSampleInit* sampleInit = new CCSampleInit();
               sampleInit->name = utfName;
               sampleInit->level = env->GetIntField(jsampleInitElement, fidLevel);
               sampleInits.push_back(sampleInit);
           }
           listener->onSampleInitsLoaded(sampleInits);
       }
   }
}

-Classes/HelloWorldScene.h

SampleDelegateをimplementし、onSampleInitsLoadedメソッドを追加する

#include "CCSampleInit.h"
#include <vector>
class HelloWorld : public cocos2d::Layer, SampleDelegate
{
public:
    static cocos2d::Scene* createScene();
    virtual bool init();
    // a selector callback
    void menuCloseCallback(cocos2d::Ref* pSender);
    void menuLogCallback(cocos2d::Ref* pSender);
    void onSampleInitsLoaded(std::vector<CCSampleInit*> sampleInits);
    // implement the "static create()" method manually
    CREATE_FUNC(HelloWorld);
};

-Classes/HelloWorldScene.cpp

#include "NativeLauncher.h"
#include "CCSampleInit.h"
#include <string>
#include <vector>
bool HelloWorld::init()
{
// 略
   auto logItem = MenuItemImage::create(
                                          "CloseNormal.png",
                                          "CloseSelected.png",
                                          CC_CALLBACK_1(HelloWorld::menuLogCallback, this));
   logItem->setPosition(Vec2(origin.x + visibleSize.width - logItem->getContentSize().width/2 ,
                                origin.y + visibleSize.height - logItem->getContentSize().height/2));
   auto logmenu = Menu::create(logItem, NULL);
   logmenu->setPosition(Vec2::ZERO);
   this->addChild(logmenu, 1);
// 略
}
void HelloWorld::menuLogCallback(Ref* pSender)
{
    NativeLauncher::launchOnSampleInitsLoaded();
}
void HelloWorld::onSampleInitsLoaded(std::vector<CCSampleInit*> sampleInits) {
    log("CCSampleInit name[0]=%s", sampleInits[0]->name);
    log("CCSampleInit level[0]=%d", sampleInits[0]->level);
    log("CCSampleInit name[1]=%s", sampleInits[1]->name);
    log("CCSampleInit level[1]=%d", sampleInits[1]->level);
}

-Classes/SampleInit.h

#ifndef Helloworld_SampleModule_h
#define Helloworld_SampleModule_h
#include "cocos2d.h"
class CCSampleInit
{
public:
    const char* name = "";
    int level = 0;
};
#endif

-Classes/SampleInit.cpp

#include "CCSampleInit.h"
USING_NS_CC;
CCSampleInit* CCSampleInit::create()
{
   return new CCSampleInit();
}

-proj.android-studio/app/src/org/cocos2dx/cpp/AppActivity.java

import com.example.helloworld.SampleBridge;
public class AppActivity extends Cocos2dxActivity {
    public static void launchOnSampleInitsLoaded() {
       System.out.println("launchOnSampleInitsLoaded()");
       (new SampleBridge()).onSampleInitsLoaded("launchOnSampleInitsLoaded");
    }
}

-proj.android/jni/Android.mk

LOCAL_SRC_FILES := hellocpp/main.cpp \
                   ../../Classes/AppDelegate.cpp \
                   ../../Classes/HelloWorldScene.cpp \
                   ../../Classes/CCSampleInit.cpp \
                   ../../Classes/NativeLauncher.cpp \
                   ../../Classes/com_example_helloworld_SampleBridge.cpp

CCSampleInitとNativeLauncher.cppとcom_example_helloworld_SampleBridge.cppを追加

-proj.android-studio/app/jni/Android.mk

LOCAL_SRC_FILES := hellocpp/main.cpp \
                   ../../../Classes/AppDelegate.cpp \
                   ../../../Classes/HelloWorldScene.cpp \
                   ../../../Classes/CCSampleInit.cpp \
                   ../../../Classes/NativeLauncher.cpp \
                   ../../../Classes/com_example_helloworld_SampleBridge.cpp

CCSampleInitとNativeLauncher.cppとcom_example_helloworld_SampleBridge.cppを追加

-proj.android-studio/app/src/com/example/helloworld/SampleBridge.java

package com.example.helloworld;
/**
 * androidでは(new SampleBridge).onCustomEvent();で呼び出し可能
 */
public class SampleBridge {
    private static native void cocosOnSampleInitsLoaded(SampleInit[] sampleInits);
    public void onSampleInitsLoaded(final String message) {
       Thread thread = new Thread(new Runnable() {
           @Override
           public void run() {
               System.out.println("SampleBridge.onCustomEventArrayObject");
               SampleInit[] sampleInits = new SampleInit[2];
               for (int i = 0; i < 2; i++) {
                   SampleInit sampleInit = new SampleInit();
                   sampleInit.name = "hoge" + i;
                   sampleInit.level = i;
                   sampleInits[i] = sampleInit;
               }
               SampleBridge.cocosOnSampleInitsLoaded(sampleInits);
           }
       });
       thread.start();
    }
}

typeリスト

JNI Types Java Type
void void
jboolean boolean
jbyte byte
jchar char
jshort short
jint int
jlong long
jfloat float
jdouble double
jobject All Java objects
jclass java.lang.Class objects
jstring java.lang.String objects
jobjectArray Array of objects
jbooleanArray Array of booleans
jbyteArray Array of bytes
jshortArray Array of shorts
jintArray Array of integers
jlongArray Array of longs
jfloatArray Array of floats
jdoubleArray Array of doubles

参考:http://stnguyen.com/cocos2d-x/call-cpp-functions-from-java.html

コールバック関数ファイルについて

明示的にcom_example_helloworld_SampleBridge.hに分けて記載してるが、NativeLauncher.hに一緒にしても問題ない。 ただし、iOSなどではこの関数は使わないので分けたほうが良い。

Unable to find source java classエラーが出た場合

一旦android-project側をclean&buildしてみる。

Execution failed for task ':compileDebugJavaWithJavac'エラーが出た場合

一旦android-project側をclean&buildしてみる。