From 8d60e11a9fcff18bcfa26f11299c428af68d2b6c Mon Sep 17 00:00:00 2001 From: zhangbin Date: Wed, 24 Apr 2013 09:43:40 +0800 Subject: [PATCH 01/85] Update the JS binding for plugin --- .../auto/jsb_pluginx_admob_auto.cpp | 289 ++++++++++++++++++ .../auto/jsb_pluginx_admob_auto.hpp | 25 ++ .../auto/jsb_pluginx_admob_auto_api.js | 65 ++++ .../auto/jsb_pluginx_alipay_auto.cpp | 2 +- .../auto/jsb_pluginx_flurry_auto.cpp | 2 +- .../jsbindings/auto/jsb_pluginx_nd91_auto.cpp | 2 +- .../auto/jsb_pluginx_protocols_auto.cpp | 196 +++++++----- .../auto/jsb_pluginx_protocols_auto.hpp | 30 +- .../auto/jsb_pluginx_protocols_auto_api.js | 49 ++- .../auto/jsb_pluginx_umeng_auto.cpp | 2 +- .../jsb_pluginx_extension_registration.cpp | 4 +- .../manual/jsb_pluginx_manual_iap.cpp | 89 +++++- .../manual/jsb_pluginx_manual_iap.h | 2 +- plugin/plugins/admob/jsb_admob.ini | 6 +- plugin/protocols/jsb_protocols.ini | 8 +- plugin/tools/tojs/genbindings-all.sh | 2 +- 16 files changed, 650 insertions(+), 123 deletions(-) create mode 100644 plugin/jsbindings/auto/jsb_pluginx_admob_auto.cpp create mode 100644 plugin/jsbindings/auto/jsb_pluginx_admob_auto.hpp create mode 100644 plugin/jsbindings/auto/jsb_pluginx_admob_auto_api.js diff --git a/plugin/jsbindings/auto/jsb_pluginx_admob_auto.cpp b/plugin/jsbindings/auto/jsb_pluginx_admob_auto.cpp new file mode 100644 index 0000000000..a1372eadd0 --- /dev/null +++ b/plugin/jsbindings/auto/jsb_pluginx_admob_auto.cpp @@ -0,0 +1,289 @@ +#include "jsb_pluginx_admob_auto.hpp" +#include "jsb_pluginx_spidermonkey_specifics.h" +#include "jsb_pluginx_basic_conversions.h" +using namespace pluginx; +#include "AdsAdmob.h" + +template +static JSBool dummy_constructor(JSContext *cx, uint32_t argc, jsval *vp) { + TypeTest t; + T* cobj = new T(); + js_type_class_t *p; + uint32_t typeId = t.s_id(); + HASH_FIND_INT(_js_global_type_ht, &typeId, p); + assert(p); + JSObject *_tmp = JS_NewObject(cx, p->jsclass, p->proto, p->parentProto); + js_proxy_t *pp; + JS_NEW_PROXY(pp, cobj, _tmp); + JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(_tmp)); + + return JS_TRUE; +} + +static JSBool empty_constructor(JSContext *cx, uint32_t argc, jsval *vp) { + return JS_FALSE; +} + + +JSClass *jsb_AdsAdmob_class; +JSObject *jsb_AdsAdmob_prototype; + +JSBool js_pluginx_admob_AdsAdmob_addTestDevice(JSContext *cx, uint32_t argc, jsval *vp) +{ + jsval *argv = JS_ARGV(cx, vp); + JSBool ok = JS_TRUE; + JSObject *obj = JS_THIS_OBJECT(cx, vp); + js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); + cocos2d::plugin::AdsAdmob* cobj = (cocos2d::plugin::AdsAdmob *)(proxy ? proxy->ptr : NULL); + JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); + if (argc == 1) { + const char* arg0; + std::string arg0_tmp; ok &= jsval_to_std_string(cx, argv[0], &arg0_tmp); arg0 = arg0_tmp.c_str(); + JSB_PRECONDITION2(ok, cx, JS_FALSE, "Error processing arguments"); + cobj->addTestDevice(arg0); + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; + } + + JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 1); + return JS_FALSE; +} +JSBool js_pluginx_admob_AdsAdmob_hideBannerAd(JSContext *cx, uint32_t argc, jsval *vp) +{ + JSObject *obj = JS_THIS_OBJECT(cx, vp); + js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); + cocos2d::plugin::AdsAdmob* cobj = (cocos2d::plugin::AdsAdmob *)(proxy ? proxy->ptr : NULL); + JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); + if (argc == 0) { + cobj->hideBannerAd(); + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; + } + + JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0); + return JS_FALSE; +} +JSBool js_pluginx_admob_AdsAdmob_showBannerAd(JSContext *cx, uint32_t argc, jsval *vp) +{ + jsval *argv = JS_ARGV(cx, vp); + JSBool ok = JS_TRUE; + JSObject *obj = JS_THIS_OBJECT(cx, vp); + js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); + cocos2d::plugin::AdsAdmob* cobj = (cocos2d::plugin::AdsAdmob *)(proxy ? proxy->ptr : NULL); + JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); + if (argc == 2) { + cocos2d::plugin::ProtocolAds::EBannerPos arg0; + int arg1; + ok &= jsval_to_int32(cx, argv[0], (int32_t *)&arg0); + ok &= jsval_to_int32(cx, argv[1], (int32_t *)&arg1); + JSB_PRECONDITION2(ok, cx, JS_FALSE, "Error processing arguments"); + cobj->showBannerAd(arg0, arg1); + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; + } + + JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 2); + return JS_FALSE; +} +JSBool js_pluginx_admob_AdsAdmob_getPluginName(JSContext *cx, uint32_t argc, jsval *vp) +{ + JSObject *obj = JS_THIS_OBJECT(cx, vp); + js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); + cocos2d::plugin::AdsAdmob* cobj = (cocos2d::plugin::AdsAdmob *)(proxy ? proxy->ptr : NULL); + JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); + if (argc == 0) { + const char* ret = cobj->getPluginName(); + jsval jsret; + jsret = c_string_to_jsval(cx, ret); + JS_SET_RVAL(cx, vp, jsret); + return JS_TRUE; + } + + JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0); + return JS_FALSE; +} +JSBool js_pluginx_admob_AdsAdmob_getPluginVersion(JSContext *cx, uint32_t argc, jsval *vp) +{ + JSObject *obj = JS_THIS_OBJECT(cx, vp); + js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); + cocos2d::plugin::AdsAdmob* cobj = (cocos2d::plugin::AdsAdmob *)(proxy ? proxy->ptr : NULL); + JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); + if (argc == 0) { + const char* ret = cobj->getPluginVersion(); + jsval jsret; + jsret = c_string_to_jsval(cx, ret); + JS_SET_RVAL(cx, vp, jsret); + return JS_TRUE; + } + + JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0); + return JS_FALSE; +} +JSBool js_pluginx_admob_AdsAdmob_init(JSContext *cx, uint32_t argc, jsval *vp) +{ + JSObject *obj = JS_THIS_OBJECT(cx, vp); + js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); + cocos2d::plugin::AdsAdmob* cobj = (cocos2d::plugin::AdsAdmob *)(proxy ? proxy->ptr : NULL); + JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); + if (argc == 0) { + bool ret = cobj->init(); + jsval jsret; + jsret = BOOLEAN_TO_JSVAL(ret); + JS_SET_RVAL(cx, vp, jsret); + return JS_TRUE; + } + + JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0); + return JS_FALSE; +} +JSBool js_pluginx_admob_AdsAdmob_initAppInfo(JSContext *cx, uint32_t argc, jsval *vp) +{ + jsval *argv = JS_ARGV(cx, vp); + JSBool ok = JS_TRUE; + JSObject *obj = JS_THIS_OBJECT(cx, vp); + js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); + cocos2d::plugin::AdsAdmob* cobj = (cocos2d::plugin::AdsAdmob *)(proxy ? proxy->ptr : NULL); + JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); + if (argc == 1) { + TAppInfo arg0; + #pragma warning NO CONVERSION TO NATIVE FOR TAppInfo; + JSB_PRECONDITION2(ok, cx, JS_FALSE, "Error processing arguments"); + cobj->initAppInfo(arg0); + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; + } + + JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 1); + return JS_FALSE; +} +JSBool js_pluginx_admob_AdsAdmob_getSDKVersion(JSContext *cx, uint32_t argc, jsval *vp) +{ + JSObject *obj = JS_THIS_OBJECT(cx, vp); + js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); + cocos2d::plugin::AdsAdmob* cobj = (cocos2d::plugin::AdsAdmob *)(proxy ? proxy->ptr : NULL); + JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); + if (argc == 0) { + const char* ret = cobj->getSDKVersion(); + jsval jsret; + jsret = c_string_to_jsval(cx, ret); + JS_SET_RVAL(cx, vp, jsret); + return JS_TRUE; + } + + JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0); + return JS_FALSE; +} +JSBool js_pluginx_admob_AdsAdmob_setDebugMode(JSContext *cx, uint32_t argc, jsval *vp) +{ + jsval *argv = JS_ARGV(cx, vp); + JSBool ok = JS_TRUE; + JSObject *obj = JS_THIS_OBJECT(cx, vp); + js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); + cocos2d::plugin::AdsAdmob* cobj = (cocos2d::plugin::AdsAdmob *)(proxy ? proxy->ptr : NULL); + JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); + if (argc == 1) { + JSBool arg0; + ok &= JS_ValueToBoolean(cx, argv[0], &arg0); + JSB_PRECONDITION2(ok, cx, JS_FALSE, "Error processing arguments"); + cobj->setDebugMode(arg0); + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; + } + + JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 1); + return JS_FALSE; +} + + +extern JSObject *jsb_ProtocolAds_prototype; + +void js_pluginx_admob_AdsAdmob_finalize(JSFreeOp *fop, JSObject *obj) { + js_proxy_t* nproxy; + js_proxy_t* jsproxy; + JS_GET_NATIVE_PROXY(jsproxy, obj); + if (jsproxy) { + JS_GET_PROXY(nproxy, jsproxy->ptr); + +// cocos2d::plugin::AdsAdmob *nobj = static_cast(nproxy->ptr); +// if (nobj) +// delete nobj; + + JS_REMOVE_PROXY(nproxy, jsproxy); + } +} + +void js_register_pluginx_admob_AdsAdmob(JSContext *cx, JSObject *global) { + jsb_AdsAdmob_class = (JSClass *)calloc(1, sizeof(JSClass)); + jsb_AdsAdmob_class->name = "AdsAdmob"; + jsb_AdsAdmob_class->addProperty = JS_PropertyStub; + jsb_AdsAdmob_class->delProperty = JS_PropertyStub; + jsb_AdsAdmob_class->getProperty = JS_PropertyStub; + jsb_AdsAdmob_class->setProperty = JS_StrictPropertyStub; + jsb_AdsAdmob_class->enumerate = JS_EnumerateStub; + jsb_AdsAdmob_class->resolve = JS_ResolveStub; + jsb_AdsAdmob_class->convert = JS_ConvertStub; + jsb_AdsAdmob_class->finalize = js_pluginx_admob_AdsAdmob_finalize; + jsb_AdsAdmob_class->flags = JSCLASS_HAS_RESERVED_SLOTS(2); + + JSPropertySpec *properties = NULL; + + static JSFunctionSpec funcs[] = { + JS_FN("addTestDevice", js_pluginx_admob_AdsAdmob_addTestDevice, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("hideBannerAd", js_pluginx_admob_AdsAdmob_hideBannerAd, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("showBannerAd", js_pluginx_admob_AdsAdmob_showBannerAd, 2, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("getPluginName", js_pluginx_admob_AdsAdmob_getPluginName, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("getPluginVersion", js_pluginx_admob_AdsAdmob_getPluginVersion, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("init", js_pluginx_admob_AdsAdmob_init, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("initAppInfo", js_pluginx_admob_AdsAdmob_initAppInfo, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("getSDKVersion", js_pluginx_admob_AdsAdmob_getSDKVersion, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("setDebugMode", js_pluginx_admob_AdsAdmob_setDebugMode, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FS_END + }; + + JSFunctionSpec *st_funcs = NULL; + + jsb_AdsAdmob_prototype = JS_InitClass( + cx, global, + jsb_ProtocolAds_prototype, + jsb_AdsAdmob_class, + empty_constructor, 0, + properties, + funcs, + NULL, // no static properties + st_funcs); + // make the class enumerable in the registered namespace + JSBool found; + JS_SetPropertyAttributes(cx, global, "AdsAdmob", JSPROP_ENUMERATE | JSPROP_READONLY, &found); + + // add the proto and JSClass to the type->js info hash table + TypeTest t; + js_type_class_t *p; + uint32_t typeId = t.s_id(); + HASH_FIND_INT(_js_global_type_ht, &typeId, p); + if (!p) { + p = (js_type_class_t *)malloc(sizeof(js_type_class_t)); + p->type = typeId; + p->jsclass = jsb_AdsAdmob_class; + p->proto = jsb_AdsAdmob_prototype; + p->parentProto = jsb_ProtocolAds_prototype; + HASH_ADD_INT(_js_global_type_ht, type, p); + } +} + +void register_all_pluginx_admob(JSContext* cx, JSObject* obj) { + // first, try to get the ns + jsval nsval; + JSObject *ns; + JS_GetProperty(cx, obj, "plugin", &nsval); + if (nsval == JSVAL_VOID) { + ns = JS_NewObject(cx, NULL, NULL, NULL); + nsval = OBJECT_TO_JSVAL(ns); + JS_SetProperty(cx, obj, "plugin", &nsval); + } else { + JS_ValueToObject(cx, nsval, &ns); + } + obj = ns; + + js_register_pluginx_admob_AdsAdmob(cx, obj); +} + diff --git a/plugin/jsbindings/auto/jsb_pluginx_admob_auto.hpp b/plugin/jsbindings/auto/jsb_pluginx_admob_auto.hpp new file mode 100644 index 0000000000..acae9ba32d --- /dev/null +++ b/plugin/jsbindings/auto/jsb_pluginx_admob_auto.hpp @@ -0,0 +1,25 @@ +#ifndef __pluginx_admob_h__ +#define __pluginx_admob_h__ + +#include "jsapi.h" +#include "jsfriendapi.h" + + +extern JSClass *jsb_AdsAdmob_class; +extern JSObject *jsb_AdsAdmob_prototype; + +JSBool js_pluginx_admob_AdsAdmob_constructor(JSContext *cx, uint32_t argc, jsval *vp); +void js_pluginx_admob_AdsAdmob_finalize(JSContext *cx, JSObject *obj); +void js_register_pluginx_admob_AdsAdmob(JSContext *cx, JSObject *global); +void register_all_pluginx_admob(JSContext* cx, JSObject* obj); +JSBool js_pluginx_admob_AdsAdmob_addTestDevice(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_admob_AdsAdmob_hideBannerAd(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_admob_AdsAdmob_showBannerAd(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_admob_AdsAdmob_getPluginName(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_admob_AdsAdmob_getPluginVersion(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_admob_AdsAdmob_init(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_admob_AdsAdmob_initAppInfo(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_admob_AdsAdmob_getSDKVersion(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_admob_AdsAdmob_setDebugMode(JSContext *cx, uint32_t argc, jsval *vp); +#endif + diff --git a/plugin/jsbindings/auto/jsb_pluginx_admob_auto_api.js b/plugin/jsbindings/auto/jsb_pluginx_admob_auto_api.js new file mode 100644 index 0000000000..1c79435300 --- /dev/null +++ b/plugin/jsbindings/auto/jsb_pluginx_admob_auto_api.js @@ -0,0 +1,65 @@ +/** + * @module pluginx_admob + */ +var plugin = plugin || {}; + +/** + * @class AdsAdmob + */ +plugin.AdsAdmob = { + +/** + * @method addTestDevice + * @param {const char*} + */ +addTestDevice : function () {}, + +/** + * @method hideBannerAd + */ +hideBannerAd : function () {}, + +/** + * @method showBannerAd + * @param {cocos2d::plugin::ProtocolAds::EBannerPos} + * @param {int} + */ +showBannerAd : function () {}, + +/** + * @method getPluginName + * @return A value converted from C/C++ "const char*" + */ +getPluginName : function () {}, + +/** + * @method getPluginVersion + * @return A value converted from C/C++ "const char*" + */ +getPluginVersion : function () {}, + +/** + * @method init + * @return A value converted from C/C++ "bool" + */ +init : function () {}, + +/** + * @method initAppInfo + * @param {TAppInfo} + */ +initAppInfo : function () {}, + +/** + * @method getSDKVersion + * @return A value converted from C/C++ "const char*" + */ +getSDKVersion : function () {}, + +/** + * @method setDebugMode + * @param {bool} + */ +setDebugMode : function () {}, + +}; diff --git a/plugin/jsbindings/auto/jsb_pluginx_alipay_auto.cpp b/plugin/jsbindings/auto/jsb_pluginx_alipay_auto.cpp index 7ab36bbb2b..75bc1fc9b8 100644 --- a/plugin/jsbindings/auto/jsb_pluginx_alipay_auto.cpp +++ b/plugin/jsbindings/auto/jsb_pluginx_alipay_auto.cpp @@ -198,7 +198,7 @@ void js_register_pluginx_alipay_IAPAlipay(JSContext *cx, JSObject *global) { JS_FN("payForProduct", js_pluginx_alipay_IAPAlipay_payForProduct, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("getSDKVersion", js_pluginx_alipay_IAPAlipay_getSDKVersion, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("setDebugMode", js_pluginx_alipay_IAPAlipay_setDebugMode, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), - JS_FS_END + JS_FS_END }; JSFunctionSpec *st_funcs = NULL; diff --git a/plugin/jsbindings/auto/jsb_pluginx_flurry_auto.cpp b/plugin/jsbindings/auto/jsb_pluginx_flurry_auto.cpp index ee847c19fe..3a7c14ba58 100644 --- a/plugin/jsbindings/auto/jsb_pluginx_flurry_auto.cpp +++ b/plugin/jsbindings/auto/jsb_pluginx_flurry_auto.cpp @@ -523,7 +523,7 @@ void js_register_pluginx_flurry_AnalyticsFlurry(JSContext *cx, JSObject *global) JS_FN("logTimedEventEnd", js_pluginx_flurry_AnalyticsFlurry_logTimedEventEnd, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("getSDKVersion", js_pluginx_flurry_AnalyticsFlurry_getSDKVersion, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("setDebugMode", js_pluginx_flurry_AnalyticsFlurry_setDebugMode, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), - JS_FS_END + JS_FS_END }; JSFunctionSpec *st_funcs = NULL; diff --git a/plugin/jsbindings/auto/jsb_pluginx_nd91_auto.cpp b/plugin/jsbindings/auto/jsb_pluginx_nd91_auto.cpp index 2b1f7de387..4f4b45bfbf 100644 --- a/plugin/jsbindings/auto/jsb_pluginx_nd91_auto.cpp +++ b/plugin/jsbindings/auto/jsb_pluginx_nd91_auto.cpp @@ -198,7 +198,7 @@ void js_register_pluginx_nd91_IAPNd91(JSContext *cx, JSObject *global) { JS_FN("payForProduct", js_pluginx_nd91_IAPNd91_payForProduct, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("getSDKVersion", js_pluginx_nd91_IAPNd91_getSDKVersion, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("setDebugMode", js_pluginx_nd91_IAPNd91_setDebugMode, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), - JS_FS_END + JS_FS_END }; JSFunctionSpec *st_funcs = NULL; diff --git a/plugin/jsbindings/auto/jsb_pluginx_protocols_auto.cpp b/plugin/jsbindings/auto/jsb_pluginx_protocols_auto.cpp index 3f27495a77..ae2a606ec0 100644 --- a/plugin/jsbindings/auto/jsb_pluginx_protocols_auto.cpp +++ b/plugin/jsbindings/auto/jsb_pluginx_protocols_auto.cpp @@ -5,7 +5,7 @@ using namespace pluginx; #include "PluginManager.h" #include "ProtocolAnalytics.h" #include "ProtocolIAP.h" -#include "ProtocolIAPOnLine.h" +#include "ProtocolAds.h" template static JSBool dummy_constructor(JSContext *cx, uint32_t argc, jsval *vp) { @@ -181,7 +181,7 @@ void js_register_pluginx_protocols_PluginProtocol(JSContext *cx, JSObject *globa JS_FN("getPluginVersion", js_pluginx_protocols_PluginProtocol_getPluginVersion, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("init", js_pluginx_protocols_PluginProtocol_init, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("setDebugMode", js_pluginx_protocols_PluginProtocol_setDebugMode, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), - JS_FS_END + JS_FS_END }; JSFunctionSpec *st_funcs = NULL; @@ -334,7 +334,7 @@ void js_register_pluginx_protocols_PluginManager(JSContext *cx, JSObject *global static JSFunctionSpec funcs[] = { JS_FN("unloadPlugin", js_pluginx_protocols_PluginManager_unloadPlugin, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("loadPlugin", js_pluginx_protocols_PluginManager_loadPlugin, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), - JS_FS_END + JS_FS_END }; static JSFunctionSpec st_funcs[] = { @@ -682,7 +682,7 @@ void js_register_pluginx_protocols_ProtocolAnalytics(JSContext *cx, JSObject *gl JS_FN("logTimedEventEnd", js_pluginx_protocols_ProtocolAnalytics_logTimedEventEnd, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("getSDKVersion", js_pluginx_protocols_ProtocolAnalytics_getSDKVersion, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("setDebugMode", js_pluginx_protocols_ProtocolAnalytics_setDebugMode, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), - JS_FS_END + JS_FS_END }; JSFunctionSpec *st_funcs = NULL; @@ -907,7 +907,7 @@ void js_register_pluginx_protocols_ProtocolIAP(JSContext *cx, JSObject *global) JS_FN("getSDKVersion", js_pluginx_protocols_ProtocolIAP_getSDKVersion, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("setDebugMode", js_pluginx_protocols_ProtocolIAP_setDebugMode, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("getPluginName", js_pluginx_protocols_ProtocolIAP_getPluginName, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), - JS_FS_END + JS_FS_END }; static JSFunctionSpec st_funcs[] = { @@ -944,34 +944,68 @@ void js_register_pluginx_protocols_ProtocolIAP(JSContext *cx, JSObject *global) } -JSClass *jsb_ProtocolIAPOnLine_class; -JSObject *jsb_ProtocolIAPOnLine_prototype; +JSClass *jsb_ProtocolAds_class; +JSObject *jsb_ProtocolAds_prototype; -JSBool js_pluginx_protocols_ProtocolIAPOnLine_initDeveloperInfo(JSContext *cx, uint32_t argc, jsval *vp) +JSBool js_pluginx_protocols_ProtocolAds_hideBannerAd(JSContext *cx, uint32_t argc, jsval *vp) +{ + JSObject *obj = JS_THIS_OBJECT(cx, vp); + js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); + cocos2d::plugin::ProtocolAds* cobj = (cocos2d::plugin::ProtocolAds *)(proxy ? proxy->ptr : NULL); + JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); + if (argc == 0) { + cobj->hideBannerAd(); + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; + } + + JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0); + return JS_FALSE; +} +JSBool js_pluginx_protocols_ProtocolAds_showBannerAd(JSContext *cx, uint32_t argc, jsval *vp) { jsval *argv = JS_ARGV(cx, vp); JSBool ok = JS_TRUE; JSObject *obj = JS_THIS_OBJECT(cx, vp); js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); - cocos2d::plugin::ProtocolIAPOnLine* cobj = (cocos2d::plugin::ProtocolIAPOnLine *)(proxy ? proxy->ptr : NULL); + cocos2d::plugin::ProtocolAds* cobj = (cocos2d::plugin::ProtocolAds *)(proxy ? proxy->ptr : NULL); JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); - if (argc == 1) { - TDeveloperInfo arg0; - ok &= jsval_to_TDeveloperInfo(cx, argv[0], &arg0); + if (argc == 2) { + cocos2d::plugin::ProtocolAds::EBannerPos arg0; + int arg1; + ok &= jsval_to_int32(cx, argv[0], (int32_t *)&arg0); + ok &= jsval_to_int32(cx, argv[1], (int32_t *)&arg1); JSB_PRECONDITION2(ok, cx, JS_FALSE, "Error processing arguments"); - cobj->initDeveloperInfo(arg0); + cobj->showBannerAd(arg0, arg1); JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_TRUE; } - JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 1); + JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 2); return JS_FALSE; } -JSBool js_pluginx_protocols_ProtocolIAPOnLine_getPluginVersion(JSContext *cx, uint32_t argc, jsval *vp) +JSBool js_pluginx_protocols_ProtocolAds_getPluginName(JSContext *cx, uint32_t argc, jsval *vp) { JSObject *obj = JS_THIS_OBJECT(cx, vp); js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); - cocos2d::plugin::ProtocolIAPOnLine* cobj = (cocos2d::plugin::ProtocolIAPOnLine *)(proxy ? proxy->ptr : NULL); + cocos2d::plugin::ProtocolAds* cobj = (cocos2d::plugin::ProtocolAds *)(proxy ? proxy->ptr : NULL); + JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); + if (argc == 0) { + const char* ret = cobj->getPluginName(); + jsval jsret; + jsret = c_string_to_jsval(cx, ret); + JS_SET_RVAL(cx, vp, jsret); + return JS_TRUE; + } + + JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0); + return JS_FALSE; +} +JSBool js_pluginx_protocols_ProtocolAds_getPluginVersion(JSContext *cx, uint32_t argc, jsval *vp) +{ + JSObject *obj = JS_THIS_OBJECT(cx, vp); + js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); + cocos2d::plugin::ProtocolAds* cobj = (cocos2d::plugin::ProtocolAds *)(proxy ? proxy->ptr : NULL); JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); if (argc == 0) { const char* ret = cobj->getPluginVersion(); @@ -984,11 +1018,11 @@ JSBool js_pluginx_protocols_ProtocolIAPOnLine_getPluginVersion(JSContext *cx, ui JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0); return JS_FALSE; } -JSBool js_pluginx_protocols_ProtocolIAPOnLine_init(JSContext *cx, uint32_t argc, jsval *vp) +JSBool js_pluginx_protocols_ProtocolAds_init(JSContext *cx, uint32_t argc, jsval *vp) { JSObject *obj = JS_THIS_OBJECT(cx, vp); js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); - cocos2d::plugin::ProtocolIAPOnLine* cobj = (cocos2d::plugin::ProtocolIAPOnLine *)(proxy ? proxy->ptr : NULL); + cocos2d::plugin::ProtocolAds* cobj = (cocos2d::plugin::ProtocolAds *)(proxy ? proxy->ptr : NULL); JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); if (argc == 0) { bool ret = cobj->init(); @@ -1001,19 +1035,19 @@ JSBool js_pluginx_protocols_ProtocolIAPOnLine_init(JSContext *cx, uint32_t argc, JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0); return JS_FALSE; } -JSBool js_pluginx_protocols_ProtocolIAPOnLine_payForProduct(JSContext *cx, uint32_t argc, jsval *vp) +JSBool js_pluginx_protocols_ProtocolAds_initAppInfo(JSContext *cx, uint32_t argc, jsval *vp) { jsval *argv = JS_ARGV(cx, vp); JSBool ok = JS_TRUE; JSObject *obj = JS_THIS_OBJECT(cx, vp); js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); - cocos2d::plugin::ProtocolIAPOnLine* cobj = (cocos2d::plugin::ProtocolIAPOnLine *)(proxy ? proxy->ptr : NULL); + cocos2d::plugin::ProtocolAds* cobj = (cocos2d::plugin::ProtocolAds *)(proxy ? proxy->ptr : NULL); JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); if (argc == 1) { - TProductInfo arg0; - ok &= jsval_to_TProductInfo(cx, argv[0], &arg0); + TAppInfo arg0; + #pragma warning NO CONVERSION TO NATIVE FOR TAppInfo; JSB_PRECONDITION2(ok, cx, JS_FALSE, "Error processing arguments"); - cobj->payForProduct(arg0); + cobj->initAppInfo(arg0); JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_TRUE; } @@ -1021,11 +1055,11 @@ JSBool js_pluginx_protocols_ProtocolIAPOnLine_payForProduct(JSContext *cx, uint3 JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 1); return JS_FALSE; } -JSBool js_pluginx_protocols_ProtocolIAPOnLine_getSDKVersion(JSContext *cx, uint32_t argc, jsval *vp) +JSBool js_pluginx_protocols_ProtocolAds_getSDKVersion(JSContext *cx, uint32_t argc, jsval *vp) { JSObject *obj = JS_THIS_OBJECT(cx, vp); js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); - cocos2d::plugin::ProtocolIAPOnLine* cobj = (cocos2d::plugin::ProtocolIAPOnLine *)(proxy ? proxy->ptr : NULL); + cocos2d::plugin::ProtocolAds* cobj = (cocos2d::plugin::ProtocolAds *)(proxy ? proxy->ptr : NULL); JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); if (argc == 0) { const char* ret = cobj->getSDKVersion(); @@ -1038,13 +1072,13 @@ JSBool js_pluginx_protocols_ProtocolIAPOnLine_getSDKVersion(JSContext *cx, uint3 JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0); return JS_FALSE; } -JSBool js_pluginx_protocols_ProtocolIAPOnLine_setDebugMode(JSContext *cx, uint32_t argc, jsval *vp) +JSBool js_pluginx_protocols_ProtocolAds_setDebugMode(JSContext *cx, uint32_t argc, jsval *vp) { jsval *argv = JS_ARGV(cx, vp); JSBool ok = JS_TRUE; JSObject *obj = JS_THIS_OBJECT(cx, vp); js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); - cocos2d::plugin::ProtocolIAPOnLine* cobj = (cocos2d::plugin::ProtocolIAPOnLine *)(proxy ? proxy->ptr : NULL); + cocos2d::plugin::ProtocolAds* cobj = (cocos2d::plugin::ProtocolAds *)(proxy ? proxy->ptr : NULL); JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); if (argc == 1) { JSBool arg0; @@ -1058,34 +1092,50 @@ JSBool js_pluginx_protocols_ProtocolIAPOnLine_setDebugMode(JSContext *cx, uint32 JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 1); return JS_FALSE; } -JSBool js_pluginx_protocols_ProtocolIAPOnLine_getPluginName(JSContext *cx, uint32_t argc, jsval *vp) +JSBool js_pluginx_protocols_ProtocolAds_presentScreen(JSContext *cx, uint32_t argc, jsval *vp) { - JSObject *obj = JS_THIS_OBJECT(cx, vp); - js_proxy_t *proxy; JS_GET_NATIVE_PROXY(proxy, obj); - cocos2d::plugin::ProtocolIAPOnLine* cobj = (cocos2d::plugin::ProtocolIAPOnLine *)(proxy ? proxy->ptr : NULL); - JSB_PRECONDITION2( cobj, cx, JS_FALSE, "Invalid Native Object"); if (argc == 0) { - const char* ret = cobj->getPluginName(); - jsval jsret; - jsret = c_string_to_jsval(cx, ret); - JS_SET_RVAL(cx, vp, jsret); + cocos2d::plugin::ProtocolAds::presentScreen(); + JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_TRUE; } - - JS_ReportError(cx, "wrong number of arguments: %d, was expecting %d", argc, 0); + JS_ReportError(cx, "wrong number of arguments"); return JS_FALSE; } -JSBool js_pluginx_protocols_ProtocolIAPOnLine_payFailedLocally(JSContext *cx, uint32_t argc, jsval *vp) + +JSBool js_pluginx_protocols_ProtocolAds_receiveAd(JSContext *cx, uint32_t argc, jsval *vp) +{ + if (argc == 0) { + cocos2d::plugin::ProtocolAds::receiveAd(); + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; + } + JS_ReportError(cx, "wrong number of arguments"); + return JS_FALSE; +} + +JSBool js_pluginx_protocols_ProtocolAds_failedToReceiveAd(JSContext *cx, uint32_t argc, jsval *vp) { jsval *argv = JS_ARGV(cx, vp); JSBool ok = JS_TRUE; if (argc == 2) { - cocos2d::plugin::EPayResult arg0; + cocos2d::plugin::AdListener::EAdErrorCode arg0; const char* arg1; ok &= jsval_to_int32(cx, argv[0], (int32_t *)&arg0); std::string arg1_tmp; ok &= jsval_to_std_string(cx, argv[1], &arg1_tmp); arg1 = arg1_tmp.c_str(); JSB_PRECONDITION2(ok, cx, JS_FALSE, "Error processing arguments"); - cocos2d::plugin::ProtocolIAPOnLine::payFailedLocally(arg0, arg1); + cocos2d::plugin::ProtocolAds::failedToReceiveAd(arg0, arg1); + JS_SET_RVAL(cx, vp, JSVAL_VOID); + return JS_TRUE; + } + JS_ReportError(cx, "wrong number of arguments"); + return JS_FALSE; +} + +JSBool js_pluginx_protocols_ProtocolAds_dismissScreen(JSContext *cx, uint32_t argc, jsval *vp) +{ + if (argc == 0) { + cocos2d::plugin::ProtocolAds::dismissScreen(); JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_TRUE; } @@ -1097,14 +1147,14 @@ JSBool js_pluginx_protocols_ProtocolIAPOnLine_payFailedLocally(JSContext *cx, ui extern JSObject *jsb_PluginProtocol_prototype; -void js_pluginx_protocols_ProtocolIAPOnLine_finalize(JSFreeOp *fop, JSObject *obj) { +void js_pluginx_protocols_ProtocolAds_finalize(JSFreeOp *fop, JSObject *obj) { js_proxy_t* nproxy; js_proxy_t* jsproxy; JS_GET_NATIVE_PROXY(jsproxy, obj); if (jsproxy) { JS_GET_PROXY(nproxy, jsproxy->ptr); -// cocos2d::plugin::ProtocolIAPOnLine *nobj = static_cast(nproxy->ptr); +// cocos2d::plugin::ProtocolAds *nobj = static_cast(nproxy->ptr); // if (nobj) // delete nobj; @@ -1112,41 +1162,45 @@ void js_pluginx_protocols_ProtocolIAPOnLine_finalize(JSFreeOp *fop, JSObject *ob } } -void js_register_pluginx_protocols_ProtocolIAPOnLine(JSContext *cx, JSObject *global) { - jsb_ProtocolIAPOnLine_class = (JSClass *)calloc(1, sizeof(JSClass)); - jsb_ProtocolIAPOnLine_class->name = "ProtocolIAPOnLine"; - jsb_ProtocolIAPOnLine_class->addProperty = JS_PropertyStub; - jsb_ProtocolIAPOnLine_class->delProperty = JS_PropertyStub; - jsb_ProtocolIAPOnLine_class->getProperty = JS_PropertyStub; - jsb_ProtocolIAPOnLine_class->setProperty = JS_StrictPropertyStub; - jsb_ProtocolIAPOnLine_class->enumerate = JS_EnumerateStub; - jsb_ProtocolIAPOnLine_class->resolve = JS_ResolveStub; - jsb_ProtocolIAPOnLine_class->convert = JS_ConvertStub; - jsb_ProtocolIAPOnLine_class->finalize = js_pluginx_protocols_ProtocolIAPOnLine_finalize; - jsb_ProtocolIAPOnLine_class->flags = JSCLASS_HAS_RESERVED_SLOTS(2); +void js_register_pluginx_protocols_ProtocolAds(JSContext *cx, JSObject *global) { + jsb_ProtocolAds_class = (JSClass *)calloc(1, sizeof(JSClass)); + jsb_ProtocolAds_class->name = "ProtocolAds"; + jsb_ProtocolAds_class->addProperty = JS_PropertyStub; + jsb_ProtocolAds_class->delProperty = JS_PropertyStub; + jsb_ProtocolAds_class->getProperty = JS_PropertyStub; + jsb_ProtocolAds_class->setProperty = JS_StrictPropertyStub; + jsb_ProtocolAds_class->enumerate = JS_EnumerateStub; + jsb_ProtocolAds_class->resolve = JS_ResolveStub; + jsb_ProtocolAds_class->convert = JS_ConvertStub; + jsb_ProtocolAds_class->finalize = js_pluginx_protocols_ProtocolAds_finalize; + jsb_ProtocolAds_class->flags = JSCLASS_HAS_RESERVED_SLOTS(2); JSPropertySpec *properties = NULL; static JSFunctionSpec funcs[] = { - JS_FN("initDeveloperInfo", js_pluginx_protocols_ProtocolIAPOnLine_initDeveloperInfo, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), - JS_FN("getPluginVersion", js_pluginx_protocols_ProtocolIAPOnLine_getPluginVersion, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), - JS_FN("init", js_pluginx_protocols_ProtocolIAPOnLine_init, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), - JS_FN("payForProduct", js_pluginx_protocols_ProtocolIAPOnLine_payForProduct, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), - JS_FN("getSDKVersion", js_pluginx_protocols_ProtocolIAPOnLine_getSDKVersion, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), - JS_FN("setDebugMode", js_pluginx_protocols_ProtocolIAPOnLine_setDebugMode, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), - JS_FN("getPluginName", js_pluginx_protocols_ProtocolIAPOnLine_getPluginName, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), - JS_FS_END + JS_FN("hideBannerAd", js_pluginx_protocols_ProtocolAds_hideBannerAd, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("showBannerAd", js_pluginx_protocols_ProtocolAds_showBannerAd, 2, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("getPluginName", js_pluginx_protocols_ProtocolAds_getPluginName, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("getPluginVersion", js_pluginx_protocols_ProtocolAds_getPluginVersion, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("init", js_pluginx_protocols_ProtocolAds_init, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("initAppInfo", js_pluginx_protocols_ProtocolAds_initAppInfo, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("getSDKVersion", js_pluginx_protocols_ProtocolAds_getSDKVersion, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("setDebugMode", js_pluginx_protocols_ProtocolAds_setDebugMode, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FS_END }; static JSFunctionSpec st_funcs[] = { - JS_FN("payFailedLocally", js_pluginx_protocols_ProtocolIAPOnLine_payFailedLocally, 2, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("presentScreen", js_pluginx_protocols_ProtocolAds_presentScreen, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("receiveAd", js_pluginx_protocols_ProtocolAds_receiveAd, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("failedToReceiveAd", js_pluginx_protocols_ProtocolAds_failedToReceiveAd, 2, JSPROP_PERMANENT | JSPROP_ENUMERATE), + JS_FN("dismissScreen", js_pluginx_protocols_ProtocolAds_dismissScreen, 0, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FS_END }; - jsb_ProtocolIAPOnLine_prototype = JS_InitClass( + jsb_ProtocolAds_prototype = JS_InitClass( cx, global, jsb_PluginProtocol_prototype, - jsb_ProtocolIAPOnLine_class, + jsb_ProtocolAds_class, empty_constructor, 0, properties, funcs, @@ -1154,18 +1208,18 @@ void js_register_pluginx_protocols_ProtocolIAPOnLine(JSContext *cx, JSObject *gl st_funcs); // make the class enumerable in the registered namespace JSBool found; - JS_SetPropertyAttributes(cx, global, "ProtocolIAPOnLine", JSPROP_ENUMERATE | JSPROP_READONLY, &found); + JS_SetPropertyAttributes(cx, global, "ProtocolAds", JSPROP_ENUMERATE | JSPROP_READONLY, &found); // add the proto and JSClass to the type->js info hash table - TypeTest t; + TypeTest t; js_type_class_t *p; uint32_t typeId = t.s_id(); HASH_FIND_INT(_js_global_type_ht, &typeId, p); if (!p) { p = (js_type_class_t *)malloc(sizeof(js_type_class_t)); p->type = typeId; - p->jsclass = jsb_ProtocolIAPOnLine_class; - p->proto = jsb_ProtocolIAPOnLine_prototype; + p->jsclass = jsb_ProtocolAds_class; + p->proto = jsb_ProtocolAds_prototype; p->parentProto = jsb_PluginProtocol_prototype; HASH_ADD_INT(_js_global_type_ht, type, p); } @@ -1186,9 +1240,9 @@ void register_all_pluginx_protocols(JSContext* cx, JSObject* obj) { obj = ns; js_register_pluginx_protocols_PluginProtocol(cx, obj); + js_register_pluginx_protocols_ProtocolAds(cx, obj); js_register_pluginx_protocols_ProtocolIAP(cx, obj); js_register_pluginx_protocols_PluginManager(cx, obj); - js_register_pluginx_protocols_ProtocolIAPOnLine(cx, obj); js_register_pluginx_protocols_ProtocolAnalytics(cx, obj); } diff --git a/plugin/jsbindings/auto/jsb_pluginx_protocols_auto.hpp b/plugin/jsbindings/auto/jsb_pluginx_protocols_auto.hpp index bed1cddc4f..bb19f692fd 100644 --- a/plugin/jsbindings/auto/jsb_pluginx_protocols_auto.hpp +++ b/plugin/jsbindings/auto/jsb_pluginx_protocols_auto.hpp @@ -68,20 +68,24 @@ JSBool js_pluginx_protocols_ProtocolIAP_setDebugMode(JSContext *cx, uint32_t arg JSBool js_pluginx_protocols_ProtocolIAP_getPluginName(JSContext *cx, uint32_t argc, jsval *vp); JSBool js_pluginx_protocols_ProtocolIAP_payResult(JSContext *cx, uint32_t argc, jsval *vp); -extern JSClass *jsb_ProtocolIAPOnLine_class; -extern JSObject *jsb_ProtocolIAPOnLine_prototype; +extern JSClass *jsb_ProtocolAds_class; +extern JSObject *jsb_ProtocolAds_prototype; -JSBool js_pluginx_protocols_ProtocolIAPOnLine_constructor(JSContext *cx, uint32_t argc, jsval *vp); -void js_pluginx_protocols_ProtocolIAPOnLine_finalize(JSContext *cx, JSObject *obj); -void js_register_pluginx_protocols_ProtocolIAPOnLine(JSContext *cx, JSObject *global); +JSBool js_pluginx_protocols_ProtocolAds_constructor(JSContext *cx, uint32_t argc, jsval *vp); +void js_pluginx_protocols_ProtocolAds_finalize(JSContext *cx, JSObject *obj); +void js_register_pluginx_protocols_ProtocolAds(JSContext *cx, JSObject *global); void register_all_pluginx_protocols(JSContext* cx, JSObject* obj); -JSBool js_pluginx_protocols_ProtocolIAPOnLine_initDeveloperInfo(JSContext *cx, uint32_t argc, jsval *vp); -JSBool js_pluginx_protocols_ProtocolIAPOnLine_getPluginVersion(JSContext *cx, uint32_t argc, jsval *vp); -JSBool js_pluginx_protocols_ProtocolIAPOnLine_init(JSContext *cx, uint32_t argc, jsval *vp); -JSBool js_pluginx_protocols_ProtocolIAPOnLine_payForProduct(JSContext *cx, uint32_t argc, jsval *vp); -JSBool js_pluginx_protocols_ProtocolIAPOnLine_getSDKVersion(JSContext *cx, uint32_t argc, jsval *vp); -JSBool js_pluginx_protocols_ProtocolIAPOnLine_setDebugMode(JSContext *cx, uint32_t argc, jsval *vp); -JSBool js_pluginx_protocols_ProtocolIAPOnLine_getPluginName(JSContext *cx, uint32_t argc, jsval *vp); -JSBool js_pluginx_protocols_ProtocolIAPOnLine_payFailedLocally(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_protocols_ProtocolAds_hideBannerAd(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_protocols_ProtocolAds_showBannerAd(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_protocols_ProtocolAds_getPluginName(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_protocols_ProtocolAds_getPluginVersion(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_protocols_ProtocolAds_init(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_protocols_ProtocolAds_initAppInfo(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_protocols_ProtocolAds_getSDKVersion(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_protocols_ProtocolAds_setDebugMode(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_protocols_ProtocolAds_presentScreen(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_protocols_ProtocolAds_receiveAd(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_protocols_ProtocolAds_failedToReceiveAd(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_protocols_ProtocolAds_dismissScreen(JSContext *cx, uint32_t argc, jsval *vp); #endif diff --git a/plugin/jsbindings/auto/jsb_pluginx_protocols_auto_api.js b/plugin/jsbindings/auto/jsb_pluginx_protocols_auto_api.js index 8c78501777..806d347b87 100644 --- a/plugin/jsbindings/auto/jsb_pluginx_protocols_auto_api.js +++ b/plugin/jsbindings/auto/jsb_pluginx_protocols_auto_api.js @@ -220,15 +220,27 @@ payResult : function () {}, }; /** - * @class ProtocolIAPOnLine + * @class ProtocolAds */ -plugin.ProtocolIAPOnLine = { +plugin.ProtocolAds = { /** - * @method initDeveloperInfo - * @param {TDeveloperInfo} + * @method hideBannerAd */ -initDeveloperInfo : function () {}, +hideBannerAd : function () {}, + +/** + * @method showBannerAd + * @param {cocos2d::plugin::ProtocolAds::EBannerPos} + * @param {int} + */ +showBannerAd : function () {}, + +/** + * @method getPluginName + * @return A value converted from C/C++ "const char*" + */ +getPluginName : function () {}, /** * @method getPluginVersion @@ -243,10 +255,10 @@ getPluginVersion : function () {}, init : function () {}, /** - * @method payForProduct - * @param {TProductInfo} + * @method initAppInfo + * @param {TAppInfo} */ -payForProduct : function () {}, +initAppInfo : function () {}, /** * @method getSDKVersion @@ -261,16 +273,25 @@ getSDKVersion : function () {}, setDebugMode : function () {}, /** - * @method getPluginName - * @return A value converted from C/C++ "const char*" + * @method presentScreen */ -getPluginName : function () {}, +presentScreen : function () {}, /** - * @method payFailedLocally - * @param {cocos2d::plugin::EPayResult} + * @method receiveAd + */ +receiveAd : function () {}, + +/** + * @method failedToReceiveAd + * @param {cocos2d::plugin::AdListener::EAdErrorCode} * @param {const char*} */ -payFailedLocally : function () {}, +failedToReceiveAd : function () {}, + +/** + * @method dismissScreen + */ +dismissScreen : function () {}, }; diff --git a/plugin/jsbindings/auto/jsb_pluginx_umeng_auto.cpp b/plugin/jsbindings/auto/jsb_pluginx_umeng_auto.cpp index e7e2780fd9..57356f1c47 100644 --- a/plugin/jsbindings/auto/jsb_pluginx_umeng_auto.cpp +++ b/plugin/jsbindings/auto/jsb_pluginx_umeng_auto.cpp @@ -621,7 +621,7 @@ void js_register_pluginx_umeng_AnalyticsUmeng(JSContext *cx, JSObject *global) { JS_FN("logTimedEventEnd", js_pluginx_umeng_AnalyticsUmeng_logTimedEventEnd, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("logEventWithLabel", js_pluginx_umeng_AnalyticsUmeng_logEventWithLabel, 2, JSPROP_PERMANENT | JSPROP_ENUMERATE), JS_FN("setDebugMode", js_pluginx_umeng_AnalyticsUmeng_setDebugMode, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE), - JS_FS_END + JS_FS_END }; JSFunctionSpec *st_funcs = NULL; diff --git a/plugin/jsbindings/manual/jsb_pluginx_extension_registration.cpp b/plugin/jsbindings/manual/jsb_pluginx_extension_registration.cpp index f461f8919c..ce13a11f3d 100644 --- a/plugin/jsbindings/manual/jsb_pluginx_extension_registration.cpp +++ b/plugin/jsbindings/manual/jsb_pluginx_extension_registration.cpp @@ -28,7 +28,7 @@ void register_pluginx_js_extensions(JSContext* cx, JSObject* global) tmpObj = JSVAL_TO_OBJECT(anonEvaluate(cx, global, "(function () { return plugin.ProtocolIAP; })()")); JS_DefineFunction(cx, tmpObj, "setResultListener", js_pluginx_ProtocolIAP_setResultListener, 1, JSPROP_READONLY | JSPROP_PERMANENT); - tmpObj = JSVAL_TO_OBJECT(anonEvaluate(cx, global, "(function () { return plugin.ProtocolIAPOnLine; })()")); - JS_DefineFunction(cx, tmpObj, "setLocalResultListener", js_pluginx_ProtocolIAPOnLine_setLocalResultListener, 1, JSPROP_READONLY | JSPROP_PERMANENT); + tmpObj = JSVAL_TO_OBJECT(anonEvaluate(cx, global, "(function () { return plugin.ProtocolAds; })()")); + JS_DefineFunction(cx, tmpObj, "setLocalResultListener", js_pluginx_ProtocolAds_setAdListener, 1, JSPROP_READONLY | JSPROP_PERMANENT); } \ No newline at end of file diff --git a/plugin/jsbindings/manual/jsb_pluginx_manual_iap.cpp b/plugin/jsbindings/manual/jsb_pluginx_manual_iap.cpp index 7ff6306b3e..a5cd5b0e3f 100644 --- a/plugin/jsbindings/manual/jsb_pluginx_manual_iap.cpp +++ b/plugin/jsbindings/manual/jsb_pluginx_manual_iap.cpp @@ -1,7 +1,7 @@ #include "jsb_pluginx_manual_iap.h" #include "jsb_pluginx_basic_conversions.h" #include "jsb_pluginx_spidermonkey_specifics.h" -#include "ProtocolIAPOnLine.h" +#include "ProtocolAds.h" using namespace pluginx; @@ -75,10 +75,56 @@ JSBool js_pluginx_ProtocolIAP_setResultListener(JSContext *cx, uint32_t argc, js return JS_FALSE; } -class Pluginx_PurchaseLocalResult : public cocos2d::plugin::LocalResultListener +class Pluginx_AdListener : public cocos2d::plugin::AdListener { public: - virtual void payFailedLocally(cocos2d::plugin::EPayResult ret, const char* msg) + virtual void onReceiveAd() + { + JSContext* cx = s_cx; + + JSBool hasAction; + jsval retval; + jsval temp_retval; + + JSObject* obj = m_pJSDelegate; + JSBool bRet = JS_HasProperty(cx, obj, "onReceiveAd", &hasAction); + if (bRet && hasAction) { + if(!JS_GetProperty(cx, obj, "onReceiveAd", &temp_retval)) { + return; + } + if(temp_retval == JSVAL_VOID) { + return; + } + JSAutoCompartment ac(cx, obj); + JS_CallFunctionName(cx, obj, "onReceiveAd", + 0, NULL, &retval); + } + } + + virtual void onPresentScreen() + { + JSContext* cx = s_cx; + + JSBool hasAction; + jsval retval; + jsval temp_retval; + + JSObject* obj = m_pJSDelegate; + JSBool bRet = JS_HasProperty(cx, obj, "onPresentScreen", &hasAction); + if (bRet && hasAction) { + if(!JS_GetProperty(cx, obj, "onPresentScreen", &temp_retval)) { + return; + } + if(temp_retval == JSVAL_VOID) { + return; + } + JSAutoCompartment ac(cx, obj); + JS_CallFunctionName(cx, obj, "onPresentScreen", + 0, NULL, &retval); + } + } + + virtual void onFailedToReceiveAd(EAdErrorCode code, const char* msg) { JSContext* cx = s_cx; @@ -86,25 +132,48 @@ public: jsval retval; jsval temp_retval; jsval dataVal[2]; - dataVal[0] = INT_TO_JSVAL(ret); + dataVal[0] = INT_TO_JSVAL(code); std::string strMsgInfo = msg; dataVal[1] = std_string_to_jsval(cx, strMsgInfo); JSObject* obj = m_pJSDelegate; - JSBool bRet = JS_HasProperty(cx, obj, "payFailedLocally", &hasAction); + JSBool bRet = JS_HasProperty(cx, obj, "onFailedToReceiveAd", &hasAction); if (bRet && hasAction) { - if(!JS_GetProperty(cx, obj, "payFailedLocally", &temp_retval)) { + if(!JS_GetProperty(cx, obj, "onFailedToReceiveAd", &temp_retval)) { return; } if(temp_retval == JSVAL_VOID) { return; } JSAutoCompartment ac(cx, obj); - JS_CallFunctionName(cx, obj, "payFailedLocally", + JS_CallFunctionName(cx, obj, "onFailedToReceiveAd", 2, dataVal, &retval); } } + virtual void onDismissScreen() + { + JSContext* cx = s_cx; + + JSBool hasAction; + jsval retval; + jsval temp_retval; + + JSObject* obj = m_pJSDelegate; + JSBool bRet = JS_HasProperty(cx, obj, "onDismissScreen", &hasAction); + if (bRet && hasAction) { + if(!JS_GetProperty(cx, obj, "onDismissScreen", &temp_retval)) { + return; + } + if(temp_retval == JSVAL_VOID) { + return; + } + JSAutoCompartment ac(cx, obj); + JS_CallFunctionName(cx, obj, "onDismissScreen", + 0, NULL, &retval); + } + } + void setJSDelegate(JSObject* pJSDelegate) { m_pJSDelegate = pJSDelegate; @@ -114,7 +183,7 @@ private: JSObject* m_pJSDelegate; }; -JSBool js_pluginx_ProtocolIAPOnLine_setLocalResultListener(JSContext *cx, uint32_t argc, jsval *vp) +JSBool js_pluginx_ProtocolAds_setAdListener(JSContext *cx, uint32_t argc, jsval *vp) { s_cx = cx; jsval *argv = JS_ARGV(cx, vp); @@ -122,9 +191,9 @@ JSBool js_pluginx_ProtocolIAPOnLine_setLocalResultListener(JSContext *cx, uint32 if (argc == 1) { // save the delegate JSObject *jsDelegate = JSVAL_TO_OBJECT(argv[0]); - Pluginx_PurchaseLocalResult* nativeDelegate = new Pluginx_PurchaseLocalResult(); + Pluginx_AdListener* nativeDelegate = new Pluginx_AdListener(); nativeDelegate->setJSDelegate(jsDelegate); - cocos2d::plugin::ProtocolIAPOnLine::setLocalResultListener(nativeDelegate); + cocos2d::plugin::ProtocolAds::setAdListener(nativeDelegate); JS_SET_RVAL(cx, vp, JSVAL_VOID); return JS_TRUE; diff --git a/plugin/jsbindings/manual/jsb_pluginx_manual_iap.h b/plugin/jsbindings/manual/jsb_pluginx_manual_iap.h index b9bbe8105e..cb93009c82 100644 --- a/plugin/jsbindings/manual/jsb_pluginx_manual_iap.h +++ b/plugin/jsbindings/manual/jsb_pluginx_manual_iap.h @@ -5,6 +5,6 @@ #include "jsfriendapi.h" JSBool js_pluginx_ProtocolIAP_setResultListener(JSContext *cx, uint32_t argc, jsval *vp); -JSBool js_pluginx_ProtocolIAPOnLine_setLocalResultListener(JSContext *cx, uint32_t argc, jsval *vp); +JSBool js_pluginx_ProtocolAds_setAdListener(JSContext *cx, uint32_t argc, jsval *vp); #endif /* __JS_MANUAL_IAP_H__ */ diff --git a/plugin/plugins/admob/jsb_admob.ini b/plugin/plugins/admob/jsb_admob.ini index b956fa5da4..ab93d3da10 100644 --- a/plugin/plugins/admob/jsb_admob.ini +++ b/plugin/plugins/admob/jsb_admob.ini @@ -23,11 +23,11 @@ cxxgenerator_headers = -I%(cxxgeneratordir)s/targets/spidermonkey/common extra_arguments = %(android_headers)s %(clang_headers)s %(cxxgenerator_headers)s %(cocos_headers)s %(android_flags)s %(clang_flags)s %(cocos_flags)s # what headers to parse -headers = %(pluginxdir)s/plugins/admob/include/IAPAlipay.h +headers = %(pluginxdir)s/plugins/admob/include/AdsAdmob.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^CCMenu*$". -classes = IAPAlipay +classes = AdsAdmob # what should we skip? in the format ClassName::[function function] # ClassName is a regular expression, but will be used like this: "^ClassName$" functions are also @@ -53,7 +53,7 @@ base_classes_to_skip = # classes that create no constructor # CCSet is special and we will use a hand-written constructor -abstract_classes = IAPAlipay +abstract_classes = AdsAdmob # Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are 'yes' or 'no'. script_control_cpp = yes diff --git a/plugin/protocols/jsb_protocols.ini b/plugin/protocols/jsb_protocols.ini index f65109a346..baf7dac773 100644 --- a/plugin/protocols/jsb_protocols.ini +++ b/plugin/protocols/jsb_protocols.ini @@ -23,11 +23,11 @@ cxxgenerator_headers = -I%(cxxgeneratordir)s/targets/spidermonkey/common extra_arguments = %(android_headers)s %(clang_headers)s %(cxxgenerator_headers)s %(cocos_headers)s %(android_flags)s %(clang_flags)s %(cocos_flags)s # what headers to parse -headers = %(pluginxdir)s/protocols/include/PluginManager.h %(pluginxdir)s/protocols/include/ProtocolAnalytics.h %(pluginxdir)s/protocols/include/ProtocolIAP.h %(pluginxdir)s/protocols/include/ProtocolIAPOnLine.h +headers = %(pluginxdir)s/protocols/include/PluginManager.h %(pluginxdir)s/protocols/include/ProtocolAnalytics.h %(pluginxdir)s/protocols/include/ProtocolIAP.h %(pluginxdir)s/protocols/include/ProtocolAds.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^CCMenu*$". -classes = PluginProtocol PluginManager ProtocolIAP ProtocolAnalytics ProtocolIAPOnLine +classes = PluginProtocol PluginManager ProtocolIAP ProtocolAnalytics ProtocolAds # what should we skip? in the format ClassName::[function function] # ClassName is a regular expression, but will be used like this: "^ClassName$" functions are also @@ -37,7 +37,7 @@ classes = PluginProtocol PluginManager ProtocolIAP ProtocolAnalytics ProtocolIAP # functions from all classes. skip = ProtocolIAP::[setResultListener], - ProtocolIAPOnLine::[setLocalResultListener] + ProtocolAds::[setAdListener] rename_functions = @@ -54,7 +54,7 @@ base_classes_to_skip = # classes that create no constructor # CCSet is special and we will use a hand-written constructor -abstract_classes = PluginProtocol ProtocolIAP ProtocolAnalytics PluginManager ProtocolIAPOnLine +abstract_classes = PluginProtocol ProtocolIAP ProtocolAnalytics PluginManager ProtocolAds # Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are 'yes' or 'no'. script_control_cpp = yes diff --git a/plugin/tools/tojs/genbindings-all.sh b/plugin/tools/tojs/genbindings-all.sh index 15aff34a92..9a332771f3 100755 --- a/plugin/tools/tojs/genbindings-all.sh +++ b/plugin/tools/tojs/genbindings-all.sh @@ -1,6 +1,6 @@ #!/bin/bash -PLUGIN_NAME=("alipay" "flurry" "nd91" "umeng") +PLUGIN_NAME=("alipay" "flurry" "nd91" "umeng" "admob") DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" # ... use paths relative to current directory From 4e24ce40eaf676ef9f42ed87ab6072cedb538914 Mon Sep 17 00:00:00 2001 From: lihex Date: Wed, 24 Apr 2013 15:58:57 +0800 Subject: [PATCH 02/85] Submit protocol of social share plugin --- plugin/protocols/include/ProtocolSocial.h | 89 +++++++++++ .../platform/android/ProtocolSocial.cpp | 151 ++++++++++++++++++ plugin/protocols/proj.android/jni/Android.mk | 1 + .../org/cocos2dx/plugin/InterfaceSocial.java | 29 ++++ 4 files changed, 270 insertions(+) create mode 100755 plugin/protocols/include/ProtocolSocial.h create mode 100755 plugin/protocols/platform/android/ProtocolSocial.cpp mode change 100644 => 100755 plugin/protocols/proj.android/jni/Android.mk create mode 100755 plugin/protocols/proj.android/src/org/cocos2dx/plugin/InterfaceSocial.java diff --git a/plugin/protocols/include/ProtocolSocial.h b/plugin/protocols/include/ProtocolSocial.h new file mode 100755 index 0000000000..865c9a95c0 --- /dev/null +++ b/plugin/protocols/include/ProtocolSocial.h @@ -0,0 +1,89 @@ +#ifndef __CXX_PROTOCOL_SOCIAL_H__ +#define __CXX_PROTOCOL_SOCIAL_H__ + +#include "PluginProtocol.h" +#include +#include + +namespace cocos2d { namespace plugin { + +typedef std::map TDeveloperInfo; +typedef std::map TShareInfo; + +typedef enum +{ + eShareSuccess = 0, + eShareFail, + eShareCancel, + eShareTimeOut, +} EShareResult; + +class ShareResultListener +{ +public: + virtual void shareResult(EShareResult ret, const char* msg, TShareInfo info) = 0; +}; + +class ProtocolSocial : public PluginProtocol +{ +public: + + /** + @brief plugin initialization + */ + virtual bool init(); + + /** + @brief initialize the developer info + @param devInfo This parameter is the info of developer, + different plugin have different format + @warning Must invoke this interface before other interfaces. + And invoked only once. + */ + virtual void initDeveloperInfo(TDeveloperInfo devInfo); + + /** + @brief share information + @param info The info of share, must contains key: + text The text of share + @warning For different plugin, the parameter should have other keys to share. + Look at the manual of plugins. + */ + virtual void share(TShareInfo info); + + /** + @brief Set whether needs to output logs to console. + @param debug if true debug mode enabled, or debug mode disabled. + */ + virtual void setDebugMode(bool debug); + + /** + @breif set the result listener + @param pListener The callback object for share result + @wraning Must invoke this interface before share + */ + static void setResultListener(ShareResultListener* pListener); + + /** + @brief share result callback + */ + static void shareResult(EShareResult ret, const char* msg); + + virtual const char* getPluginVersion() { return "ProtocolSocial, v0.1.00 , subclass should override this interface!"; }; + virtual const char* getSDKVersion(); + virtual const char* getPluginName() = 0; + +protected: + ProtocolSocial(); +public: + virtual ~ProtocolSocial(); + +protected: + static bool m_bSharing; + static ShareResultListener* m_pListener; + static TShareInfo m_curInfo; +}; + +}} // namespace cocos2d { namespace plugin { + +#endif /* ----- #ifndef __CXX_PROTOCOL_SOCIAL_H__ ----- */ diff --git a/plugin/protocols/platform/android/ProtocolSocial.cpp b/plugin/protocols/platform/android/ProtocolSocial.cpp new file mode 100755 index 0000000000..9825bdd722 --- /dev/null +++ b/plugin/protocols/platform/android/ProtocolSocial.cpp @@ -0,0 +1,151 @@ +#include "ProtocolSocial.h" +#include "PluginJniHelper.h" +#include +#include "PluginUtils.h" +#include "PluginJavaData.h" + +#if 1 +#define LOG_TAG "ProtocolSocial" +#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) +#else +#define LOGD(...) +#endif + +namespace cocos2d { namespace plugin { + +extern "C" { + JNIEXPORT void JNICALL Java_org_cocos2dx_plugin_InterfaceSocial_nativeShareResult(JNIEnv* env, jobject thiz, jint ret, jstring msg) + { + std::string strMsg = PluginJniHelper::jstring2string(msg); + ProtocolSocial::shareResult((EShareResult) ret, strMsg.c_str()); + } +} + +bool ProtocolSocial::m_bSharing = false; +ShareResultListener* ProtocolSocial::m_pListener = NULL; +TShareInfo ProtocolSocial::m_curInfo; + +ProtocolSocial::ProtocolSocial() +{ +} + +ProtocolSocial::~ProtocolSocial() +{ + PluginUtils::erasePluginJavaData(this); +} + +bool ProtocolSocial::init() +{ + return true; +} + +void ProtocolSocial::initDeveloperInfo(TDeveloperInfo devInfo) +{ + if (devInfo.empty()) + { + LOGD("The developer info is empty!"); + return; + } + else + { + PluginJavaData* pData = PluginUtils::getPluginJavaData(this); + PluginJniMethodInfo t; + if (PluginJniHelper::getMethodInfo(t + , pData->jclassName.c_str() + , "initDeveloperInfo" + , "(Ljava/util/Hashtable;)V")) + { + // generate the hashtable from map + jobject obj_Map = PluginUtils::createJavaMapObject(t, &devInfo); + + // invoke java method + t.env->CallVoidMethod(pData->jobj, t.methodID, obj_Map); + t.env->DeleteLocalRef(obj_Map); + t.env->DeleteLocalRef(t.classID); + } + } +} + +void ProtocolSocial::share(TShareInfo info) +{ + if (m_bSharing) + { + LOGD("Now is sharing"); + return; + } + + if (info.empty()) + { + if (NULL != m_pListener) + { + shareResult(eShareFail, "Share info error"); + } + LOGD("The Share info is empty!"); + return; + } + else + { + m_bSharing = true; + m_curInfo = info; + + PluginJavaData* pData = PluginUtils::getPluginJavaData(this); + PluginJniMethodInfo t; + if (PluginJniHelper::getMethodInfo(t + , pData->jclassName.c_str() + , "share" + , "(Ljava/util/Hashtable;)V")) + { + // generate the hashtable from map + jobject obj_Map = PluginUtils::createJavaMapObject(t, &info); + + // invoke java method + t.env->CallVoidMethod(pData->jobj, t.methodID, obj_Map); + t.env->DeleteLocalRef(obj_Map); + t.env->DeleteLocalRef(t.classID); + } + } +} + +void ProtocolSocial::setResultListener(ShareResultListener* pListener) +{ + m_pListener = pListener; +} + +void ProtocolSocial::shareResult(EShareResult ret, const char* msg) +{ + m_bSharing = false; + if (m_pListener) + { + m_pListener->shareResult(ret, msg, m_curInfo); + } + else + { + LOGD("Result listener is null!"); + } + m_curInfo.clear(); + LOGD("Share result is : %d(%s)", (int) ret, msg); +} + +const char* ProtocolSocial::getSDKVersion() +{ + std::string verName; + + PluginJavaData* pData = PluginUtils::getPluginJavaData(this); + PluginJniMethodInfo t; + if (PluginJniHelper::getMethodInfo(t + , pData->jclassName.c_str() + , "getSDKVersion" + , "()Ljava/lang/String;")) + { + jstring ret = (jstring)(t.env->CallObjectMethod(pData->jobj, t.methodID)); + verName = PluginJniHelper::jstring2string(ret); + } + return verName.c_str(); +} + +void ProtocolSocial::setDebugMode(bool debug) +{ + PluginUtils::callJavaFunctionWithName_oneBaseType(this, "setDebugMode", "(Z)V", debug); +} + +}} // namespace cocos2d { namespace plugin { diff --git a/plugin/protocols/proj.android/jni/Android.mk b/plugin/protocols/proj.android/jni/Android.mk old mode 100644 new mode 100755 index 9e0ad021e8..5e82597a05 --- a/plugin/protocols/proj.android/jni/Android.mk +++ b/plugin/protocols/proj.android/jni/Android.mk @@ -13,6 +13,7 @@ $(addprefix ../../platform/android/, \ ProtocolAnalytics.cpp \ ProtocolIAP.cpp \ ProtocolAds.cpp \ + ProtocolSocial.cpp \ ) \ ../../PluginManager.cpp \ ../../RegisterPlugin.cpp \ diff --git a/plugin/protocols/proj.android/src/org/cocos2dx/plugin/InterfaceSocial.java b/plugin/protocols/proj.android/src/org/cocos2dx/plugin/InterfaceSocial.java new file mode 100755 index 0000000000..a4b3cb08f6 --- /dev/null +++ b/plugin/protocols/proj.android/src/org/cocos2dx/plugin/InterfaceSocial.java @@ -0,0 +1,29 @@ +package org.cocos2dx.plugin; + +import java.util.Hashtable; + +public class InterfaceSocial { + public static final int SHARERESULT_SUCCESS = 0; + public static final int SHARERESULT_FAIL = 1; + public static final int SHARERESULT_CANCEL = 2; + public static final int SHARERESULT_TIMEOUT = 3; + + public interface ShareAdapter { + public void initDeveloperInfo(Hashtable cpInfo); + public void share(Hashtable cpInfo); + public void setDebugMode(boolean debug); + public String getSDKVersion(); + } + + public static void shareResult(int ret, String msg) { + final int curRet = ret; + final String curMsg = msg; + PluginWrapper.runOnGLThread(new Runnable() { + @Override + public void run() { + nativeShareResult(curRet, curMsg); + } + }); + } + private static native void nativeShareResult(int ret, String msg); +} From ae7dab15b6b8c6e83048ad3df616a089c26341c0 Mon Sep 17 00:00:00 2001 From: lihex Date: Wed, 24 Apr 2013 15:59:54 +0800 Subject: [PATCH 03/85] Submit twitter share plugin implement --- .../plugins/twitter/include/SocialTwitter.h | 58 +++++ .../platform/android/SocialTwitter.cpp | 55 ++++ .../plugins/twitter/proj.android/.classpath | 12 + plugin/plugins/twitter/proj.android/.project | 45 ++++ .../twitter/proj.android/AndroidManifest.xml | 9 + .../alipay_plugin.apk.REMOVED.git-id | 1 + .../twitter/proj.android/ForManifest.xml | 7 + plugin/plugins/twitter/proj.android/build.xml | 91 +++++++ .../twitter/proj.android/build_native.sh | 20 ++ .../twitter/proj.android/jni/Android.mk | 29 +++ .../twitter/proj.android/jni/Application.mk | 7 + .../twitter/proj.android/project.properties | 16 ++ .../twitter/proj.android/res/.gitignore | 0 .../sdk/signpost-commonshttp4-1.2.1.1.jar | Bin 0 -> 6455 bytes .../sdk/signpost-core-1.2.1.1.jar | Bin 0 -> 44558 bytes .../sdk/signpost-jetty6-1.2.1.1.jar | Bin 0 -> 4310 bytes ...er4j-core-android-3.0.1.jar.REMOVED.git-id | 1 + .../src/org/cocos2dx/plugin/Consts.java | 9 + .../org/cocos2dx/plugin/SocialTwitter.java | 172 +++++++++++++ .../src/org/cocos2dx/plugin/TwitterApp.java | 237 ++++++++++++++++++ .../org/cocos2dx/plugin/TwitterDialog.java | 182 ++++++++++++++ .../org/cocos2dx/plugin/TwitterSession.java | 56 +++++ plugin/tools/config.sh | 3 +- 23 files changed, 1009 insertions(+), 1 deletion(-) create mode 100755 plugin/plugins/twitter/include/SocialTwitter.h create mode 100755 plugin/plugins/twitter/platform/android/SocialTwitter.cpp create mode 100755 plugin/plugins/twitter/proj.android/.classpath create mode 100755 plugin/plugins/twitter/proj.android/.project create mode 100755 plugin/plugins/twitter/proj.android/AndroidManifest.xml create mode 100644 plugin/plugins/twitter/proj.android/ForAssets/alipay_plugin.apk.REMOVED.git-id create mode 100755 plugin/plugins/twitter/proj.android/ForManifest.xml create mode 100755 plugin/plugins/twitter/proj.android/build.xml create mode 100755 plugin/plugins/twitter/proj.android/build_native.sh create mode 100755 plugin/plugins/twitter/proj.android/jni/Android.mk create mode 100755 plugin/plugins/twitter/proj.android/jni/Application.mk create mode 100755 plugin/plugins/twitter/proj.android/project.properties create mode 100755 plugin/plugins/twitter/proj.android/res/.gitignore create mode 100755 plugin/plugins/twitter/proj.android/sdk/signpost-commonshttp4-1.2.1.1.jar create mode 100755 plugin/plugins/twitter/proj.android/sdk/signpost-core-1.2.1.1.jar create mode 100755 plugin/plugins/twitter/proj.android/sdk/signpost-jetty6-1.2.1.1.jar create mode 100644 plugin/plugins/twitter/proj.android/sdk/twitter4j-core-android-3.0.1.jar.REMOVED.git-id create mode 100644 plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/Consts.java create mode 100755 plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/SocialTwitter.java create mode 100755 plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterApp.java create mode 100755 plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterDialog.java create mode 100755 plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterSession.java diff --git a/plugin/plugins/twitter/include/SocialTwitter.h b/plugin/plugins/twitter/include/SocialTwitter.h new file mode 100755 index 0000000000..7b99bd54c0 --- /dev/null +++ b/plugin/plugins/twitter/include/SocialTwitter.h @@ -0,0 +1,58 @@ +#ifndef __CCX_SOCIAL_TWITTER_H__ +#define __CCX_SOCIAL_TWITTER_H__ + +#include "ProtocolSocial.h" +#include +#include + +namespace cocos2d { namespace plugin { + +class SocialTwitter : public ProtocolSocial +{ + PLUGIN_REGISTER_DECL(SocialTwitter) +public: + /** + @brief plugin initialization + */ + virtual bool init(); + + /** + @brief initialize the developer info + @param devInfo This parameter is the info of developer, must contains key: + AlipayPartner The partner id of alipay account + AlipaySeller The seller id of alipay account + AlipayRsaPrivate The RSA private key of alipay account + AlipayPublic The public key of alipay account + AlipayNotifyUrl The notify url of developer (must not be empty) + AlipayPluginName The apk file name of Alipay (must not be empty) + @warning Must invoke this interface before other interfaces. + And invoked only once. + */ + virtual void initDeveloperInfo(TDeveloperInfo devInfo); + + /** + @brief pay for product + @param info The info of product, must contains key: + productName The name of product + productPrice The price of product(must can be parse to float) + productDesc The description of product + @warning For different plugin, the parameter should have other keys to pay. + Look at the manual of plugins. + */ + virtual void share(TShareInfo info); + + /** + @brief Set whether needs to output logs to console. + @param debug if true debug mode enabled, or debug mode disabled. + */ + virtual void setDebugMode(bool debug); + + virtual const char* getPluginVersion() { return "v0.1.01"; }; + virtual const char* getSDKVersion(); + + virtual ~SocialTwitter(); +}; + +}} // namespace cocos2d { namespace plugin { + +#endif /* __CCX_SOCIAL_TWITTER_H__ */ diff --git a/plugin/plugins/twitter/platform/android/SocialTwitter.cpp b/plugin/plugins/twitter/platform/android/SocialTwitter.cpp new file mode 100755 index 0000000000..4b26c8f6d8 --- /dev/null +++ b/plugin/plugins/twitter/platform/android/SocialTwitter.cpp @@ -0,0 +1,55 @@ +#include "SocialTwitter.h" +#include "PluginUtils.h" + +namespace cocos2d { namespace plugin { + +PLUGIN_REGISTER_IMPL(SocialTwitter) + +SocialTwitter::~SocialTwitter() +{ +} + +/** +@brief plugin initialization +*/ +bool SocialTwitter::init() +{ + return PluginUtils::initJavaPlugin(this, "org.cocos2dx.plugin.SocialTwitter"); +} + +/** +@brief initialize the developer info +@param devInfo This parameter is the info of developer, must contains key: + consumerkey The consumerkey of twitter account + consumersecret The consumersecret of twitter account + More: https://dev.twitter.com +@warning Must invoke this interface before other interfaces. + And invoked only once. +*/ +void SocialTwitter::initDeveloperInfo(TDeveloperInfo devInfo) +{ + ProtocolSocial::initDeveloperInfo(devInfo); +} + +/** +@brief pay for product +@param info The info of product, must contains key: + text The text to share + imagePath The full path of image to share +*/ +void SocialTwitter::share(TShareInfo info) +{ + ProtocolSocial::share(info); +} + +const char* SocialTwitter::getSDKVersion() +{ + return ProtocolSocial::getSDKVersion(); +} + +void SocialTwitter::setDebugMode(bool debug) +{ + ProtocolSocial::setDebugMode(debug); +} + +}} // namespace cocos2d { namespace plugin { diff --git a/plugin/plugins/twitter/proj.android/.classpath b/plugin/plugins/twitter/proj.android/.classpath new file mode 100755 index 0000000000..4ba22f534d --- /dev/null +++ b/plugin/plugins/twitter/proj.android/.classpath @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/plugin/plugins/twitter/proj.android/.project b/plugin/plugins/twitter/proj.android/.project new file mode 100755 index 0000000000..9aade58531 --- /dev/null +++ b/plugin/plugins/twitter/proj.android/.project @@ -0,0 +1,45 @@ + + + libPluginTwitter + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + + + android + 2 + PARENT-1-PROJECT_LOC/platform/android + + + include + 2 + PARENT-1-PROJECT_LOC/include + + + diff --git a/plugin/plugins/twitter/proj.android/AndroidManifest.xml b/plugin/plugins/twitter/proj.android/AndroidManifest.xml new file mode 100755 index 0000000000..8582917b67 --- /dev/null +++ b/plugin/plugins/twitter/proj.android/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/plugin/plugins/twitter/proj.android/ForAssets/alipay_plugin.apk.REMOVED.git-id b/plugin/plugins/twitter/proj.android/ForAssets/alipay_plugin.apk.REMOVED.git-id new file mode 100644 index 0000000000..e7115f0d77 --- /dev/null +++ b/plugin/plugins/twitter/proj.android/ForAssets/alipay_plugin.apk.REMOVED.git-id @@ -0,0 +1 @@ +db46ceaf2554c8d9e48cdaec3a4cdf5519bb8896 \ No newline at end of file diff --git a/plugin/plugins/twitter/proj.android/ForManifest.xml b/plugin/plugins/twitter/proj.android/ForManifest.xml new file mode 100755 index 0000000000..00d34cd419 --- /dev/null +++ b/plugin/plugins/twitter/proj.android/ForManifest.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/plugin/plugins/twitter/proj.android/build.xml b/plugin/plugins/twitter/proj.android/build.xml new file mode 100755 index 0000000000..10e9663ff5 --- /dev/null +++ b/plugin/plugins/twitter/proj.android/build.xml @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugin/plugins/twitter/proj.android/build_native.sh b/plugin/plugins/twitter/proj.android/build_native.sh new file mode 100755 index 0000000000..0b272b9465 --- /dev/null +++ b/plugin/plugins/twitter/proj.android/build_native.sh @@ -0,0 +1,20 @@ +# set params +PLUGIN_ANDROID_ROOT=$(cd "$(dirname "$0")"; pwd) + +if [ ! "${PLUGIN_ROOT}" ]; then + PLUGIN_ROOT="$PLUGIN_ANDROID_ROOT"/../.. +fi + +# build +"$ANDROID_NDK_ROOT"/ndk-build -C "$PLUGIN_ANDROID_ROOT" \ +NDK_MODULE_PATH="$PLUGIN_ROOT" + +echo +if [ "0" != "$?" ]; then + echo "Build error occoured!!!" + exit 1 +fi + +echo +echo "Native build action success." +exit 0 \ No newline at end of file diff --git a/plugin/plugins/twitter/proj.android/jni/Android.mk b/plugin/plugins/twitter/proj.android/jni/Android.mk new file mode 100755 index 0000000000..e4c920eb4c --- /dev/null +++ b/plugin/plugins/twitter/proj.android/jni/Android.mk @@ -0,0 +1,29 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := PluginTwitterStatic + +LOCAL_MODULE_FILENAME := libPluginTwitterStatic + +LOCAL_SRC_FILES := \ +$(addprefix ../../platform/android/, \ + SocialTwitter.cpp \ +) \ + +LOCAL_CFLAGS := + +LOCAL_EXPORT_CFLAGS := + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../include + +LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../../include + +LOCAL_WHOLE_STATIC_LIBRARIES := PluginProtocolStatic + +LOCAL_LDLIBS := -landroid +LOCAL_LDLIBS += -llog + +include $(BUILD_STATIC_LIBRARY) + +$(call import-module, protocols/proj.android/jni) diff --git a/plugin/plugins/twitter/proj.android/jni/Application.mk b/plugin/plugins/twitter/proj.android/jni/Application.mk new file mode 100755 index 0000000000..e4935028c3 --- /dev/null +++ b/plugin/plugins/twitter/proj.android/jni/Application.mk @@ -0,0 +1,7 @@ +# it is needed for ndk-r5 +APP_STL := gnustl_static +APP_CPPFLAGS += -frtti +APP_MODULES := PluginTwitterStatic +APP_ABI :=armeabi +#APP_ABI :=x86 +#APP_ABI :=mips mips-r2 mips-r2-sf armeabi diff --git a/plugin/plugins/twitter/proj.android/project.properties b/plugin/plugins/twitter/proj.android/project.properties new file mode 100755 index 0000000000..9d741eed16 --- /dev/null +++ b/plugin/plugins/twitter/proj.android/project.properties @@ -0,0 +1,16 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-7 +android.library=true +android.library.reference.1=../../../protocols/proj.android diff --git a/plugin/plugins/twitter/proj.android/res/.gitignore b/plugin/plugins/twitter/proj.android/res/.gitignore new file mode 100755 index 0000000000..e69de29bb2 diff --git a/plugin/plugins/twitter/proj.android/sdk/signpost-commonshttp4-1.2.1.1.jar b/plugin/plugins/twitter/proj.android/sdk/signpost-commonshttp4-1.2.1.1.jar new file mode 100755 index 0000000000000000000000000000000000000000..50e9838e6fd89498ffc8bd54e7ab01cd55eabea5 GIT binary patch literal 6455 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
    e7lGjy}LU6zgrn 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 literal 0 HcmV?d00001 diff --git a/plugin/plugins/twitter/proj.android/sdk/signpost-jetty6-1.2.1.1.jar b/plugin/plugins/twitter/proj.android/sdk/signpost-jetty6-1.2.1.1.jar new file mode 100755 index 0000000000000000000000000000000000000000..b5d974c7ce1871bae52a24641232f26528b665b2 GIT binary patch literal 4310 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 literal 0 HcmV?d00001 diff --git a/plugin/plugins/twitter/proj.android/sdk/twitter4j-core-android-3.0.1.jar.REMOVED.git-id b/plugin/plugins/twitter/proj.android/sdk/twitter4j-core-android-3.0.1.jar.REMOVED.git-id new file mode 100644 index 0000000000..cd6a606604 --- /dev/null +++ b/plugin/plugins/twitter/proj.android/sdk/twitter4j-core-android-3.0.1.jar.REMOVED.git-id @@ -0,0 +1 @@ +62d02b6f0d450b3b64d061280594018742ddcd27 \ No newline at end of file diff --git a/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/Consts.java b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/Consts.java new file mode 100644 index 0000000000..74b4ea8da2 --- /dev/null +++ b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/Consts.java @@ -0,0 +1,9 @@ +package org.cocos2dx.plugin; + +public interface Consts { + public static int EGETTING_ACCESS_TOKEN =0; + public static int EUSER_CANCELED = 1; + public static int EGETTING_REQUEST_TOKEN=2; + public static int EFAILED_OPENING_AUTHORIZATION_PAGE=3; + public static int EPAGE_ERROR =4; +} diff --git a/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/SocialTwitter.java b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/SocialTwitter.java new file mode 100755 index 0000000000..8a701a6fd0 --- /dev/null +++ b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/SocialTwitter.java @@ -0,0 +1,172 @@ +package org.cocos2dx.plugin; + +import java.util.Hashtable; + +import org.cocos2dx.plugin.InterfaceSocial.ShareAdapter; +import org.cocos2dx.plugin.TwitterApp.TwDialogListener; + +import android.app.Activity; +import android.content.Context; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.util.Log; + +public class SocialTwitter implements ShareAdapter { + + private static final String LOG_TAG = "SocialTwitter"; + private static Activity mContext = null; + protected static boolean bDebug = false; + private static String CONSUMER_KEY=""; + private static String CONSUMER_SECRET=""; + + private static TwitterApp mTwitter = null; + private static boolean isInitialized = false; + private static Hashtable mShareInfo = null; + + public static String KEY_TEXT="text"; + public static String KEY_IMAGE_PATH = "imagePath"; + + protected static void LogE(String msg, Exception e) { + Log.e(LOG_TAG, msg, e); + e.printStackTrace(); + } + + protected static void LogD(String msg) { + if (bDebug) { + Log.d(LOG_TAG, msg); + } + } + + public SocialTwitter(Context context) { + mContext = (Activity) context; + } + + + @Override + public void initDeveloperInfo(Hashtable cpInfo) { + LogD("initDeveloperInfo invoked " + cpInfo.toString()); + mShareInfo = cpInfo; + mShareInfo = cpInfo; + try { + SocialTwitter.CONSUMER_KEY = cpInfo.get("consumerkey"); + SocialTwitter.CONSUMER_SECRET = cpInfo.get("consumersecret"); + if(isInitialized){ + return; + } + isInitialized = true; + PluginWrapper.runOnMainThread(new Runnable() { + + @Override + public void run() { + mTwitter = new TwitterApp(PluginWrapper.getContext(), SocialTwitter.CONSUMER_KEY, SocialTwitter.CONSUMER_SECRET); + mTwitter.setListener(mTwLoginDialogListener); + } + }); + } catch (Exception e) { + LogE("Developer info is wrong!", e); + } + + } + + @Override + public void share(Hashtable info) { + LogD("share invoked " + info.toString()); + mShareInfo = info; + if (! networkReachable()) { + shareResult(InterfaceSocial.SHARERESULT_FAIL, "网络不可用"); + return; + } + // need login + if(!mTwitter.hasAccessToken()){ + PluginWrapper.runOnMainThread(new Runnable() { + + @Override + public void run() { + mTwitter.authorize(); + } + }); + + return; + } + + PluginWrapper.runOnMainThread(new Runnable() { + + @Override + public void run() { + String text = mShareInfo.get(KEY_TEXT); + String imagePath = mShareInfo.get(KEY_IMAGE_PATH); + try { + if(imagePath != null && imagePath.length() > 0){ + mTwitter.updateStatus(text, imagePath); + }else{ + mTwitter.updateStatus(text); + } + LogD("Posted to Twitter!"); + shareResult(InterfaceSocial.SHARERESULT_SUCCESS, "user lihex"); + } catch (Exception e) { + LogD("Post to Twitter failed!"); + shareResult(InterfaceSocial.SHARERESULT_FAIL, "user lihex"); + e.printStackTrace(); + } + } + }); + } + + @Override + public void setDebugMode(boolean debug) { + bDebug = debug; + } + + @Override + public String getSDKVersion() { + return "Unknown version"; + } + + private boolean networkReachable() { + boolean bRet = false; + try { + ConnectivityManager conn = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo netInfo = conn.getActiveNetworkInfo(); + bRet = (null == netInfo) ? false : netInfo.isAvailable(); + } catch (Exception e) { + LogE("Fail to check network status", e); + } + LogD("NetWork reachable : " + bRet); + return bRet; + } + + private static void shareResult(int ret, String msg) { + InterfaceSocial.shareResult(ret, msg); + LogD("SocialTwitter result : " + ret + " msg : " + msg); + } + + private static final TwDialogListener mTwLoginDialogListener = new TwDialogListener() { + + @Override + public void onError(int flag, String value) { + LogD("Twitter connection failed!"); + shareResult(InterfaceSocial.SHARERESULT_FAIL, value); + } + + @Override + public void onComplete(String value) { + String username = mTwitter.getUsername(); + LogD("Connected to Twitter as" + username); + String text = mShareInfo.get(KEY_TEXT); + String imagePath = mShareInfo.get(KEY_IMAGE_PATH); + try { + if(imagePath != null && imagePath.length() > 0){ + mTwitter.updateStatus(text, imagePath); + }else{ + mTwitter.updateStatus(text); + } + LogD("Posted to Twitter!"); + shareResult(InterfaceSocial.SHARERESULT_SUCCESS, username); + } catch (Exception e) { + LogD("Post to Twitter failed!"); + shareResult(InterfaceSocial.SHARERESULT_FAIL, username); + e.printStackTrace(); + } + } + }; +} diff --git a/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterApp.java b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterApp.java new file mode 100755 index 0000000000..61662c6b8b --- /dev/null +++ b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterApp.java @@ -0,0 +1,237 @@ +/** + * @author Lorensius W. L. T + * + * http://www.londatiga.net + */ + +package org.cocos2dx.plugin; + +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLDecoder; + +import oauth.signpost.OAuthProvider; +import oauth.signpost.basic.DefaultOAuthProvider; +import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer; +import twitter4j.StatusUpdate; +import twitter4j.Twitter; +import twitter4j.TwitterException; +import twitter4j.TwitterFactory; +import twitter4j.User; +import twitter4j.auth.AccessToken; +import android.app.Dialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Handler; +import android.os.Message; +import android.util.Log; +import android.view.Window; + +public class TwitterApp { + private Twitter mTwitter; + private TwitterSession mSession; + private AccessToken mAccessToken; + private CommonsHttpOAuthConsumer mHttpOauthConsumer; + private OAuthProvider mHttpOauthprovider; + private String mConsumerKey; + private String mSecretKey; + private ProgressDialog mProgressDlg; + private TwDialogListener mListener; + private Context context; + private boolean mInit = true; + private static final String LOG_TAG = "TwitterApp"; + public static final String CALLBACK_URL = "twitterapp://connect"; + + protected static void LogE(String msg, Exception e) { + Log.e(LOG_TAG, msg, e); + e.printStackTrace(); + } + + protected static void LogD(String msg) { + if (SocialTwitter.bDebug) { + Log.d(LOG_TAG, msg); + } + } + + + public TwitterApp(Context context, String consumerKey, String secretKey) { + this.context = context; + + mTwitter = new TwitterFactory().getInstance(); + mSession = new TwitterSession(context); + mProgressDlg = new ProgressDialog(context); + mProgressDlg.setCancelable(false); + mProgressDlg.requestWindowFeature(Window.FEATURE_NO_TITLE); + + mConsumerKey = consumerKey; + mSecretKey = secretKey; + + mHttpOauthConsumer = new CommonsHttpOAuthConsumer(mConsumerKey, mSecretKey); + mHttpOauthprovider = new DefaultOAuthProvider("https://twitter.com/oauth/request_token", + "https://twitter.com/oauth/access_token", + "https://twitter.com/oauth/authorize"); + + mAccessToken = mSession.getAccessToken(); + + configureToken(); + } + + public void setListener(TwDialogListener listener) { + mListener = listener; + } + + private void configureToken() { + if (mAccessToken != null) { + if (mInit) { + mTwitter.setOAuthConsumer(mConsumerKey, mSecretKey); + mInit = false; + } + mTwitter.setOAuthAccessToken(mAccessToken); + } + } + + public boolean hasAccessToken() { + return (mAccessToken == null) ? false : true; + } + + public void resetAccessToken() { + if (mAccessToken != null) { + mSession.resetAccessToken(); + mAccessToken = null; + } + } + + public String getUsername() { + return mSession.getUsername(); + } + + public void updateStatus(String status) throws Exception { + try { + mTwitter.updateStatus(status); + } catch (TwitterException e) { + throw e; + } + } + + public void updateStatus(String status, String imagePath) throws Exception { + StatusUpdate update = new StatusUpdate(status); + update.setMedia(new File(imagePath)); + try { + mTwitter.updateStatus(update); + } catch (TwitterException e) { + throw e; + } + } + + public void authorize() { + mProgressDlg.setMessage("Initializing ..."); + mProgressDlg.show(); + + new Thread() { + @Override + public void run() { + String authUrl = ""; + int what = 1; + try { + authUrl = mHttpOauthprovider.retrieveRequestToken(mHttpOauthConsumer, CALLBACK_URL); + what = 0; + LogD("Request token url " + authUrl); + } catch (Exception e) { + LogD("Failed to get request token"); + e.printStackTrace(); + } + mHandler.sendMessage(mHandler.obtainMessage(what, 1, 0, authUrl)); + } + }.start(); + } + + public void processToken(String callbackUrl) { + mProgressDlg.setMessage("Finalizing ..."); + mProgressDlg.show(); + + final String verifier = getVerifier(callbackUrl); + + new Thread() { + @Override + public void run() { + int what = 1; + try { + mHttpOauthprovider.retrieveAccessToken(mHttpOauthConsumer, verifier); + mAccessToken = new AccessToken(mHttpOauthConsumer.getToken(), mHttpOauthConsumer.getTokenSecret()); + configureToken(); + User user = mTwitter.verifyCredentials(); + mSession.storeAccessToken(mAccessToken, user.getName()); + what = 0; + } catch (Exception e){ + LogD("Error getting access token"); + e.printStackTrace(); + } + mHandler.sendMessage(mHandler.obtainMessage(what, 2, 0)); + } + }.start(); + } + + private String getVerifier(String callbackUrl) { + String verifier = ""; + try { + callbackUrl = callbackUrl.replace("twitterapp", "http"); + URL url = new URL(callbackUrl); + String query = url.getQuery(); + String array[] = query.split("&"); + for (String parameter : array) { + String v[] = parameter.split("="); + if (URLDecoder.decode(v[0]).equals(oauth.signpost.OAuth.OAUTH_VERIFIER)) { + verifier = URLDecoder.decode(v[1]); + break; + } + } + } catch (MalformedURLException e) { + e.printStackTrace(); + } + return verifier; + } + + private void showLoginDialog(String url) { + final TwDialogListener listener = new TwDialogListener() { + @Override + public void onComplete(String value) { + processToken(value); + } + + @Override + public void onError(int flag, String value) { + mListener.onError(Consts.EFAILED_OPENING_AUTHORIZATION_PAGE, "Failed opening authorization page"); + } + }; + + new TwitterDialog(context, url, listener).show(); + } + + private Handler mHandler = new Handler() { + @Override + public void handleMessage(Message msg) { + mProgressDlg.dismiss(); + + if (msg.what == 1) { + if (msg.arg1 == 1) + mListener.onError(Consts.EGETTING_REQUEST_TOKEN, "Error getting request token"); + else + mListener.onError(Consts.EGETTING_ACCESS_TOKEN, "Error getting access token"); + }else { + if (msg.arg1 == 1) + showLoginDialog((String) msg.obj); + else + mListener.onComplete(""); + } + } + }; + + public interface TwDialogListener { + public void onComplete(String value); + + public void onError(int flag, String value); + } + +} \ No newline at end of file diff --git a/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterDialog.java b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterDialog.java new file mode 100755 index 0000000000..68303860a6 --- /dev/null +++ b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterDialog.java @@ -0,0 +1,182 @@ +/** + * Modified from FbDialog from Facebook SDK + * + * Lorensius W. L. T + */ +package org.cocos2dx.plugin; + +import org.cocos2dx.plugin.TwitterApp.TwDialogListener; + +import android.app.Dialog; +import android.app.ProgressDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.util.Log; +import android.view.Display; +import android.view.ViewGroup; +import android.view.Window; +import android.webkit.CookieManager; +import android.webkit.CookieSyncManager; +import android.webkit.WebView; +import android.webkit.WebViewClient; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +public class TwitterDialog extends Dialog { + static final FrameLayout.LayoutParams FILL = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, + ViewGroup.LayoutParams.FILL_PARENT); + static final int MARGIN = 4; + static final int PADDING = 2; + + private String mUrl; + private TwDialogListener mListener; + private ProgressDialog mSpinner; + private WebView mWebView; + private LinearLayout mContent; + private TextView mTitle; + + private static final String LOG_TAG = "Twitter-WebView"; + + protected static void LogD(String msg) { + if (SocialTwitter.bDebug) { + Log.d(LOG_TAG, msg); + } + } + public TwitterDialog(Context context, String url, TwDialogListener listener) { + super(context); + + mUrl = url; + mListener = listener; + setOnCancelListener(mCancelListener); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mSpinner = new ProgressDialog(getContext()); + + mSpinner.requestWindowFeature(Window.FEATURE_NO_TITLE); + mSpinner.setMessage("Loading..."); + mSpinner.setCancelable(false); + + mContent = new LinearLayout(getContext()); + + mContent.setOrientation(LinearLayout.VERTICAL); + + setUpTitle(); + setUpWebView(); + + Display display = getWindow().getWindowManager().getDefaultDisplay(); + double[] dimensions = new double[2]; + + if (display.getWidth() < display.getHeight()) { + dimensions[0] = 0.87 * display.getWidth(); + dimensions[1] = 0.82 * display.getHeight(); + } else { + dimensions[0] = 0.75 * display.getWidth(); + dimensions[1] = 0.75 * display.getHeight(); + } + + addContentView(mContent, new FrameLayout.LayoutParams((int) dimensions[0], (int) dimensions[1])); + } + + private void setUpTitle() { + requestWindowFeature(Window.FEATURE_NO_TITLE); + + // Drawable icon = getContext().getResources().getDrawable(R.drawable.twitter_icon); + + mTitle = new TextView(getContext()); + + mTitle.setText("Twitter"); + mTitle.setTextColor(Color.WHITE); + mTitle.setTypeface(Typeface.DEFAULT_BOLD); + mTitle.setBackgroundColor(0xFFbbd7e9); + mTitle.setPadding(MARGIN + PADDING, MARGIN, MARGIN, MARGIN); + mTitle.setCompoundDrawablePadding(MARGIN + PADDING); + // mTitle.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null); + mTitle.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); + + mContent.addView(mTitle); + } + + private void setUpWebView() { + CookieSyncManager.createInstance(getContext()); + CookieManager cookieManager = CookieManager.getInstance(); + cookieManager.removeAllCookie(); + + mWebView = new WebView(getContext()); + + mWebView.setVerticalScrollBarEnabled(false); + mWebView.setHorizontalScrollBarEnabled(false); + mWebView.setWebViewClient(new TwitterWebViewClient()); + mWebView.getSettings().setJavaScriptEnabled(true); + mWebView.loadUrl(mUrl); + mWebView.setLayoutParams(FILL); + + + mContent.addView(mWebView); + } + + private class TwitterWebViewClient extends WebViewClient { + + @Override + public boolean shouldOverrideUrlLoading(WebView view, String url) { + LogD("Redirecting URL " + url); + + if (url.startsWith(TwitterApp.CALLBACK_URL)) { + mListener.onComplete(url); + + TwitterDialog.this.dismiss(); + + return true; + } else if (url.startsWith("authorize")) { + return false; + } + + return true; + } + + @Override + public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) { + LogD("Page error: " + description); + + super.onReceivedError(view, errorCode, description, failingUrl); + + mListener.onError(Consts.EPAGE_ERROR, description); + + TwitterDialog.this.dismiss(); + } + + @Override + public void onPageStarted(WebView view, String url, Bitmap favicon) { + LogD("Loading URL: " + url); + super.onPageStarted(view, url, favicon); + mSpinner.show(); + } + + @Override + public void onPageFinished(WebView view, String url) { + super.onPageFinished(view, url); + String title = mWebView.getTitle(); + if (title != null && title.length() > 0) { + mTitle.setText(title); + } + mSpinner.dismiss(); + } + } + + private DialogInterface.OnCancelListener mCancelListener = new OnCancelListener() { + + @Override + public void onCancel(DialogInterface dialog) { + mSpinner.dismiss(); + mListener.onError(Consts.EUSER_CANCELED, "User canceled!"); + } + }; +} diff --git a/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterSession.java b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterSession.java new file mode 100755 index 0000000000..adcb4fe3ea --- /dev/null +++ b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterSession.java @@ -0,0 +1,56 @@ +/** + * @author Lorensius W. L. T + * + * http://www.londatiga.net + */ +package org.cocos2dx.plugin; + +import twitter4j.auth.AccessToken; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.SharedPreferences.Editor; + +public class TwitterSession { + private SharedPreferences sharedPref; + private Editor editor; + + private static final String TWEET_AUTH_KEY = "auth_key"; + private static final String TWEET_AUTH_SECRET_KEY = "auth_secret_key"; + private static final String TWEET_USER_NAME = "user_name"; + private static final String SHARED = "Twitter_Preferences"; + + public TwitterSession(Context context) { + sharedPref = context.getSharedPreferences(SHARED, Context.MODE_PRIVATE); + editor = sharedPref.edit(); + } + + public void storeAccessToken(AccessToken accessToken, String username) { + editor.putString(TWEET_AUTH_KEY, accessToken.getToken()); + editor.putString(TWEET_AUTH_SECRET_KEY, accessToken.getTokenSecret()); + editor.putString(TWEET_USER_NAME, username); + + editor.commit(); + } + + public void resetAccessToken() { + editor.putString(TWEET_AUTH_KEY, null); + editor.putString(TWEET_AUTH_SECRET_KEY, null); + editor.putString(TWEET_USER_NAME, null); + + editor.commit(); + } + + public String getUsername() { + return sharedPref.getString(TWEET_USER_NAME, ""); + } + + public AccessToken getAccessToken() { + String token = sharedPref.getString(TWEET_AUTH_KEY, null); + String tokenSecret = sharedPref.getString(TWEET_AUTH_SECRET_KEY, null); + + if (token != null && tokenSecret != null) + return new AccessToken(token, tokenSecret); + else + return null; + } +} \ No newline at end of file diff --git a/plugin/tools/config.sh b/plugin/tools/config.sh index 704df1e450..633aa08126 100755 --- a/plugin/tools/config.sh +++ b/plugin/tools/config.sh @@ -1,7 +1,8 @@ #define plugins array export ALL_PLUGINS=("flurry" "umeng" \ "alipay" "nd91" \ -"admob") +"admob" \ +"twitter") # define the plugin root directory & publish target directory export TARGET_DIR_NAME="publish" From 661977645e5a21719f286115c535406a7857d7ce Mon Sep 17 00:00:00 2001 From: lihex Date: Wed, 24 Apr 2013 16:00:36 +0800 Subject: [PATCH 04/85] Add HelloSocial sample --- .../HelloSocial/Classes/AppDelegate.cpp | 60 +++++++++ .../samples/HelloSocial/Classes/AppDelegate.h | 40 ++++++ .../HelloSocial/Classes/HelloWorldScene.cpp | 126 ++++++++++++++++++ .../HelloSocial/Classes/HelloWorldScene.h | 24 ++++ .../HelloSocial/Classes/MyShareManager.cpp | 106 +++++++++++++++ .../HelloSocial/Classes/MyShareManager.h | 37 +++++ .../Resources/background.png.REMOVED.git-id | 1 + .../HelloSocial/proj.android/.classpath | 14 ++ .../samples/HelloSocial/proj.android/.project | 45 +++++++ .../proj.android/AndroidManifest.xml | 30 +++++ .../HelloSocial/proj.android/ant.properties | 17 +++ .../HelloSocial/proj.android/build.xml | 92 +++++++++++++ .../HelloSocial/proj.android/build_native.sh | 81 +++++++++++ .../HelloSocial/proj.android/jni/Android.mk | 24 ++++ .../proj.android/jni/Application.mk | 2 + .../proj.android/jni/hellocpp/main.cpp | 47 +++++++ .../proj.android/proguard-project.txt | 20 +++ .../proj.android/project.properties | 15 +++ .../proj.android/res/values/strings.xml | 4 + .../org/cocos2dx/helloSocial/HelloSocial.java | 43 ++++++ 20 files changed, 828 insertions(+) create mode 100755 plugin/samples/HelloSocial/Classes/AppDelegate.cpp create mode 100755 plugin/samples/HelloSocial/Classes/AppDelegate.h create mode 100755 plugin/samples/HelloSocial/Classes/HelloWorldScene.cpp create mode 100755 plugin/samples/HelloSocial/Classes/HelloWorldScene.h create mode 100755 plugin/samples/HelloSocial/Classes/MyShareManager.cpp create mode 100755 plugin/samples/HelloSocial/Classes/MyShareManager.h create mode 100644 plugin/samples/HelloSocial/Resources/background.png.REMOVED.git-id create mode 100755 plugin/samples/HelloSocial/proj.android/.classpath create mode 100755 plugin/samples/HelloSocial/proj.android/.project create mode 100755 plugin/samples/HelloSocial/proj.android/AndroidManifest.xml create mode 100755 plugin/samples/HelloSocial/proj.android/ant.properties create mode 100755 plugin/samples/HelloSocial/proj.android/build.xml create mode 100755 plugin/samples/HelloSocial/proj.android/build_native.sh create mode 100755 plugin/samples/HelloSocial/proj.android/jni/Android.mk create mode 100755 plugin/samples/HelloSocial/proj.android/jni/Application.mk create mode 100755 plugin/samples/HelloSocial/proj.android/jni/hellocpp/main.cpp create mode 100755 plugin/samples/HelloSocial/proj.android/proguard-project.txt create mode 100755 plugin/samples/HelloSocial/proj.android/project.properties create mode 100755 plugin/samples/HelloSocial/proj.android/res/values/strings.xml create mode 100755 plugin/samples/HelloSocial/proj.android/src/org/cocos2dx/helloSocial/HelloSocial.java diff --git a/plugin/samples/HelloSocial/Classes/AppDelegate.cpp b/plugin/samples/HelloSocial/Classes/AppDelegate.cpp new file mode 100755 index 0000000000..1efcdf0b4c --- /dev/null +++ b/plugin/samples/HelloSocial/Classes/AppDelegate.cpp @@ -0,0 +1,60 @@ +#include "AppDelegate.h" +#include "cocos2d.h" +#include "HelloWorldScene.h" +#include "PluginManager.h" +#include "MyShareManager.h" + +using namespace cocos2d::plugin; +USING_NS_CC; + +AppDelegate::AppDelegate() +{ + +} + +AppDelegate::~AppDelegate() +{ + +} + +bool AppDelegate::applicationDidFinishLaunching() +{ + MyShareManager::sharedManager()->loadSocialPlugin(); + + // initialize director + CCDirector *pDirector = CCDirector::sharedDirector(); + pDirector->setOpenGLView(CCEGLView::sharedOpenGLView()); + CCEGLView* pEGLView = CCEGLView::sharedOpenGLView(); + pEGLView->setDesignResolutionSize(960.0f, 640.0f, kResolutionNoBorder); + // turn on display FPS + pDirector->setDisplayStats(true); + + // set FPS. the default value is 1.0/60 if you don't call this + pDirector->setAnimationInterval(1.0 / 60); + + // create a scene. it's an autorelease object + CCScene *pScene = HelloWorld::scene(); + + // run + pDirector->runWithScene(pScene); + + return true; +} + +// This function will be called when the app is inactive. When comes a phone call,it's be invoked too +void AppDelegate::applicationDidEnterBackground() +{ + CCDirector::sharedDirector()->pause(); + + // if you use SimpleAudioEngine, it must be pause + // SimpleAudioEngine::sharedEngine()->pauseBackgroundMusic(); +} + +// this function will be called when the app is active again +void AppDelegate::applicationWillEnterForeground() +{ + CCDirector::sharedDirector()->resume(); + + // if you use SimpleAudioEngine, it must resume here + // SimpleAudioEngine::sharedEngine()->resumeBackgroundMusic(); +} diff --git a/plugin/samples/HelloSocial/Classes/AppDelegate.h b/plugin/samples/HelloSocial/Classes/AppDelegate.h new file mode 100755 index 0000000000..d036940402 --- /dev/null +++ b/plugin/samples/HelloSocial/Classes/AppDelegate.h @@ -0,0 +1,40 @@ +#ifndef _APP_DELEGATE_H_ +#define _APP_DELEGATE_H_ + +#include "CCApplication.h" + +/** +@brief The cocos2d Application. + +The reason for implement as private inheritance is to hide some interface call by CCDirector. +*/ +class AppDelegate : private cocos2d::CCApplication +{ +public: + AppDelegate(); + virtual ~AppDelegate(); + + /** + @brief Implement CCDirector and CCScene init code here. + @return true Initialize success, app continue. + @return false Initialize failed, app terminate. + */ + virtual bool applicationDidFinishLaunching(); + + /** + @brief The function be called when the application enter background + @param the pointer of the application + */ + virtual void applicationDidEnterBackground(); + + /** + @brief The function be called when the application enter foreground + @param the pointer of the application + */ + virtual void applicationWillEnterForeground(); + + static void loadAnalyticsPlugin(); +}; + +#endif // _APP_DELEGATE_H_ + diff --git a/plugin/samples/HelloSocial/Classes/HelloWorldScene.cpp b/plugin/samples/HelloSocial/Classes/HelloWorldScene.cpp new file mode 100755 index 0000000000..75535b2d64 --- /dev/null +++ b/plugin/samples/HelloSocial/Classes/HelloWorldScene.cpp @@ -0,0 +1,126 @@ +#include "HelloWorldScene.h" +#include "PluginManager.h" +#include "AppDelegate.h" +#include "MyShareManager.h" + +using namespace cocos2d; +using namespace cocos2d::plugin; + +enum { + TAG_PAY_BY_ALIPAY = 100, + TAG_PAY_BY_ND91, +}; + +typedef struct tagEventMenuItem { + std::string id; + int tag; +}EventMenuItem; + +static EventMenuItem s_EventMenuItem[] = { + {"twitter.jpeg", TAG_PAY_BY_ALIPAY} +}; + +CCScene* HelloWorld::scene() +{ + // 'scene' is an autorelease object + CCScene *scene = CCScene::create(); + + // 'layer' is an autorelease object + HelloWorld *layer = HelloWorld::create(); + + // add layer as a child to scene + scene->addChild(layer); + + // return the scene + return scene; +} + +// on "init" you need to initialize your instance +bool HelloWorld::init() +{ + ////////////////////////////// + // 1. super init first + if ( !CCLayer::init() ) + { + return false; + } + + CCSize size = CCDirector::sharedDirector()->getVisibleSize(); + + CCSprite* pBackground = CCSprite::create("background.png"); + pBackground->setPosition(ccp(size.width / 2, size.height / 2)); + addChild(pBackground); + ///////////////////////////// + // 2. add a menu item with "X" image, which is clicked to quit the program + // you may modify it. + + CCEGLView* pEGLView = CCEGLView::sharedOpenGLView(); + CCPoint posBR = ccp(pEGLView->getVisibleOrigin().x + pEGLView->getVisibleSize().width, pEGLView->getVisibleOrigin().y); + CCPoint posBC = ccp(pEGLView->getVisibleOrigin().x + pEGLView->getVisibleSize().width/2, pEGLView->getVisibleOrigin().y); + CCPoint posTL = ccp(pEGLView->getVisibleOrigin().x, pEGLView->getVisibleOrigin().y + pEGLView->getVisibleSize().height); + + // add a "close" icon to exit the progress. it's an autorelease object + CCMenuItemImage *pCloseItem = CCMenuItemImage::create( + "CloseNormal.png", + "CloseSelected.png", + this, + menu_selector(HelloWorld::menuCloseCallback) ); + pCloseItem->setPosition( ccp(posBR.x - 20, posBR.y + 20) ); + + // create menu, it's an autorelease object + CCMenu* pMenu = CCMenu::create(pCloseItem, NULL); + pMenu->setPosition( CCPointZero ); + this->addChild(pMenu, 1); + + CCPoint posStep = ccp(220, -150); + CCPoint beginPos = ccpAdd(posTL, ccpMult(posStep, 0.5f)); + int line = 0; + int row = 0; + for (int i = 0; i < sizeof(s_EventMenuItem)/sizeof(s_EventMenuItem[0]); i++) { + CCMenuItemImage* pMenuItem = CCMenuItemImage::create(s_EventMenuItem[i].id.c_str(), s_EventMenuItem[i].id.c_str(), + this, menu_selector(HelloWorld::eventMenuCallback)); + pMenu->addChild(pMenuItem, 0, s_EventMenuItem[i].tag); + + CCPoint pos = ccpAdd(beginPos, ccp(posStep.x * row, posStep.y * line)); + CCSize itemSize = pMenuItem->getContentSize(); + if ((pos.x + itemSize.width / 2) > posBR.x) + { + line += 1; + row = 0; + pos = ccpAdd(beginPos, ccp(posStep.x * row, posStep.y * line)); + } + row += 1; + pMenuItem->setPosition(pos); + } + + CCLabelTTF* label = CCLabelTTF::create("Reload all plugins", "Arial", 24); + CCMenuItemLabel* pMenuItem = CCMenuItemLabel::create(label, this, menu_selector(HelloWorld::reloadPluginMenuCallback)); + pMenuItem->setAnchorPoint(ccp(0.5f, 0)); + pMenu->addChild(pMenuItem, 0); + pMenuItem->setPosition(posBC); + + return true; +} + +void HelloWorld::reloadPluginMenuCallback(CCObject* pSender) +{ + MyShareManager::sharedManager()->unloadSocialPlugin(); + MyShareManager::sharedManager()->loadSocialPlugin(); +} + +void HelloWorld::eventMenuCallback(CCObject* pSender) +{ + TShareInfo pInfo; + pInfo["text"] = "MyFirst tweet!"; + // pInfo["imagePath"] = "Full/path/to/image"; + MyShareManager::sharedManager()->shareByMode(pInfo, MyShareManager::eTwitter); +} + +void HelloWorld::menuCloseCallback(CCObject* pSender) +{ + MyShareManager::purgeManager(); + CCDirector::sharedDirector()->end(); +#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) + exit(0); +#endif +} diff --git a/plugin/samples/HelloSocial/Classes/HelloWorldScene.h b/plugin/samples/HelloSocial/Classes/HelloWorldScene.h new file mode 100755 index 0000000000..cf90652eeb --- /dev/null +++ b/plugin/samples/HelloSocial/Classes/HelloWorldScene.h @@ -0,0 +1,24 @@ +#ifndef __HELLOWORLD_SCENE_H__ +#define __HELLOWORLD_SCENE_H__ + +#include "cocos2d.h" + +class HelloWorld : public cocos2d::CCLayer +{ +public: + // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone + virtual bool init(); + + // there's no 'id' in cpp, so we recommand to return the exactly class pointer + static cocos2d::CCScene* scene(); + + // a selector callback + void menuCloseCallback(CCObject* pSender); + void eventMenuCallback(CCObject* pSender); + void reloadPluginMenuCallback(CCObject* pSender); + + // implement the "static node()" method manually + CREATE_FUNC(HelloWorld); +}; + +#endif // __HELLOWORLD_SCENE_H__ diff --git a/plugin/samples/HelloSocial/Classes/MyShareManager.cpp b/plugin/samples/HelloSocial/Classes/MyShareManager.cpp new file mode 100755 index 0000000000..9bd4add8e2 --- /dev/null +++ b/plugin/samples/HelloSocial/Classes/MyShareManager.cpp @@ -0,0 +1,106 @@ +#include "MyShareManager.h" +#include "PluginManager.h" +#include "cocos2d.h" + +using namespace cocos2d::plugin; +using namespace cocos2d; + +MyShareManager* MyShareManager::s_pManager = NULL; + +MyShareManager::MyShareManager() +: s_pRetListener(NULL) +, s_pTwitter(NULL) +{ + +} + +MyShareManager::~MyShareManager() +{ + unloadSocialPlugin(); + if (s_pRetListener) + { + delete s_pRetListener; + } +} + +MyShareManager* MyShareManager::sharedManager() +{ + if (s_pManager == NULL) { + s_pManager = new MyShareManager(); + } + return s_pManager; +} + +void MyShareManager::purgeManager() +{ + if (s_pManager) + { + delete s_pManager; + } +} + +void MyShareManager::loadSocialPlugin() +{ + { + // init twitter plugin + s_pTwitter = dynamic_cast(PluginManager::getInstance()->loadPlugin("SocialTwitter")); + TDeveloperInfo pTwitterInfo; + + /* Warning: must set your twiiter dev info here */ + // pTwitterInfo["consumerkey"] = "your consumerkey"; + // pTwitterInfo["consumersecret"] = "your consumersecret"; + + if (pTwitterInfo.empty()) + { + char msg[256] = { 0 }; + sprintf(msg, "Developer info is empty. PLZ fill your twitter info in %s(nearby line %d)", __FILE__, __LINE__); + CCMessageBox(msg, "Twitter Warning"); + } + s_pTwitter->setDebugMode(true); + s_pTwitter->initDeveloperInfo(pTwitterInfo); + } + + if (s_pRetListener == NULL) + { + s_pRetListener = new MyShareResult(); + ProtocolSocial::setResultListener(s_pRetListener); + } +} + +void MyShareManager::unloadSocialPlugin() +{ + if (s_pTwitter) + { + PluginManager::getInstance()->unloadPlugin("SocialTwitter"); + s_pTwitter = NULL; + } +} + +void MyShareManager::shareByMode(TShareInfo info, MyShareMode mode) +{ + ProtocolSocial* pShare = NULL; + switch(mode) + { + case eTwitter: + pShare = s_pTwitter; + break; + default: + break; + } + + if (pShare) { + pShare->share(info); + } +} + +void MyShareResult::shareResult(EShareResult ret, const char* msg, TShareInfo info) +{ + char shareInfo[1024] = { 0 }; + char shareStatus[1024] = { 0 }; + sprintf(shareStatus, "Share info:%s", (ret == eShareSuccess)? "Successed" : "Failed"); + sprintf(shareInfo, " %s\ntext:%s", + shareStatus, + info.find("text")->second.c_str() + ); + CCMessageBox(shareInfo , msg); +} diff --git a/plugin/samples/HelloSocial/Classes/MyShareManager.h b/plugin/samples/HelloSocial/Classes/MyShareManager.h new file mode 100755 index 0000000000..a8c65eea67 --- /dev/null +++ b/plugin/samples/HelloSocial/Classes/MyShareManager.h @@ -0,0 +1,37 @@ +#ifndef __MY_SHARE_MANAGER_H__ +#define __MY_SHARE_MANAGER_H__ + +#include "SocialTwitter.h" + +class MyShareResult : public cocos2d::plugin::ShareResultListener +{ +public: + virtual void shareResult(cocos2d::plugin::EShareResult ret, const char* msg, cocos2d::plugin::TShareInfo info); +}; + +class MyShareManager +{ +public: + static MyShareManager* sharedManager(); + static void purgeManager(); + + typedef enum { + eNoneMode = 0, + eTwitter, + } MyShareMode; + + void unloadSocialPlugin(); + void loadSocialPlugin(); + void shareByMode(cocos2d::plugin::TShareInfo info, MyShareMode mode); + +private: + MyShareManager(); + virtual ~MyShareManager(); + + static MyShareManager* s_pManager; + + cocos2d::plugin::SocialTwitter* s_pTwitter; + MyShareResult* s_pRetListener; +}; + +#endif // __MY_SHARE_MANAGER_H__ diff --git a/plugin/samples/HelloSocial/Resources/background.png.REMOVED.git-id b/plugin/samples/HelloSocial/Resources/background.png.REMOVED.git-id new file mode 100644 index 0000000000..15b10523a1 --- /dev/null +++ b/plugin/samples/HelloSocial/Resources/background.png.REMOVED.git-id @@ -0,0 +1 @@ +b2e4ae6ce873ef4a74cf0230693ef26e939d2778 \ No newline at end of file diff --git a/plugin/samples/HelloSocial/proj.android/.classpath b/plugin/samples/HelloSocial/proj.android/.classpath new file mode 100755 index 0000000000..2115f0c73a --- /dev/null +++ b/plugin/samples/HelloSocial/proj.android/.classpath @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/plugin/samples/HelloSocial/proj.android/.project b/plugin/samples/HelloSocial/proj.android/.project new file mode 100755 index 0000000000..6328a7480a --- /dev/null +++ b/plugin/samples/HelloSocial/proj.android/.project @@ -0,0 +1,45 @@ + + + HelloSocial + + + + + + com.android.ide.eclipse.adt.ResourceManagerBuilder + + + + + com.android.ide.eclipse.adt.PreCompilerBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + com.android.ide.eclipse.adt.ApkBuilder + + + + + + com.android.ide.eclipse.adt.AndroidNature + org.eclipse.jdt.core.javanature + + + + Classes + 2 + PARENT-1-PROJECT_LOC/Classes + + + publish + 2 + PARENT-3-PROJECT_LOC/publish + + + diff --git a/plugin/samples/HelloSocial/proj.android/AndroidManifest.xml b/plugin/samples/HelloSocial/proj.android/AndroidManifest.xml new file mode 100755 index 0000000000..dc93dff99a --- /dev/null +++ b/plugin/samples/HelloSocial/proj.android/AndroidManifest.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/plugin/samples/HelloSocial/proj.android/ant.properties b/plugin/samples/HelloSocial/proj.android/ant.properties new file mode 100755 index 0000000000..b0971e891e --- /dev/null +++ b/plugin/samples/HelloSocial/proj.android/ant.properties @@ -0,0 +1,17 @@ +# This file is used to override default values used by the Ant build system. +# +# This file must be checked into Version Control Systems, as it is +# integral to the build system of your project. + +# This file is only used by the Ant script. + +# You can use this to override default values such as +# 'source.dir' for the location of your java source folder and +# 'out.dir' for the location of your output folder. + +# You can also use it define how the release builds are signed by declaring +# the following properties: +# 'key.store' for the location of your keystore and +# 'key.alias' for the name of the key to use. +# The password will be asked during the build when you use the 'release' target. + diff --git a/plugin/samples/HelloSocial/proj.android/build.xml b/plugin/samples/HelloSocial/proj.android/build.xml new file mode 100755 index 0000000000..80abad0ab0 --- /dev/null +++ b/plugin/samples/HelloSocial/proj.android/build.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugin/samples/HelloSocial/proj.android/build_native.sh b/plugin/samples/HelloSocial/proj.android/build_native.sh new file mode 100755 index 0000000000..01fc562132 --- /dev/null +++ b/plugin/samples/HelloSocial/proj.android/build_native.sh @@ -0,0 +1,81 @@ +APPNAME="HelloAnalytics" + +# options + +buildexternalsfromsource= + +usage(){ +cat << EOF +usage: $0 [options] + +Build C/C++ code for $APPNAME using Android NDK + +OPTIONS: +-s Build externals from source +-h this help +EOF +} + +while getopts "sh" OPTION; do +case "$OPTION" in +s) +buildexternalsfromsource=1 +;; +h) +usage +exit 0 +;; +esac +done + +# paths + +if [ -z "${NDK_ROOT+aaa}" ];then +echo "please define NDK_ROOT" +exit 1 +fi + +DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +# ... use paths relative to current directory +PLUGIN_ROOT="$DIR/../../.." +COCOS2DX_ROOT="$DIR/../../../.." +APP_ROOT="$DIR/.." +APP_ANDROID_ROOT="$DIR" + +echo "PLUGIN_ROOT = $PLUGIN_ROOT" +echo "NDK_ROOT = $NDK_ROOT" +echo "COCOS2DX_ROOT = $COCOS2DX_ROOT" +echo "APP_ROOT = $APP_ROOT" +echo "APP_ANDROID_ROOT = $APP_ANDROID_ROOT" +echo "---------------------------------------------------------" + +# make sure assets is exist +if [ -d "$APP_ANDROID_ROOT"/assets ]; then + rm -rf "$APP_ANDROID_ROOT"/assets +fi + +mkdir "$APP_ANDROID_ROOT"/assets + +# copy resources +for file in "$APP_ROOT"/Resources/* +do +if [ -d "$file" ]; then + cp -rf "$file" "$APP_ANDROID_ROOT"/assets +fi + +if [ -f "$file" ]; then + cp "$file" "$APP_ANDROID_ROOT"/assets +fi +done + +if [[ "$buildexternalsfromsource" ]]; then + echo "Building external dependencies from source" + set -x + "$NDK_ROOT"/ndk-build -j 4 -C "$APP_ANDROID_ROOT" $* \ + "NDK_MODULE_PATH=${PLUGIN_ROOT}/publish:${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/source" +else + echo "Using prebuilt externals" + set -x + "$NDK_ROOT"/ndk-build -j 4 -C "$APP_ANDROID_ROOT" $* \ + "NDK_MODULE_PATH=${PLUGIN_ROOT}/publish:${COCOS2DX_ROOT}:${COCOS2DX_ROOT}/cocos2dx/platform/third_party/android/prebuilt" +fi diff --git a/plugin/samples/HelloSocial/proj.android/jni/Android.mk b/plugin/samples/HelloSocial/proj.android/jni/Android.mk new file mode 100755 index 0000000000..3e8cd941a2 --- /dev/null +++ b/plugin/samples/HelloSocial/proj.android/jni/Android.mk @@ -0,0 +1,24 @@ +LOCAL_PATH := $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_MODULE := game_shared + +LOCAL_MODULE_FILENAME := libgame + +LOCAL_SRC_FILES := hellocpp/main.cpp \ + ../../Classes/AppDelegate.cpp \ + ../../Classes/HelloWorldScene.cpp \ + ../../Classes/MyShareManager.cpp + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes + +LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static \ + PluginTwitterStatic \ + PluginProtocolStatic + +include $(BUILD_SHARED_LIBRARY) + +$(call import-module,cocos2dx) \ +$(call import-module,plugins/twitter/android) \ +$(call import-module,protocols/android) diff --git a/plugin/samples/HelloSocial/proj.android/jni/Application.mk b/plugin/samples/HelloSocial/proj.android/jni/Application.mk new file mode 100755 index 0000000000..d16d4facd2 --- /dev/null +++ b/plugin/samples/HelloSocial/proj.android/jni/Application.mk @@ -0,0 +1,2 @@ +APP_STL := gnustl_static +APP_CPPFLAGS += -frtti \ No newline at end of file diff --git a/plugin/samples/HelloSocial/proj.android/jni/hellocpp/main.cpp b/plugin/samples/HelloSocial/proj.android/jni/hellocpp/main.cpp new file mode 100755 index 0000000000..ee1079c797 --- /dev/null +++ b/plugin/samples/HelloSocial/proj.android/jni/hellocpp/main.cpp @@ -0,0 +1,47 @@ +#include "AppDelegate.h" +#include "platform/android/jni/JniHelper.h" +#include "PluginJniHelper.h" +#include +#include + +#include "HelloWorldScene.h" + +#define LOG_TAG "main" +#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__) + +using namespace cocos2d; + +extern "C" +{ + +jint JNI_OnLoad(JavaVM *vm, void *reserved) +{ + JniHelper::setJavaVM(vm); + PluginJniHelper::setJavaVM(vm); + + return JNI_VERSION_1_4; +} + +void Java_org_cocos2dx_lib_Cocos2dxRenderer_nativeInit(JNIEnv* env, jobject thiz, jint w, jint h) +{ + if (!CCDirector::sharedDirector()->getOpenGLView()) + { + CCEGLView *view = CCEGLView::sharedOpenGLView(); + view->setFrameSize(w, h); + + AppDelegate *pAppDelegate = new AppDelegate(); + CCApplication::sharedApplication()->run(); + } + else + { + ccDrawInit(); + ccGLInvalidateStateCache(); + + CCShaderCache::sharedShaderCache()->reloadDefaultShaders(); + CCTextureCache::reloadAllTextures(); + CCNotificationCenter::sharedNotificationCenter()->postNotification(EVNET_COME_TO_FOREGROUND, NULL); + CCDirector::sharedDirector()->setGLDefaultValues(); + } +} + +} diff --git a/plugin/samples/HelloSocial/proj.android/proguard-project.txt b/plugin/samples/HelloSocial/proj.android/proguard-project.txt new file mode 100755 index 0000000000..b60ae7ea07 --- /dev/null +++ b/plugin/samples/HelloSocial/proj.android/proguard-project.txt @@ -0,0 +1,20 @@ +# To enable ProGuard in your project, edit project.properties +# to define the proguard.config property as described in that file. +# +# Add project specific ProGuard rules here. +# By default, the flags in this file are appended to flags specified +# in ${sdk.dir}/tools/proguard/proguard-android.txt +# You can edit the include path and order by changing the ProGuard +# include property in project.properties. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# Add any project specific keep options here: + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} diff --git a/plugin/samples/HelloSocial/proj.android/project.properties b/plugin/samples/HelloSocial/proj.android/project.properties new file mode 100755 index 0000000000..859630e465 --- /dev/null +++ b/plugin/samples/HelloSocial/proj.android/project.properties @@ -0,0 +1,15 @@ +# This file is automatically generated by Android Tools. +# Do not modify this file -- YOUR CHANGES WILL BE ERASED! +# +# This file must be checked in Version Control Systems. +# +# To customize properties used by the Ant build system edit +# "ant.properties", and override values to adapt the script to your +# project structure. +# +# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): +#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt + +# Project target. +target=android-8 +android.library.reference.1=../../../../cocos2dx/platform/android/java diff --git a/plugin/samples/HelloSocial/proj.android/res/values/strings.xml b/plugin/samples/HelloSocial/proj.android/res/values/strings.xml new file mode 100755 index 0000000000..320a39b235 --- /dev/null +++ b/plugin/samples/HelloSocial/proj.android/res/values/strings.xml @@ -0,0 +1,4 @@ + + + HelloSocial + diff --git a/plugin/samples/HelloSocial/proj.android/src/org/cocos2dx/helloSocial/HelloSocial.java b/plugin/samples/HelloSocial/proj.android/src/org/cocos2dx/helloSocial/HelloSocial.java new file mode 100755 index 0000000000..cc2a90bf8e --- /dev/null +++ b/plugin/samples/HelloSocial/proj.android/src/org/cocos2dx/helloSocial/HelloSocial.java @@ -0,0 +1,43 @@ +/**************************************************************************** +Copyright (c) 2010-2012 cocos2d-x.org + +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.helloSocial; + +import org.cocos2dx.lib.Cocos2dxActivity; +import org.cocos2dx.lib.Cocos2dxGLSurfaceView; +import org.cocos2dx.plugin.PluginWrapper; + +import android.os.Bundle; + +public class HelloSocial extends Cocos2dxActivity{ + + protected void onCreate(Bundle savedInstanceState){ + super.onCreate(savedInstanceState); + PluginWrapper.init(this); + PluginWrapper.setGLSurfaceView(Cocos2dxGLSurfaceView.getInstance()); + } + + static { + System.loadLibrary("game"); + } +} From f7e07188b23e5890bdc4c3cd5fe2a515266e6bce Mon Sep 17 00:00:00 2001 From: zhangbin Date: Wed, 24 Apr 2013 16:53:02 +0800 Subject: [PATCH 05/85] Adjust the implementation of ProtocolSocial & plugin twitter. --- .../plugins/twitter/include/SocialTwitter.h | 17 ++--- .../platform/android/SocialTwitter.cpp | 12 ++-- .../plugins/twitter/proj.android/.classpath | 8 +-- .../org/cocos2dx/plugin/SocialTwitter.java | 66 ++++++++----------- .../src/org/cocos2dx/plugin/TwitterApp.java | 2 - plugin/protocols/include/ProtocolSocial.h | 15 ++--- .../platform/android/ProtocolSocial.cpp | 17 +---- .../HelloAds/Classes/HelloWorldScene.cpp | 8 ++- .../HelloSocial/Classes/HelloWorldScene.cpp | 13 ++-- .../HelloSocial/Classes/MyShareManager.cpp | 17 ++--- .../HelloSocial/Classes/MyShareManager.h | 2 +- .../HelloSocial/proj.android/.classpath | 12 ++-- .../samples/HelloSocial/proj.android/.project | 2 +- plugin/tools/android/build_common.xml | 0 14 files changed, 80 insertions(+), 111 deletions(-) mode change 100644 => 100755 plugin/tools/android/build_common.xml diff --git a/plugin/plugins/twitter/include/SocialTwitter.h b/plugin/plugins/twitter/include/SocialTwitter.h index 7b99bd54c0..5d282f8073 100755 --- a/plugin/plugins/twitter/include/SocialTwitter.h +++ b/plugin/plugins/twitter/include/SocialTwitter.h @@ -19,23 +19,18 @@ public: /** @brief initialize the developer info @param devInfo This parameter is the info of developer, must contains key: - AlipayPartner The partner id of alipay account - AlipaySeller The seller id of alipay account - AlipayRsaPrivate The RSA private key of alipay account - AlipayPublic The public key of alipay account - AlipayNotifyUrl The notify url of developer (must not be empty) - AlipayPluginName The apk file name of Alipay (must not be empty) + TwitterKey The consumerkey of twitter account + TwitterSecret The consumersecret of twitter account @warning Must invoke this interface before other interfaces. And invoked only once. */ - virtual void initDeveloperInfo(TDeveloperInfo devInfo); + virtual void initDeveloperInfo(TSocialDevInfo devInfo); /** @brief pay for product - @param info The info of product, must contains key: - productName The name of product - productPrice The price of product(must can be parse to float) - productDesc The description of product + @param info The info of product, can contains key: + SharedText The text need to share + SharedImagePath The full path of image file need to share (optinal) @warning For different plugin, the parameter should have other keys to pay. Look at the manual of plugins. */ diff --git a/plugin/plugins/twitter/platform/android/SocialTwitter.cpp b/plugin/plugins/twitter/platform/android/SocialTwitter.cpp index 4b26c8f6d8..86a07905a3 100755 --- a/plugin/plugins/twitter/platform/android/SocialTwitter.cpp +++ b/plugin/plugins/twitter/platform/android/SocialTwitter.cpp @@ -20,13 +20,13 @@ bool SocialTwitter::init() /** @brief initialize the developer info @param devInfo This parameter is the info of developer, must contains key: - consumerkey The consumerkey of twitter account - consumersecret The consumersecret of twitter account - More: https://dev.twitter.com + TwitterKey The consumerkey of twitter account + TwitterSecret The consumersecret of twitter account + More: https://dev.twitter.com @warning Must invoke this interface before other interfaces. And invoked only once. */ -void SocialTwitter::initDeveloperInfo(TDeveloperInfo devInfo) +void SocialTwitter::initDeveloperInfo(TSocialDevInfo devInfo) { ProtocolSocial::initDeveloperInfo(devInfo); } @@ -34,8 +34,8 @@ void SocialTwitter::initDeveloperInfo(TDeveloperInfo devInfo) /** @brief pay for product @param info The info of product, must contains key: - text The text to share - imagePath The full path of image to share + SharedText The text need to share + SharedImagePath The full path of image file need to share (optinal) */ void SocialTwitter::share(TShareInfo info) { diff --git a/plugin/plugins/twitter/proj.android/.classpath b/plugin/plugins/twitter/proj.android/.classpath index 4ba22f534d..e877b82024 100755 --- a/plugin/plugins/twitter/proj.android/.classpath +++ b/plugin/plugins/twitter/proj.android/.classpath @@ -4,9 +4,9 @@ - - - - + + + + diff --git a/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/SocialTwitter.java b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/SocialTwitter.java index 8a701a6fd0..4afde2de89 100755 --- a/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/SocialTwitter.java +++ b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/SocialTwitter.java @@ -23,8 +23,8 @@ public class SocialTwitter implements ShareAdapter { private static boolean isInitialized = false; private static Hashtable mShareInfo = null; - public static String KEY_TEXT="text"; - public static String KEY_IMAGE_PATH = "imagePath"; + public static String KEY_TEXT="SharedText"; + public static String KEY_IMAGE_PATH = "SharedImagePath"; protected static void LogE(String msg, Exception e) { Log.e(LOG_TAG, msg, e); @@ -45,11 +45,11 @@ public class SocialTwitter implements ShareAdapter { @Override public void initDeveloperInfo(Hashtable cpInfo) { LogD("initDeveloperInfo invoked " + cpInfo.toString()); - mShareInfo = cpInfo; - mShareInfo = cpInfo; try { - SocialTwitter.CONSUMER_KEY = cpInfo.get("consumerkey"); - SocialTwitter.CONSUMER_SECRET = cpInfo.get("consumersecret"); + SocialTwitter.CONSUMER_KEY = cpInfo.get("TwitterKey"); + SocialTwitter.CONSUMER_SECRET = cpInfo.get("TwitterSecret"); + LogD("key : " + SocialTwitter.CONSUMER_KEY); + LogD("secret : " + SocialTwitter.CONSUMER_SECRET); if(isInitialized){ return; } @@ -73,7 +73,7 @@ public class SocialTwitter implements ShareAdapter { LogD("share invoked " + info.toString()); mShareInfo = info; if (! networkReachable()) { - shareResult(InterfaceSocial.SHARERESULT_FAIL, "网络不可用"); + shareResult(InterfaceSocial.SHARERESULT_FAIL, "Network error!"); return; } // need login @@ -93,21 +93,7 @@ public class SocialTwitter implements ShareAdapter { @Override public void run() { - String text = mShareInfo.get(KEY_TEXT); - String imagePath = mShareInfo.get(KEY_IMAGE_PATH); - try { - if(imagePath != null && imagePath.length() > 0){ - mTwitter.updateStatus(text, imagePath); - }else{ - mTwitter.updateStatus(text); - } - LogD("Posted to Twitter!"); - shareResult(InterfaceSocial.SHARERESULT_SUCCESS, "user lihex"); - } catch (Exception e) { - LogD("Post to Twitter failed!"); - shareResult(InterfaceSocial.SHARERESULT_FAIL, "user lihex"); - e.printStackTrace(); - } + SocialTwitter.sendToTwitter(); } }); } @@ -150,23 +136,25 @@ public class SocialTwitter implements ShareAdapter { @Override public void onComplete(String value) { - String username = mTwitter.getUsername(); - LogD("Connected to Twitter as" + username); - String text = mShareInfo.get(KEY_TEXT); - String imagePath = mShareInfo.get(KEY_IMAGE_PATH); - try { - if(imagePath != null && imagePath.length() > 0){ - mTwitter.updateStatus(text, imagePath); - }else{ - mTwitter.updateStatus(text); - } - LogD("Posted to Twitter!"); - shareResult(InterfaceSocial.SHARERESULT_SUCCESS, username); - } catch (Exception e) { - LogD("Post to Twitter failed!"); - shareResult(InterfaceSocial.SHARERESULT_FAIL, username); - e.printStackTrace(); - } + SocialTwitter.sendToTwitter(); } }; + + private static void sendToTwitter() { + String text = mShareInfo.get(KEY_TEXT); + String imagePath = mShareInfo.get(KEY_IMAGE_PATH); + try { + if(imagePath != null && imagePath.length() > 0){ + mTwitter.updateStatus(text, imagePath); + }else{ + mTwitter.updateStatus(text); + } + LogD("Posted to Twitter!"); + shareResult(InterfaceSocial.SHARERESULT_SUCCESS, "Share succeed!"); + } catch (Exception e) { + LogD("Post to Twitter failed!"); + shareResult(InterfaceSocial.SHARERESULT_FAIL, "Unknown error!"); + e.printStackTrace(); + } + } } diff --git a/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterApp.java b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterApp.java index 61662c6b8b..0c36337846 100755 --- a/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterApp.java +++ b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/TwitterApp.java @@ -20,10 +20,8 @@ import twitter4j.TwitterException; import twitter4j.TwitterFactory; import twitter4j.User; import twitter4j.auth.AccessToken; -import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; -import android.content.DialogInterface; import android.os.Handler; import android.os.Message; import android.util.Log; diff --git a/plugin/protocols/include/ProtocolSocial.h b/plugin/protocols/include/ProtocolSocial.h index 865c9a95c0..b3d6c0d32a 100755 --- a/plugin/protocols/include/ProtocolSocial.h +++ b/plugin/protocols/include/ProtocolSocial.h @@ -7,7 +7,7 @@ namespace cocos2d { namespace plugin { -typedef std::map TDeveloperInfo; +typedef std::map TSocialDevInfo; typedef std::map TShareInfo; typedef enum @@ -21,7 +21,7 @@ typedef enum class ShareResultListener { public: - virtual void shareResult(EShareResult ret, const char* msg, TShareInfo info) = 0; + virtual void shareResult(EShareResult ret, const char* msg) = 0; }; class ProtocolSocial : public PluginProtocol @@ -40,12 +40,13 @@ public: @warning Must invoke this interface before other interfaces. And invoked only once. */ - virtual void initDeveloperInfo(TDeveloperInfo devInfo); + virtual void initDeveloperInfo(TSocialDevInfo devInfo); /** @brief share information - @param info The info of share, must contains key: - text The text of share + @param info The info of share, contains key: + SharedText The text need to share + SharedImagePath The full path of image file need to share (optinal) @warning For different plugin, the parameter should have other keys to share. Look at the manual of plugins. */ @@ -69,7 +70,7 @@ public: */ static void shareResult(EShareResult ret, const char* msg); - virtual const char* getPluginVersion() { return "ProtocolSocial, v0.1.00 , subclass should override this interface!"; }; + virtual const char* getPluginVersion() { return "ProtocolSocial, v0.1.0, subclass should override this interface!"; }; virtual const char* getSDKVersion(); virtual const char* getPluginName() = 0; @@ -79,9 +80,7 @@ public: virtual ~ProtocolSocial(); protected: - static bool m_bSharing; static ShareResultListener* m_pListener; - static TShareInfo m_curInfo; }; }} // namespace cocos2d { namespace plugin { diff --git a/plugin/protocols/platform/android/ProtocolSocial.cpp b/plugin/protocols/platform/android/ProtocolSocial.cpp index 9825bdd722..c5a2f44a68 100755 --- a/plugin/protocols/platform/android/ProtocolSocial.cpp +++ b/plugin/protocols/platform/android/ProtocolSocial.cpp @@ -21,9 +21,7 @@ extern "C" { } } -bool ProtocolSocial::m_bSharing = false; ShareResultListener* ProtocolSocial::m_pListener = NULL; -TShareInfo ProtocolSocial::m_curInfo; ProtocolSocial::ProtocolSocial() { @@ -39,7 +37,7 @@ bool ProtocolSocial::init() return true; } -void ProtocolSocial::initDeveloperInfo(TDeveloperInfo devInfo) +void ProtocolSocial::initDeveloperInfo(TSocialDevInfo devInfo) { if (devInfo.empty()) { @@ -68,12 +66,6 @@ void ProtocolSocial::initDeveloperInfo(TDeveloperInfo devInfo) void ProtocolSocial::share(TShareInfo info) { - if (m_bSharing) - { - LOGD("Now is sharing"); - return; - } - if (info.empty()) { if (NULL != m_pListener) @@ -85,9 +77,6 @@ void ProtocolSocial::share(TShareInfo info) } else { - m_bSharing = true; - m_curInfo = info; - PluginJavaData* pData = PluginUtils::getPluginJavaData(this); PluginJniMethodInfo t; if (PluginJniHelper::getMethodInfo(t @@ -113,16 +102,14 @@ void ProtocolSocial::setResultListener(ShareResultListener* pListener) void ProtocolSocial::shareResult(EShareResult ret, const char* msg) { - m_bSharing = false; if (m_pListener) { - m_pListener->shareResult(ret, msg, m_curInfo); + m_pListener->shareResult(ret, msg); } else { LOGD("Result listener is null!"); } - m_curInfo.clear(); LOGD("Share result is : %d(%s)", (int) ret, msg); } diff --git a/plugin/samples/HelloAds/Classes/HelloWorldScene.cpp b/plugin/samples/HelloAds/Classes/HelloWorldScene.cpp index fefd5d45ab..0c89eb7dd7 100644 --- a/plugin/samples/HelloAds/Classes/HelloWorldScene.cpp +++ b/plugin/samples/HelloAds/Classes/HelloWorldScene.cpp @@ -120,9 +120,15 @@ bool HelloWorld::init() void HelloWorld::testShow(CCObject* pSender) { + int nSize = 0; if (m_pAds == m_pAdmob) { - m_pAds->showBannerAd(m_ePos, AdsAdmob::eSizeBanner); + nSize = AdsAdmob::eSizeBanner; + } + + if (m_pAds) + { + m_pAds->showBannerAd(m_ePos, nSize); } } diff --git a/plugin/samples/HelloSocial/Classes/HelloWorldScene.cpp b/plugin/samples/HelloSocial/Classes/HelloWorldScene.cpp index 75535b2d64..8406e8a611 100755 --- a/plugin/samples/HelloSocial/Classes/HelloWorldScene.cpp +++ b/plugin/samples/HelloSocial/Classes/HelloWorldScene.cpp @@ -7,8 +7,7 @@ using namespace cocos2d; using namespace cocos2d::plugin; enum { - TAG_PAY_BY_ALIPAY = 100, - TAG_PAY_BY_ND91, + TAG_SHARE_BY_TWWITER = 100, }; typedef struct tagEventMenuItem { @@ -17,7 +16,7 @@ typedef struct tagEventMenuItem { }EventMenuItem; static EventMenuItem s_EventMenuItem[] = { - {"twitter.jpeg", TAG_PAY_BY_ALIPAY} + {"twitter.jpeg", TAG_SHARE_BY_TWWITER} }; CCScene* HelloWorld::scene() @@ -110,10 +109,12 @@ void HelloWorld::reloadPluginMenuCallback(CCObject* pSender) void HelloWorld::eventMenuCallback(CCObject* pSender) { + CCMenuItemLabel* pMenuItem = (CCMenuItemLabel*)pSender; TShareInfo pInfo; - pInfo["text"] = "MyFirst tweet!"; - // pInfo["imagePath"] = "Full/path/to/image"; - MyShareManager::sharedManager()->shareByMode(pInfo, MyShareManager::eTwitter); + pInfo["SharedText"] = "MyFirst tweet!"; + // pInfo["SharedImagePath"] = "Full/path/to/image"; + MyShareManager::MyShareMode mode = (MyShareManager::MyShareMode) (pMenuItem->getTag() - TAG_SHARE_BY_TWWITER + 1); + MyShareManager::sharedManager()->shareByMode(pInfo, mode); } void HelloWorld::menuCloseCallback(CCObject* pSender) diff --git a/plugin/samples/HelloSocial/Classes/MyShareManager.cpp b/plugin/samples/HelloSocial/Classes/MyShareManager.cpp index 9bd4add8e2..4c03fc7300 100755 --- a/plugin/samples/HelloSocial/Classes/MyShareManager.cpp +++ b/plugin/samples/HelloSocial/Classes/MyShareManager.cpp @@ -44,11 +44,11 @@ void MyShareManager::loadSocialPlugin() { // init twitter plugin s_pTwitter = dynamic_cast(PluginManager::getInstance()->loadPlugin("SocialTwitter")); - TDeveloperInfo pTwitterInfo; + TSocialDevInfo pTwitterInfo; /* Warning: must set your twiiter dev info here */ - // pTwitterInfo["consumerkey"] = "your consumerkey"; - // pTwitterInfo["consumersecret"] = "your consumersecret"; + // pTwitterInfo["TwitterKey"] = "your consumerkey"; + // pTwitterInfo["TwitterSecret"] = "your consumersecret"; if (pTwitterInfo.empty()) { @@ -93,14 +93,9 @@ void MyShareManager::shareByMode(TShareInfo info, MyShareMode mode) } } -void MyShareResult::shareResult(EShareResult ret, const char* msg, TShareInfo info) +void MyShareResult::shareResult(EShareResult ret, const char* msg) { - char shareInfo[1024] = { 0 }; char shareStatus[1024] = { 0 }; - sprintf(shareStatus, "Share info:%s", (ret == eShareSuccess)? "Successed" : "Failed"); - sprintf(shareInfo, " %s\ntext:%s", - shareStatus, - info.find("text")->second.c_str() - ); - CCMessageBox(shareInfo , msg); + sprintf(shareStatus, "Share %s", (ret == eShareSuccess)? "Successed" : "Failed"); + CCMessageBox(msg, shareStatus); } diff --git a/plugin/samples/HelloSocial/Classes/MyShareManager.h b/plugin/samples/HelloSocial/Classes/MyShareManager.h index a8c65eea67..832baa1d3d 100755 --- a/plugin/samples/HelloSocial/Classes/MyShareManager.h +++ b/plugin/samples/HelloSocial/Classes/MyShareManager.h @@ -6,7 +6,7 @@ class MyShareResult : public cocos2d::plugin::ShareResultListener { public: - virtual void shareResult(cocos2d::plugin::EShareResult ret, const char* msg, cocos2d::plugin::TShareInfo info); + virtual void shareResult(cocos2d::plugin::EShareResult ret, const char* msg); }; class MyShareManager diff --git a/plugin/samples/HelloSocial/proj.android/.classpath b/plugin/samples/HelloSocial/proj.android/.classpath index 2115f0c73a..78f3e75cff 100755 --- a/plugin/samples/HelloSocial/proj.android/.classpath +++ b/plugin/samples/HelloSocial/proj.android/.classpath @@ -4,11 +4,11 @@ - - - - - - + + + + + + diff --git a/plugin/samples/HelloSocial/proj.android/.project b/plugin/samples/HelloSocial/proj.android/.project index 6328a7480a..5227238c68 100755 --- a/plugin/samples/HelloSocial/proj.android/.project +++ b/plugin/samples/HelloSocial/proj.android/.project @@ -37,7 +37,7 @@ PARENT-1-PROJECT_LOC/Classes - publish + plugin-x 2 PARENT-3-PROJECT_LOC/publish diff --git a/plugin/tools/android/build_common.xml b/plugin/tools/android/build_common.xml old mode 100644 new mode 100755 From fb7851b429fc3fb490835217545417d65158bb64 Mon Sep 17 00:00:00 2001 From: minggo Date: Wed, 24 Apr 2013 17:06:59 +0800 Subject: [PATCH 06/85] define checkAnim() before using it --- .../luaScript/EffectsTest/EffectsTest.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/samples/Lua/TestLua/Resources/luaScript/EffectsTest/EffectsTest.lua b/samples/Lua/TestLua/Resources/luaScript/EffectsTest/EffectsTest.lua index 27812d1233..81e342ac7f 100644 --- a/samples/Lua/TestLua/Resources/luaScript/EffectsTest/EffectsTest.lua +++ b/samples/Lua/TestLua/Resources/luaScript/EffectsTest/EffectsTest.lua @@ -12,15 +12,6 @@ local testLayer = nil local titleLabel = nil local entry = nil -local function onEnterOrExit(tag) - local scheduler = CCDirector:sharedDirector():getScheduler() - if tag == "enter" then - entry = scheduler:scheduleScriptFunc(checkAnim, 0, false) - elseif tag == "exit" then - scheduler:unscheduleScriptEntry(entry) - end -end - local function checkAnim(dt) local s2 = testLayer:getChildByTag(kTagBackground) if s2 == nil then @@ -34,6 +25,15 @@ local function checkAnim(dt) end end +local function onEnterOrExit(tag) + local scheduler = CCDirector:sharedDirector():getScheduler() + if tag == "enter" then + entry = scheduler:scheduleScriptFunc(checkAnim, 0, false) + elseif tag == "exit" then + scheduler:unscheduleScriptEntry(entry) + end +end + local function backAction() ActionIdx = ActionIdx - 1 if ActionIdx < 0 then From f30aaed42639a78d9eac34b7344a99705f56daed Mon Sep 17 00:00:00 2001 From: zhangbin Date: Wed, 24 Apr 2013 17:23:35 +0800 Subject: [PATCH 07/85] Modify the permission of plugin twitter. --- .../proj.android/ForAssets/alipay_plugin.apk.REMOVED.git-id | 1 - .../proj.android/src/org/cocos2dx/plugin/SocialTwitter.java | 6 ++++++ plugin/samples/HelloSocial/proj.android/AndroidManifest.xml | 2 -- plugin/samples/HelloSocial/proj.android/build.xml | 2 +- plugin/samples/HelloSocial/proj.android/build_native.sh | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) delete mode 100644 plugin/plugins/twitter/proj.android/ForAssets/alipay_plugin.apk.REMOVED.git-id diff --git a/plugin/plugins/twitter/proj.android/ForAssets/alipay_plugin.apk.REMOVED.git-id b/plugin/plugins/twitter/proj.android/ForAssets/alipay_plugin.apk.REMOVED.git-id deleted file mode 100644 index e7115f0d77..0000000000 --- a/plugin/plugins/twitter/proj.android/ForAssets/alipay_plugin.apk.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -db46ceaf2554c8d9e48cdaec3a4cdf5519bb8896 \ No newline at end of file diff --git a/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/SocialTwitter.java b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/SocialTwitter.java index 4afde2de89..38e3f5f907 100755 --- a/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/SocialTwitter.java +++ b/plugin/plugins/twitter/proj.android/src/org/cocos2dx/plugin/SocialTwitter.java @@ -76,6 +76,12 @@ public class SocialTwitter implements ShareAdapter { shareResult(InterfaceSocial.SHARERESULT_FAIL, "Network error!"); return; } + + if (! isInitialized) { + shareResult(InterfaceSocial.SHARERESULT_FAIL, "Initialize failed!"); + return; + } + // need login if(!mTwitter.hasAccessToken()){ PluginWrapper.runOnMainThread(new Runnable() { diff --git a/plugin/samples/HelloSocial/proj.android/AndroidManifest.xml b/plugin/samples/HelloSocial/proj.android/AndroidManifest.xml index dc93dff99a..68fe456fce 100755 --- a/plugin/samples/HelloSocial/proj.android/AndroidManifest.xml +++ b/plugin/samples/HelloSocial/proj.android/AndroidManifest.xml @@ -24,7 +24,5 @@ - - diff --git a/plugin/samples/HelloSocial/proj.android/build.xml b/plugin/samples/HelloSocial/proj.android/build.xml index 80abad0ab0..b3f20e0181 100755 --- a/plugin/samples/HelloSocial/proj.android/build.xml +++ b/plugin/samples/HelloSocial/proj.android/build.xml @@ -1,5 +1,5 @@ - + - lib/libCocosDenshion.so armle-v7 - TestLua + TestLua + lib/libCocosDenshion.so armle-v7 - TestLua + TestLua + lib/libCocosDenshion.so armle-v7 - TestLua + TestLua + lib/libCocosDenshion.so armle-v7 - TestLua + TestLua + lib/libCocosDenshion.so x86 - TestLua + TestLua + lib/libCocosDenshion.so x86 - TestLua + TestLua + lib/libCocosDenshion.so x86 TestLua + lib/libCocosDenshion.so diff --git a/samples/Lua/TestLua/proj.blackberry/empty/.gitkeep b/samples/Lua/TestLua/proj.blackberry/empty/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripting/lua/proj.blackberry/.cproject b/scripting/lua/proj.blackberry/.cproject index 082f443c08..93f4db3d12 100644 --- a/scripting/lua/proj.blackberry/.cproject +++ b/scripting/lua/proj.blackberry/.cproject @@ -1,550 +1,551 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/template/multi-platform-cpp/proj.blackberry/.cproject b/template/multi-platform-cpp/proj.blackberry/.cproject index ecc554f3c0..a53d13954a 100644 --- a/template/multi-platform-cpp/proj.blackberry/.cproject +++ b/template/multi-platform-cpp/proj.blackberry/.cproject @@ -25,6 +25,7 @@