facebook twitter hatena line email

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

提供: 初心者エンジニアの簡易メモ
移動: 案内検索

サンプルコード

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);
    for (CCSampleInit* _sample : samples) {
        log("CCSampleInit level=%d", _sample->name);
        log("CCSampleInit level=%d", _sample->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();
    }
}

参考

https://teratail.com/questions/71591