Well we all like cross programming I guess and especially when it works 🙂
Here is a c++ class that can call JNI or IOS methods according to the running platform. With it you can execute any native (openUrl,market etc. ) function. Be sure to see the examples for Android and IOS.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#ifndef NATIVEINTERFACE_H_ #define NATIVEINTERFACE_H_ #include "cocos2d.h" using namespace cocos2d; class NativeInterface { public: CCString * nativeCallback(const char* str); NativeInterface(); virtual ~NativeInterface(); }; #endif /* NATIVEINTERFACE_H_ */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
#include "NativeInterface.h" #if(CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #include "platform/android/jni/JniHelper.h" #include "platform/CCCommon.h" #endif #if(CC_TARGET_PLATFORM == CC_PLATFORM_IOS) #include "IOSHelper.h" #endif #include <string> using namespace std; CCString * NativeInterface::nativeCallback(const char* str){ #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) // won't compile this part if IOS JniMethodInfo minfo; if(JniHelper::getStaticMethodInfo(minfo, "com/example/package/path/JniHelper", "open", "(Ljava/lang/String;)Ljava/lang/String;")) { string tmp(str); tmp = tmp + " from Android"; jstring message = minfo.env->NewStringUTF(tmp.c_str()); jstring return_value = (jstring) minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID, message); string ret = JniHelper::jstring2string(return_value); CCString *sret = CCString::create("ef"); minfo.env->DeleteLocalRef(message); //minfo.env->DeleteLocalRef(return_value); minfo.env->DeleteLocalRef(minfo.classID); return sret; } #elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) // won't compile this part if ANDROID IOSHelper *hios = new IOSHelper(); string tmp(str); string ret = hios->nativeCallback(tmp); CCString *sret = CCString::create(ret.c_str()); return sret; #endif CCString *pret = CCString::create("none"); return pret; } NativeInterface::NativeInterface() { } NativeInterface::~NativeInterface() { } |
Okay we have
Notice the method I’ll be calling has one parameter and a return value both string. If you want to use another method like void with no return value you should change the method signature in NativeInterface.cpp, 4th parameter of JniHelper::getStaticMethodInfo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
//everybody has this class under src folder, it starts you cocos2d app/game package com.donkeycat.RankMaster; import org.cocos2dx.lib.Cocos2dxActivity; import android.os.Bundle; public class MyGame extends Cocos2dxActivity{ protected JniHelper mHelper; protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); mHelper = new JniHelper(this); } static { System.loadLibrary("game"); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
package com.example.MyGame; import android.app.Activity; import android.content.Intent; import android.util.Log; public class JniHelper { static Activity activity; public JniHelper(Activity activity){ JniHelper.activity = activity; } public static java.lang.String open(java.lang.String message) { Intent intent = new Intent(JniHelper.activity, MyActivity.class); JniHelper.activity.startActivity(intent); return "Yes No"; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
package com.example.MyGame; import android.os.Bundle; import android.app.Activity; import android.app.AlertDialog; import android.content.DialogInterface; import android.util.Log; import android.view.Menu; public class MyActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); AlertDialog alertDialog = new AlertDialog.Builder(this).create(); Log.v("cocos2dx", "alert create ist done"); alertDialog.setIcon(R.drawable.icon); alertDialog.setButton("OK", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { //here you can add functions } }); alertDialog.show(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } } |
Well this is straight forward, we just have to provide a class like a bridge, which will be included only if the platform is IOS. In Xcode 4 for .mm extension just rename your .cpp file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
#ifndef IOSHELPER_H_ #define IOSHELPER_H_ #include using namespace std; class IOSHelper { public: string nativeCallback(string str,void(*callback)(int index)); IOSHelper(); virtual ~IOSHelper(); }; #endif /* IOSHELPER_H_ */ |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#include "IOSHelper.h" string IOSHelper::nativeCallbackTest(string str,void(*callback)(int index)){ UIAlertView* message=[[UIAlertView alloc] initWithTitle:@"Hello" message:@"ABC" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil]; [message show]; callback(99); return str; } IOSHelper::IOSHelper() { // TODO Auto-generated constructor stub } IOSHelper::~IOSHelper() { // TODO Auto-generated destructor stub } |