1.MessageCenter.h
#ifndef __MESSAGECENTER_H__ #define __MESSAGECENTER_H__ #include <string> #include <list> struct lua_State; class MessageCenter { public: MessageCenter(void); ~MessageCenter(void); static MessageCenter * getInstance(); static int lua_bind_AllFunction(lua_State* tolua_S); void cppSendMessageToJava(const std::string & message); void addMessageToList(const std::string &message); const std::string luaGetMessageFromCpp(); static const std::string classPrefix; static const std::string fullName; static const std::string className; private: static MessageCenter *m_instance; std::list<std::string> m_messageList; }; int lua_cocos2dx_MessageCenter_getInstance(lua_State* tolua_S); int lua_cocos2dx_MessageCenter_luaGetMessageFromCpp(lua_State* tolua_S); int lua_cocos2dx_MessageCenter_cppSendMessageToJava(lua_State* tolua_S); //void Java_org_cocos2dx_lua_AppActivity_javaSendMessageToCpp(JNIEnv env,jobject thiz,jstring msg) #endif
2.MessageCenter.cpp
#include "MessageCenter.h" #include "tolua_fix.h" #include "LuaBasicConversions.h" #include <stdlib.h> #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) #include <jni.h> #include <android/log.h> #include "platform/android/jni/JniHelper.h" #define LOG_TAG "MessageCenter" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) #endif using namespace cocos2d; const std::string MessageCenter::classPrefix = "cp"; const std::string MessageCenter::className = "MessageCenter"; const std::string MessageCenter::fullName = classPrefix + "." + className; MessageCenter *MessageCenter::m_instance = NULL; MessageCenter::MessageCenter(void) { m_messageList.clear(); } MessageCenter::~MessageCenter(void) { } MessageCenter * MessageCenter::getInstance() { if (!m_instance){ m_instance = new MessageCenter(); } return m_instance; } const std::string MessageCenter::luaGetMessageFromCpp() { if(!m_messageList.empty()) { const std::string message = m_messageList.front(); m_messageList.pop_front(); return message; } return "0"; } void MessageCenter::addMessageToList(const std::string &message) { m_messageList.push_back(message); } void MessageCenter::cppSendMessageToJava(const std::string & message) { CCLOG("sendMessageToJava:%s",message.c_str()); #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) JniMethodInfo jmi; JniHelper::getStaticMethodInfo(jmi,"org/cocos2dx/lua/AppActivity","SendMessage","(Ljava/lang/String;)V"); jstring str = (jmi.env->NewStringUTF(message.c_str())); jmi.env->CallStaticVoidMethod(jmi.classID,jmi.methodID,str); #endif } #if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID) extern "C" { void Java_org_cocos2dx_lua_AppActivity_javaSendMessageToCpp(JNIEnv env,jstring msg) { std::string str = JniHelper::jstring2string(msg); LOGD("javaSendMessageToCpp"); MessageCenter::getInstance()->addMessageToList(str); } } #endif //==============lua bind================ int MessageCenter::lua_bind_AllFunction(lua_State* tolua_S) { lua_getglobal(tolua_S,"_G"); if (lua_istable(tolua_S,-1))//stack:...,_G,{ tolua_open(tolua_S); tolua_module(tolua_S,classPrefix.c_str(),0); tolua_beginmodule(tolua_S,classPrefix.c_str()); tolua_usertype(tolua_S,MessageCenter::fullName.c_str()); tolua_cclass(tolua_S,className.c_str(),MessageCenter::fullName.c_str(),"",nullptr); tolua_beginmodule(tolua_S,className.c_str()); tolua_function(tolua_S,"getInstance",lua_cocos2dx_MessageCenter_getInstance); tolua_function(tolua_S,"cppSendMessageToJava",lua_cocos2dx_MessageCenter_cppSendMessageToJava); tolua_function(tolua_S,"luaGetMessageFromCpp",lua_cocos2dx_MessageCenter_luaGetMessageFromCpp); tolua_endmodule(tolua_S); g_luaType[typeid(MessageCenter).name()] = MessageCenter::fullName; g_typeCast[className] = MessageCenter::fullName; tolua_endmodule(tolua_S); } lua_pop(tolua_S,1); return 1; } int lua_cocos2dx_MessageCenter_getInstance(lua_State* tolua_S) { int argc = 0; MessageCenter* parentOfFunction = nullptr; const std::string &functionString = "'lua_cocos2dx_MessageCenter_getInstance'"; const std::string &luaFunctionString = MessageCenter::fullName + ":getInstance"; #if COCOS2D_DEBUG >= 1 tolua_Error tolua_err; if (!tolua_isusertable(tolua_S,1,&tolua_err)) { tolua_error(tolua_S,("#ferror in function " + functionString).c_str(),&tolua_err); return 0; } parentOfFunction = (MessageCenter*)tolua_tousertype(tolua_S,0); if (!parentOfFunction) { //tolua_error(tolua_S,("invalid 'cobj' in function " + functionString).c_str(),nullptr); //return 0; } #endif argc = lua_gettop(tolua_S) - 1; if (argc == 0) { MessageCenter* ret = MessageCenter::getInstance(); object_to_luaval<MessageCenter>(tolua_S,(MessageCenter*)ret); return 1; } else {luaL_error(tolua_S,"%s has wrong number of arguments: %d,was expecting %d \n",luaFunctionString.c_str(),argc,1);} return 0; } int lua_cocos2dx_MessageCenter_cppSendMessageToJava(lua_State* tolua_S) { int argc = 0; MessageCenter* parentOfFunction = nullptr; bool ok = true; const std::string &functionString = "'lua_cocos2dx_MessageCenter_cppSendMessageToJava'"; const std::string &luaFunctionString = MessageCenter::fullName + ":cppSendMessageToJava"; #if COCOS2D_DEBUG >= 1 tolua_Error tolua_err; if (!tolua_isusertype(tolua_S,&tolua_err); return 0; } #endif parentOfFunction = (MessageCenter*)tolua_tousertype(tolua_S,0); #if COCOS2D_DEBUG >= 1 if (!parentOfFunction) { tolua_error(tolua_S,nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; if (argc == 1) { std::string arg0; ok &= luaval_to_std_string(tolua_S,2,&arg0,luaFunctionString.c_str()); if(!ok) { tolua_error(tolua_S,("invalid arguments in function " + functionString).c_str(),nullptr); return 0; } parentOfFunction->cppSendMessageToJava(arg0); lua_settop(tolua_S,1); return 1; } else {luaL_error(tolua_S,1);} return 0; } int lua_cocos2dx_MessageCenter_luaGetMessageFromCpp(lua_State* tolua_S) { int argc = 0; MessageCenter* parentOfFunction = nullptr; bool ok = true; const std::string &functionString = "'lua_cocos2dx_MessageCenter_luaGetMessageFromCpp'"; const std::string &luaFunctionString = MessageCenter::fullName + ":luaGetMessageFromCpp"; #if COCOS2D_DEBUG >= 1 tolua_Error tolua_err; if (!tolua_isusertype(tolua_S,nullptr); return 0; } #endif argc = lua_gettop(tolua_S) - 1; if (argc == 0) { const std::string &ret = parentOfFunction->luaGetMessageFromCpp(); tolua_pushcppstring(tolua_S,ret); return 1; } else {luaL_error(tolua_S,1);} return 0; }
3. 在AppDelegate.cpp中注册MessageCenter函数
bool AppDelegate::applicationDidFinishLaunching() { // set default FPS Director::getInstance()->setAnimationInterval(1.0 / 60.0f); // register lua module auto engine = LuaEngine::getInstance(); ScriptEngineManager::getInstance()->setScriptEngine(engine); lua_State* L = engine->getLuaStack()->getLuaState(); lua_module_register(L); register_TestLayer(L); TestClass::lua_bind_AllFunction(L); MessageCenter::lua_bind_AllFunction(L); ScreenMatchLayer::lua_bind_AllFunction(L); // If you want to use Quick-Cocos2d-X,please uncomment below code // register_all_quick_manual(L); LuaStack* stack = engine->getLuaStack(); stack->setXXTEAKeyAndSign("2dxLua",strlen("2dxLua"),"XXTEA",strlen("XXTEA")); //register custom function //LuaStack* stack = engine->getLuaStack(); //register_custom_function(stack->getLuaState()); #if (COCOS2D_DEBUG > 0) && (CC_CODE_IDE_DEBUG_SUPPORT > 0) // NOTE:Please don't remove this call if you want to debug with Cocos Code IDE RuntimeEngine::getInstance()->start(); cocos2d::log("iShow!"); #else if (engine->executeScriptFile("src/main.lua")) { return false; } #endif return true; }
4. org.cocos2dx.lua.AppActivity的java文件(AppActivity.java)
/**************************************************************************** Copyright (c) 2008-2010 Ricardo Quesada Copyright (c) 2010-2012 cocos2d-x.org Copyright (c) 2011 Zynga Inc. Copyright (c) 2013-2014 Chukong Technologies Inc. http://www.cocos2d-x.org Permission is hereby granted,free of charge,to any person obtaining a copy of this software and associated documentation files (the "Software"),to deal in the Software without restriction,including without limitation the rights to use,copy,modify,merge,publish,distribute,sublicense,and/or sell copies of the Software,and to permit persons to whom the Software is furnished to do so,subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS",WITHOUT WARRANTY OF ANY KIND,EXPRESS OR IMPLIED,INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,DAMAGES OR OTHER LIABILITY,WHETHER IN AN ACTION OF CONTRACT,TORT OR OTHERWISE,ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ package org.cocos2dx.lua; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.util.Enumeration; import java.util.ArrayList; import org.cocos2dx.lib.Cocos2dxActivity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.ActivityInfo; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.provider.Settings; import android.text.format.Formatter; import android.util.Log; import android.view.KeyEvent; import android.view.WindowManager; import android.widget.Toast; public class AppActivity extends Cocos2dxActivity{ private static Handler handler; static String hostIPAdress = "0.0.0.0"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if(nativeIsLandScape()) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT); } final String packageName = this.getPackageName(); final String ipAddress = this.getHostIpAddress(); final String macAddress = this.getMacAddress(); handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); String message = (String) msg.obj; if(message.equals("love")){ Log.i("wc","isLove"); AppActivity.javaSendMessageToCpp("2001|" + packageName); AppActivity.javaSendMessageToCpp("2002|" + ipAddress); AppActivity.javaSendMessageToCpp("2003|" + macAddress); } Log.i("wc",message); } }; //2.Set the format of window // Check the wifi is opened when the native is debug. if(nativeIsDebug()) { getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); if(!isNetworkConnected()) { AlertDialog.Builder builder=new AlertDialog.Builder(this); builder.setTitle("Warning"); builder.setMessage("Please open WIFI for debuging..."); builder.setPositiveButton("OK",new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog,int which) { startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS)); finish(); System.exit(0); } }); builder.setNegativeButton("Cancel",null); builder.setCancelable(true); builder.show(); } hostIPAdress = getHostIpAddress(); } } private boolean isNetworkConnected() { ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); if (cm != null) { NetworkInfo networkInfo = cm.getActiveNetworkInfo(); ArrayList networkTypes = new ArrayList(); networkTypes.add(ConnectivityManager.TYPE_WIFI); try { networkTypes.add(ConnectivityManager.class.getDeclaredField("TYPE_ETHERNET").getInt(null)); } catch (NoSuchFieldException nsfe) { } catch (IllegalAccessException iae) { throw new RuntimeException(iae); } if (networkInfo != null && networkTypes.contains(networkInfo.getType())) { return true; } } return false; } public String getHostIpAddress() { WifiManager wifiMgr = (WifiManager) getSystemService(WIFI_SERVICE); WifiInfo wifiInfo = wifiMgr.getConnectionInfo(); int ip = wifiInfo.getIpAddress(); return ((ip & 0xFF) + "." + ((ip >>>= 8) & 0xFF) + "." + ((ip >>>= 8) & 0xFF) + "." + ((ip >>>= 8) & 0xFF)); } public static String getLocalIpAddress() { return hostIPAdress; } private void exitApp(){ new AlertDialog.Builder(this).setTitle("退出").setMessage("是否退出游戏") .setPositiveButton("是",new OnClickListener() { @Override public void onClick(DialogInterface dialog,int which) { AppActivity.this.finish(); System.exit(0); } }).setNegativeButton("否",int which) { } }).show(); } private static native boolean nativeIsLandScape(); private static native boolean nativeIsDebug(); private static native void javaSendMessageToCpp(String msg); @Override public boolean onKeyUp(int keyCode,KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { exitApp(); return true; } return super.onKeyUp(keyCode,event); } public String getMacAddress() { WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE); WifiInfo info = wifi.getConnectionInfo(); return info.getMacAddress(); } public static void SendMessage(String msg) { Message message = Message.obtain(); message.obj = msg; AppActivity.handler.sendMessage(message); } }
5. lua中的调用方法
Utility.lua
cc.const = function() if cc.const == nil then cc.const = {} cc._const = {} local function newIndex(t,k,v) if not cc._const[k] then cc._const[k] = v else error("尝试给 const."..k.." 赋值") end end local mt = { __newindex = newIndex,__index = cc._const } setMetatable(cc.const,mt) end return cc.const end local getPackageName = function(msgArray) cc.showTextTips("getPackageName:" .. msgArray[2]) end local getIpAddress = function(msgArray) cc.showTextTips("getIpAddress:" .. msgArray[2]) end local getMacAddress = function(msgArray) cc.showTextTips("getMacAddress:" .. msgArray[2]) end cc.android = { packageName = "",ip = "",mac = "",eventList = { ["2001"] = getPackageName,["2002"] = getIpAddress,["2003"] = getMacAddress },} cc.zOrder = { showTextTips = 100 } function cc.splitStringWithSeparator(str,split_char) local sub_str_tab = {}; while (true) do local pos = string.find(str,split_char); if (not pos) then sub_str_tab[#sub_str_tab + 1] = str; break; end local sub_str = string.sub(str,pos - 1); sub_str_tab[#sub_str_tab + 1] = sub_str; str = string.sub(str,pos + 1,#str); end return sub_str_tab; end function cc.startListenCppMessage() local function event_loop(dtime) local msg = cp.MessageCenter : getInstance() : luaGetMessageFromCpp() if msg ~= nil and msg ~= "0" then local msgArray = cc.splitStringWithSeparator(msg,"|") local code = msgArray[1] if #msgArray > 0 and cc.android.eventList[code] ~= nil then cc.android.eventList[code](msgArray) end end end cc.Director : getInstance() : getScheduler() : scheduleScriptFunc(event_loop,0.1,false) end function cc.showTextTips(text) local scene = cc.Director:getInstance() : getRunningScene() if scene ~= nil and text ~= "" then local function createTextBackgroundWithSize(bgSize) local bgSprite = ccui.Scale9Sprite:create("tips/ui_bg_small.png") bgSprite : setScale9Enabled(true) bgSprite : setContentSize(bgSize) bgSprite : setLocalZOrder(cc.zOrder.showTextTips) bgSprite : setPosition(480,320) return bgSprite end local label = cc.LabelTTF:create(text,"heiti",24) local bgSize = cc.size(label : getContentSize().width + 40,50) local bgSprite = createTextBackgroundWithSize(bgSize) scene : addChild(bgSprite) bgSprite : addChild(label) label : setPosition(bgSize.width / 2,bgSize.height / 2) local actionMove = cc.Sequence:create( cc.MoveBy:create(1.0,cc.p(0,100)),cc.DelayTime:create(0.5),cc.CallFunc:create( function () bgSprite : removeFromParent() end) ) bgSprite : runAction(actionMove) else print("showTextTips error") end end