mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-10-09 01:55:22 +00:00
初始化
This commit is contained in:
319
cocos2d-x/cocos/platform/android/jni/JniHelper.cpp
Normal file
319
cocos2d-x/cocos/platform/android/jni/JniHelper.cpp
Normal file
@@ -0,0 +1,319 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
#include "platform/android/jni/JniHelper.h"
|
||||
#include <android/log.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "base/ccUTF8.h"
|
||||
|
||||
#define LOG_TAG "JniHelper"
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
|
||||
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
|
||||
|
||||
static pthread_key_t g_key;
|
||||
|
||||
jclass _getClassID(const char *className) {
|
||||
if (nullptr == className) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JNIEnv* env = cocos2d::JniHelper::getEnv();
|
||||
|
||||
jstring _jstrClassName = env->NewStringUTF(className);
|
||||
|
||||
jclass _clazz = (jclass) env->CallObjectMethod(cocos2d::JniHelper::classloader,
|
||||
cocos2d::JniHelper::loadclassMethod_methodID,
|
||||
_jstrClassName);
|
||||
|
||||
if (nullptr == _clazz || env->ExceptionCheck()) {
|
||||
LOGE("Classloader failed to find class of %s", className);
|
||||
env->ExceptionClear();
|
||||
_clazz = nullptr;
|
||||
}
|
||||
|
||||
env->DeleteLocalRef(_jstrClassName);
|
||||
|
||||
return _clazz;
|
||||
}
|
||||
|
||||
void _detachCurrentThread(void* a) {
|
||||
cocos2d::JniHelper::getJavaVM()->DetachCurrentThread();
|
||||
}
|
||||
|
||||
namespace cocos2d {
|
||||
|
||||
JavaVM* JniHelper::_psJavaVM = nullptr;
|
||||
jmethodID JniHelper::loadclassMethod_methodID = nullptr;
|
||||
jobject JniHelper::classloader = nullptr;
|
||||
std::function<void()> JniHelper::classloaderCallback = nullptr;
|
||||
|
||||
jobject JniHelper::_activity = nullptr;
|
||||
|
||||
JavaVM* JniHelper::getJavaVM() {
|
||||
pthread_t thisthread = pthread_self();
|
||||
LOGD("JniHelper::getJavaVM(), pthread_self() = %ld", thisthread);
|
||||
return _psJavaVM;
|
||||
}
|
||||
|
||||
void JniHelper::setJavaVM(JavaVM *javaVM) {
|
||||
pthread_t thisthread = pthread_self();
|
||||
LOGD("JniHelper::setJavaVM(%p), pthread_self() = %ld", javaVM, thisthread);
|
||||
_psJavaVM = javaVM;
|
||||
|
||||
pthread_key_create(&g_key, _detachCurrentThread);
|
||||
}
|
||||
|
||||
JNIEnv* JniHelper::cacheEnv(JavaVM* jvm) {
|
||||
JNIEnv* _env = nullptr;
|
||||
// get jni environment
|
||||
jint ret = jvm->GetEnv((void**)&_env, JNI_VERSION_1_4);
|
||||
|
||||
switch (ret) {
|
||||
case JNI_OK :
|
||||
// Success!
|
||||
pthread_setspecific(g_key, _env);
|
||||
return _env;
|
||||
|
||||
case JNI_EDETACHED :
|
||||
// Thread not attached
|
||||
if (jvm->AttachCurrentThread(&_env, nullptr) < 0)
|
||||
{
|
||||
LOGE("Failed to get the environment using AttachCurrentThread()");
|
||||
|
||||
return nullptr;
|
||||
} else {
|
||||
// Success : Attached and obtained JNIEnv!
|
||||
pthread_setspecific(g_key, _env);
|
||||
return _env;
|
||||
}
|
||||
|
||||
case JNI_EVERSION :
|
||||
// Cannot recover from this error
|
||||
LOGE("JNI interface version 1.4 not supported");
|
||||
default :
|
||||
LOGE("Failed to get the environment using GetEnv()");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
JNIEnv* JniHelper::getEnv() {
|
||||
JNIEnv *_env = (JNIEnv *)pthread_getspecific(g_key);
|
||||
if (_env == nullptr)
|
||||
_env = JniHelper::cacheEnv(_psJavaVM);
|
||||
return _env;
|
||||
}
|
||||
|
||||
jobject JniHelper::getActivity() {
|
||||
return _activity;
|
||||
}
|
||||
|
||||
bool JniHelper::setClassLoaderFrom(jobject activityinstance) {
|
||||
JniMethodInfo _getclassloaderMethod;
|
||||
if (!JniHelper::getMethodInfo_DefaultClassLoader(_getclassloaderMethod,
|
||||
"android/content/Context",
|
||||
"getClassLoader",
|
||||
"()Ljava/lang/ClassLoader;")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jobject _c = cocos2d::JniHelper::getEnv()->CallObjectMethod(activityinstance,
|
||||
_getclassloaderMethod.methodID);
|
||||
|
||||
if (nullptr == _c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JniMethodInfo _m;
|
||||
if (!JniHelper::getMethodInfo_DefaultClassLoader(_m,
|
||||
"java/lang/ClassLoader",
|
||||
"loadClass",
|
||||
"(Ljava/lang/String;)Ljava/lang/Class;")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JniHelper::classloader = cocos2d::JniHelper::getEnv()->NewGlobalRef(_c);
|
||||
JniHelper::loadclassMethod_methodID = _m.methodID;
|
||||
JniHelper::_activity = cocos2d::JniHelper::getEnv()->NewGlobalRef(activityinstance);
|
||||
if (JniHelper::classloaderCallback != nullptr){
|
||||
JniHelper::classloaderCallback();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JniHelper::getStaticMethodInfo(JniMethodInfo &methodinfo,
|
||||
const char *className,
|
||||
const char *methodName,
|
||||
const char *paramCode) {
|
||||
if ((nullptr == className) ||
|
||||
(nullptr == methodName) ||
|
||||
(nullptr == paramCode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JNIEnv *env = JniHelper::getEnv();
|
||||
if (!env) {
|
||||
LOGE("Failed to get JNIEnv");
|
||||
return false;
|
||||
}
|
||||
|
||||
jclass classID = _getClassID(className);
|
||||
if (! classID) {
|
||||
LOGE("Failed to find class %s", className);
|
||||
env->ExceptionClear();
|
||||
return false;
|
||||
}
|
||||
|
||||
jmethodID methodID = env->GetStaticMethodID(classID, methodName, paramCode);
|
||||
if (! methodID) {
|
||||
LOGE("Failed to find static method id of %s", methodName);
|
||||
env->ExceptionClear();
|
||||
return false;
|
||||
}
|
||||
|
||||
methodinfo.classID = classID;
|
||||
methodinfo.env = env;
|
||||
methodinfo.methodID = methodID;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JniHelper::getMethodInfo_DefaultClassLoader(JniMethodInfo &methodinfo,
|
||||
const char *className,
|
||||
const char *methodName,
|
||||
const char *paramCode) {
|
||||
if ((nullptr == className) ||
|
||||
(nullptr == methodName) ||
|
||||
(nullptr == paramCode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JNIEnv *env = JniHelper::getEnv();
|
||||
if (!env) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jclass classID = env->FindClass(className);
|
||||
if (! classID) {
|
||||
LOGE("Failed to find class %s", className);
|
||||
env->ExceptionClear();
|
||||
return false;
|
||||
}
|
||||
|
||||
jmethodID methodID = env->GetMethodID(classID, methodName, paramCode);
|
||||
if (! methodID) {
|
||||
LOGE("Failed to find method id of %s", methodName);
|
||||
env->ExceptionClear();
|
||||
return false;
|
||||
}
|
||||
|
||||
methodinfo.classID = classID;
|
||||
methodinfo.env = env;
|
||||
methodinfo.methodID = methodID;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JniHelper::getMethodInfo(JniMethodInfo &methodinfo,
|
||||
const char *className,
|
||||
const char *methodName,
|
||||
const char *paramCode) {
|
||||
if ((nullptr == className) ||
|
||||
(nullptr == methodName) ||
|
||||
(nullptr == paramCode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JNIEnv *env = JniHelper::getEnv();
|
||||
if (!env) {
|
||||
return false;
|
||||
}
|
||||
|
||||
jclass classID = _getClassID(className);
|
||||
if (! classID) {
|
||||
LOGE("Failed to find class %s", className);
|
||||
env->ExceptionClear();
|
||||
return false;
|
||||
}
|
||||
|
||||
jmethodID methodID = env->GetMethodID(classID, methodName, paramCode);
|
||||
if (! methodID) {
|
||||
LOGE("Failed to find method id of %s", methodName);
|
||||
env->ExceptionClear();
|
||||
return false;
|
||||
}
|
||||
|
||||
methodinfo.classID = classID;
|
||||
methodinfo.env = env;
|
||||
methodinfo.methodID = methodID;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string JniHelper::jstring2string(jstring jstr) {
|
||||
if (jstr == nullptr) {
|
||||
return "";
|
||||
}
|
||||
|
||||
JNIEnv *env = JniHelper::getEnv();
|
||||
if (!env) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string strValue = cocos2d::StringUtils::getStringUTFCharsJNI(env, jstr);
|
||||
|
||||
return strValue;
|
||||
}
|
||||
|
||||
jstring JniHelper::convert(JniHelper::LocalRefMapType &localRefs, cocos2d::JniMethodInfo& t, const char* x) {
|
||||
jstring ret = nullptr;
|
||||
if (x)
|
||||
ret = cocos2d::StringUtils::newStringUTFJNI(t.env, x);
|
||||
|
||||
localRefs[t.env].push_back(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
jstring JniHelper::convert(JniHelper::LocalRefMapType &localRefs, cocos2d::JniMethodInfo& t, const std::string& x) {
|
||||
return convert(localRefs, t, x.c_str());
|
||||
}
|
||||
|
||||
void JniHelper::deleteLocalRefs(JNIEnv* env, JniHelper::LocalRefMapType &localRefs) {
|
||||
if (!env) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& ref : localRefs[env]) {
|
||||
env->DeleteLocalRef(ref);
|
||||
}
|
||||
localRefs[env].clear();
|
||||
}
|
||||
|
||||
void JniHelper::reportError(const std::string& className, const std::string& methodName, const std::string& signature) {
|
||||
LOGE("Failed to find static java method. Class name: %s, method name: %s, signature: %s ", className.c_str(), methodName.c_str(), signature.c_str());
|
||||
}
|
||||
|
||||
} //namespace cocos2d
|
399
cocos2d-x/cocos/platform/android/jni/JniHelper.h
Normal file
399
cocos2d-x/cocos/platform/android/jni/JniHelper.h
Normal file
@@ -0,0 +1,399 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2010-2012 cocos2d-x.org
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
#ifndef __ANDROID_JNI_HELPER_H__
|
||||
#define __ANDROID_JNI_HELPER_H__
|
||||
|
||||
#include <jni.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
#include <functional>
|
||||
#include "base/ccMacros.h"
|
||||
#include "math/Vec3.h"
|
||||
|
||||
//The macro must be used this way to find the native method. The principle is not well understood.
|
||||
#define JNI_METHOD2(CLASS2,FUNC2) Java_##CLASS2##_##FUNC2
|
||||
#define JNI_METHOD1(CLASS1,FUNC1) JNI_METHOD2(CLASS1,FUNC1)
|
||||
|
||||
NS_CC_BEGIN
|
||||
|
||||
typedef struct JniMethodInfo_
|
||||
{
|
||||
JNIEnv * env;
|
||||
jclass classID;
|
||||
jmethodID methodID;
|
||||
} JniMethodInfo;
|
||||
|
||||
|
||||
class CC_DLL JniHelper
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::unordered_map<JNIEnv *, std::vector<jobject >> LocalRefMapType;
|
||||
|
||||
static void setJavaVM(JavaVM *javaVM);
|
||||
static JavaVM* getJavaVM();
|
||||
static JNIEnv* getEnv();
|
||||
static jobject getActivity();
|
||||
|
||||
static bool setClassLoaderFrom(jobject activityInstance);
|
||||
static bool getStaticMethodInfo(JniMethodInfo &methodinfo,
|
||||
const char *className,
|
||||
const char *methodName,
|
||||
const char *paramCode);
|
||||
static bool getMethodInfo(JniMethodInfo &methodinfo,
|
||||
const char *className,
|
||||
const char *methodName,
|
||||
const char *paramCode);
|
||||
|
||||
static std::string jstring2string(jstring str);
|
||||
|
||||
static jmethodID loadclassMethod_methodID;
|
||||
static jobject classloader;
|
||||
static std::function<void()> classloaderCallback;
|
||||
|
||||
template <typename... Ts>
|
||||
static jobject newObject(const std::string& className, Ts... xs)
|
||||
{
|
||||
jobject ret = nullptr;
|
||||
static const char* methodName = "<init>";
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")V";
|
||||
if (cocos2d::JniHelper::getMethodInfo(t, className.c_str(), methodName, signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
ret = t.env->NewObject(t.classID, t.methodID, convert(t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static void callObjectVoidMethod(jobject object,
|
||||
const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")V";
|
||||
if (cocos2d::JniHelper::getMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
t.env->CallVoidMethod(object, t.methodID, convert(localRefs, t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static float callObjectFloatMethod(jobject object,
|
||||
const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
float ret = 0.0f;
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")F";
|
||||
if (cocos2d::JniHelper::getMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
ret = t.env->CallFloatMethod(object, t.methodID, convert(localRefs, t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static jbyteArray callObjectByteArrayMethod(jobject object,
|
||||
const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
jbyteArray ret = nullptr;
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")[B";
|
||||
if (cocos2d::JniHelper::getMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
ret = (jbyteArray)t.env->CallObjectMethod(object, t.methodID, convert(localRefs, t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static void callStaticVoidMethod(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")V";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
t.env->CallStaticVoidMethod(t.classID, t.methodID, convert(localRefs, t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static bool callStaticBooleanMethod(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
jboolean jret = JNI_FALSE;
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")Z";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
jret = t.env->CallStaticBooleanMethod(t.classID, t.methodID, convert(localRefs, t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return (jret == JNI_TRUE);
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static int callStaticIntMethod(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
jint ret = 0;
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")I";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
ret = t.env->CallStaticIntMethod(t.classID, t.methodID, convert(t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static float callStaticFloatMethod(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
jfloat ret = 0.0;
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")F";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
ret = t.env->CallStaticFloatMethod(t.classID, t.methodID, convert(localRefs, t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static float* callStaticFloatArrayMethod(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
static float ret[32];
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")[F";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
jfloatArray array = (jfloatArray) t.env->CallStaticObjectMethod(t.classID, t.methodID, convert(localRefs, t, xs)...);
|
||||
jsize len = t.env->GetArrayLength(array);
|
||||
if (len <= 32) {
|
||||
jfloat* elems = t.env->GetFloatArrayElements(array, 0);
|
||||
if (elems) {
|
||||
memcpy(ret, elems, sizeof(float) * len);
|
||||
t.env->ReleaseFloatArrayElements(array, elems, 0);
|
||||
};
|
||||
}
|
||||
t.env->DeleteLocalRef(array);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
return &ret[0];
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static Vec3 callStaticVec3Method(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
Vec3 ret;
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")[F";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
jfloatArray array = (jfloatArray) t.env->CallStaticObjectMethod(t.classID, t.methodID, convert(localRefs, t, xs)...);
|
||||
jsize len = t.env->GetArrayLength(array);
|
||||
if (len == 3) {
|
||||
jfloat* elems = t.env->GetFloatArrayElements(array, 0);
|
||||
ret.x = elems[0];
|
||||
ret.y = elems[1];
|
||||
ret.z = elems[2];
|
||||
t.env->ReleaseFloatArrayElements(array, elems, 0);
|
||||
}
|
||||
t.env->DeleteLocalRef(array);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static double callStaticDoubleMethod(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
jdouble ret = 0.0;
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")D";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
ret = t.env->CallStaticDoubleMethod(t.classID, t.methodID, convert(localRefs, t, xs)...);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename... Ts>
|
||||
static std::string callStaticStringMethod(const std::string& className,
|
||||
const std::string& methodName,
|
||||
Ts... xs) {
|
||||
std::string ret;
|
||||
|
||||
cocos2d::JniMethodInfo t;
|
||||
std::string signature = "(" + std::string(getJNISignature(xs...)) + ")Ljava/lang/String;";
|
||||
if (cocos2d::JniHelper::getStaticMethodInfo(t, className.c_str(), methodName.c_str(), signature.c_str())) {
|
||||
LocalRefMapType localRefs;
|
||||
jstring jret = (jstring)t.env->CallStaticObjectMethod(t.classID, t.methodID, convert(localRefs, t, xs)...);
|
||||
ret = cocos2d::JniHelper::jstring2string(jret);
|
||||
t.env->DeleteLocalRef(t.classID);
|
||||
t.env->DeleteLocalRef(jret);
|
||||
deleteLocalRefs(t.env, localRefs);
|
||||
} else {
|
||||
reportError(className, methodName, signature);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
private:
|
||||
static JNIEnv* cacheEnv(JavaVM* jvm);
|
||||
|
||||
static bool getMethodInfo_DefaultClassLoader(JniMethodInfo &methodinfo,
|
||||
const char *className,
|
||||
const char *methodName,
|
||||
const char *paramCode);
|
||||
|
||||
static JavaVM* _psJavaVM;
|
||||
|
||||
static jobject _activity;
|
||||
|
||||
static jstring convert(LocalRefMapType &localRefs, cocos2d::JniMethodInfo& t, const char* x);
|
||||
|
||||
static jstring convert(LocalRefMapType &localRefs, cocos2d::JniMethodInfo& t, const std::string& x);
|
||||
|
||||
template <typename T>
|
||||
static T convert(LocalRefMapType &localRefs, cocos2d::JniMethodInfo&, T x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
static void deleteLocalRefs(JNIEnv* env, LocalRefMapType &localRefs);
|
||||
|
||||
static std::string getJNISignature() {
|
||||
return "";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(bool) {
|
||||
return "Z";
|
||||
}
|
||||
|
||||
// jchar is unsigned 16 bits, we do char => jchar conversion on purpose
|
||||
static std::string getJNISignature(char) {
|
||||
return "C";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(jshort) {
|
||||
return "S";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(jint) {
|
||||
return "I";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(jlong) {
|
||||
return "J";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(jfloat) {
|
||||
return "F";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(jdouble) {
|
||||
return "D";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(jbyteArray) {
|
||||
return "[B";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(const char*) {
|
||||
return "Ljava/lang/String;";
|
||||
}
|
||||
|
||||
static std::string getJNISignature(const std::string&) {
|
||||
return "Ljava/lang/String;";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static std::string getJNISignature(T x) {
|
||||
// This template should never be instantiated
|
||||
static_assert(sizeof(x) == 0, "Unsupported argument type");
|
||||
return "";
|
||||
}
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
static std::string getJNISignature(T x, Ts... xs) {
|
||||
return getJNISignature(x) + getJNISignature(xs...);
|
||||
}
|
||||
|
||||
static void reportError(const std::string& className, const std::string& methodName, const std::string& signature);
|
||||
};
|
||||
|
||||
NS_CC_END
|
||||
|
||||
#endif // __ANDROID_JNI_HELPER_H__
|
680
cocos2d-x/cocos/platform/android/jni/JniImp.cpp
Normal file
680
cocos2d-x/cocos/platform/android/jni/JniImp.cpp
Normal file
@@ -0,0 +1,680 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
#include "JniImp.h"
|
||||
#include <unordered_map>
|
||||
#include <android/log.h>
|
||||
#include <android/asset_manager_jni.h>
|
||||
#include <jni.h>
|
||||
#include <mutex>
|
||||
#include "JniHelper.h"
|
||||
#include "platform/CCApplication.h"
|
||||
#include "scripting/js-bindings/jswrapper/SeApi.h"
|
||||
#include "scripting/js-bindings/event/EventDispatcher.h"
|
||||
#include "platform/android/CCFileUtils-android.h"
|
||||
#include "base/CCScheduler.h"
|
||||
#include "base/CCAutoreleasePool.h"
|
||||
#include "base/CCGLUtils.h"
|
||||
|
||||
#define JNI_IMP_LOG_TAG "JniImp"
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,JNI_IMP_LOG_TAG,__VA_ARGS__)
|
||||
|
||||
#ifndef ORG_RENDER_CLASS_NAME
|
||||
#define ORG_RENDER_CLASS_NAME org_cocos2dx_lib_Cocos2dxRenderer
|
||||
#endif
|
||||
#define JNI_RENDER(FUNC) JNI_METHOD1(ORG_RENDER_CLASS_NAME,FUNC)
|
||||
|
||||
#ifndef ORG_ACTIVITY_CLASS_NAME
|
||||
#define ORG_ACTIVITY_CLASS_NAME org_cocos2dx_lib_Cocos2dxActivity
|
||||
#endif
|
||||
#define JNI_ACTIVITY(FUNC) JNI_METHOD1(ORG_ACTIVITY_CLASS_NAME,FUNC)
|
||||
|
||||
#ifndef ORG_ACCELEROMETER_CLASS_NAME
|
||||
#define ORG_ACCELEROMETER_CLASS_NAME org_cocos2dx_lib_Cocos2dxAccelerometer
|
||||
#endif
|
||||
#define JNI_ACCELEROMETER(FUNC) JNI_METHOD1(ORG_ACCELEROMETER_CLASS_NAME,FUNC)
|
||||
|
||||
#ifndef ORG_HELPER_CLASS_NAME
|
||||
#define ORG_HELPER_CLASS_NAME org_cocos2dx_lib_Cocos2dxHelper
|
||||
#endif
|
||||
#define JNI_HELPER(FUNC) JNI_METHOD1(ORG_HELPER_CLASS_NAME,FUNC)
|
||||
|
||||
#ifndef ORG_AUDIOFOCUS_CLASS_NAME
|
||||
#define ORG_AUDIOFOCUS_CLASS_NAME org_cocos2dx_lib_Cocos2dxAudioFocusManager
|
||||
#endif
|
||||
#define JNI_AUDIO(FUNC) JNI_METHOD1(ORG_AUDIOFOCUS_CLASS_NAME,FUNC)
|
||||
|
||||
#ifndef JCLS_HELPER
|
||||
#define JCLS_HELPER "org/cocos2dx/lib/Cocos2dxHelper"
|
||||
#endif
|
||||
|
||||
#ifndef JCLS_RENDERER
|
||||
#define JCLS_RENDERER "org/cocos2dx/lib/Cocos2dxRenderer"
|
||||
#endif
|
||||
|
||||
|
||||
#define KEYCODE_BACK 0x04
|
||||
#define KEYCODE_MENU 0x52
|
||||
#define KEYCODE_DPAD_UP 0x13
|
||||
#define KEYCODE_DPAD_DOWN 0x14
|
||||
#define KEYCODE_DPAD_LEFT 0x15
|
||||
#define KEYCODE_DPAD_RIGHT 0x16
|
||||
#define KEYCODE_ENTER 0x42
|
||||
#define KEYCODE_DPAD_CENTER 0x17
|
||||
|
||||
using namespace cocos2d;
|
||||
|
||||
extern uint32_t __jsbInvocationCount;
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
bool __isOpenDebugView = false;
|
||||
bool __isGLOptModeEnabled = true;
|
||||
std::string g_apkPath;
|
||||
EditTextCallback s_editTextCallback = nullptr;
|
||||
void* s_ctx = nullptr;
|
||||
int g_deviceSampleRate = 44100;
|
||||
int g_deviceAudioBufferSizeInFrames = 192;
|
||||
int g_width = 0;
|
||||
int g_height = 0;
|
||||
bool g_isStarted = false;
|
||||
bool g_isGameFinished = false;
|
||||
int g_SDKInt = 0;
|
||||
|
||||
cocos2d::Application* g_app = nullptr;
|
||||
|
||||
bool setCanvasCallback(se::Object* global)
|
||||
{
|
||||
se::AutoHandleScope scope;
|
||||
se::ScriptEngine* se = se::ScriptEngine::getInstance();
|
||||
char commandBuf[200] = {0};
|
||||
uint8_t devicePixelRatio = Application::getInstance()->getDevicePixelRatio();
|
||||
sprintf(commandBuf, "window.innerWidth = %d; window.innerHeight = %d;",
|
||||
g_width / devicePixelRatio,
|
||||
g_height / devicePixelRatio);
|
||||
se->evalString(commandBuf);
|
||||
glViewport(0, 0, g_width / devicePixelRatio, g_height / devicePixelRatio);
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void cocos_jni_env_init (JNIEnv* env);
|
||||
|
||||
Application* cocos_android_app_init(JNIEnv* env, int width, int height);
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void getSDKInt(JNIEnv* env)
|
||||
{
|
||||
if (env && g_SDKInt == 0)
|
||||
{
|
||||
// VERSION is a nested class within android.os.Build (hence "$" rather than "/")
|
||||
jclass versionClass = env->FindClass("android/os/Build$VERSION");
|
||||
if (NULL == versionClass)
|
||||
return;
|
||||
|
||||
jfieldID sdkIntFieldID = env->GetStaticFieldID(versionClass, "SDK_INT", "I");
|
||||
if (NULL == sdkIntFieldID)
|
||||
return;
|
||||
|
||||
g_SDKInt = env->GetStaticIntField(versionClass, sdkIntFieldID);
|
||||
}
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved)
|
||||
{
|
||||
JniHelper::setJavaVM(vm);
|
||||
cocos_jni_env_init(JniHelper::getEnv());
|
||||
getSDKInt(JniHelper::getEnv());
|
||||
|
||||
return JNI_VERSION_1_4;
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* Cocos2dxActivity native functions implementation.
|
||||
*****************************************************/
|
||||
|
||||
JNIEXPORT jintArray JNICALL JNI_ACTIVITY(getGLContextAttrs)(JNIEnv* env, jobject thiz)
|
||||
{
|
||||
//REFINE
|
||||
int tmp[7] = {8, 8, 8,
|
||||
8, 0, 0, 0};
|
||||
jintArray glContextAttrsJava = env->NewIntArray(7);
|
||||
env->SetIntArrayRegion(glContextAttrsJava, 0, 7, tmp);
|
||||
|
||||
return glContextAttrsJava;
|
||||
}
|
||||
|
||||
/*****************************************************
|
||||
* Cocos2dxRenderer native functions implementation.
|
||||
*****************************************************/
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeInit)(JNIEnv* env, jobject thiz, jint w, jint h, jstring jDefaultResourcePath)
|
||||
{
|
||||
g_width = w;
|
||||
g_height = h;
|
||||
|
||||
g_app = cocos_android_app_init(env, w, h);
|
||||
|
||||
g_isGameFinished = false;
|
||||
ccInvalidateStateCache();
|
||||
std::string defaultResourcePath = JniHelper::jstring2string(jDefaultResourcePath);
|
||||
LOGD("nativeInit: %d, %d, %s", w, h, defaultResourcePath.c_str());
|
||||
|
||||
|
||||
if (!defaultResourcePath.empty())
|
||||
FileUtils::getInstance()->setDefaultResourceRootPath(defaultResourcePath);
|
||||
|
||||
se::ScriptEngine* se = se::ScriptEngine::getInstance();
|
||||
se->addRegisterCallback(setCanvasCallback);
|
||||
|
||||
EventDispatcher::init();
|
||||
|
||||
g_app->start();
|
||||
g_isStarted = true;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeRender)(JNIEnv* env)
|
||||
{
|
||||
if (g_isGameFinished)
|
||||
{
|
||||
// with Application destructor called, native resource will be released
|
||||
delete g_app;
|
||||
g_app = nullptr;
|
||||
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "endApplication");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!g_isStarted)
|
||||
{
|
||||
auto scheduler = Application::getInstance()->getScheduler();
|
||||
scheduler->removeAllFunctionsToBePerformedInCocosThread();
|
||||
scheduler->unscheduleAll();
|
||||
|
||||
se::ScriptEngine::getInstance()->cleanup();
|
||||
cocos2d::PoolManager::getInstance()->getCurrentPool()->clear();
|
||||
|
||||
//REFINE: Wait HttpClient, WebSocket, Audio thread to exit
|
||||
|
||||
ccInvalidateStateCache();
|
||||
|
||||
se::ScriptEngine* se = se::ScriptEngine::getInstance();
|
||||
se->addRegisterCallback(setCanvasCallback);
|
||||
|
||||
EventDispatcher::init();
|
||||
|
||||
if(!g_app->applicationDidFinishLaunching())
|
||||
{
|
||||
g_isGameFinished = true;
|
||||
return;
|
||||
}
|
||||
|
||||
g_isStarted = true;
|
||||
}
|
||||
|
||||
static std::chrono::steady_clock::time_point prevTime;
|
||||
static std::chrono::steady_clock::time_point now;
|
||||
static float dt = 0.f;
|
||||
static float dtSum = 0.f;
|
||||
static uint32_t jsbInvocationTotalCount = 0;
|
||||
static uint32_t jsbInvocationTotalFrames = 0;
|
||||
bool downsampleEnabled = g_app->isDownsampleEnabled();
|
||||
|
||||
if (downsampleEnabled)
|
||||
g_app->getRenderTexture()->prepare();
|
||||
|
||||
g_app->getScheduler()->update(dt);
|
||||
EventDispatcher::dispatchTickEvent(dt);
|
||||
|
||||
if (downsampleEnabled)
|
||||
g_app->getRenderTexture()->draw();
|
||||
|
||||
PoolManager::getInstance()->getCurrentPool()->clear();
|
||||
|
||||
now = std::chrono::steady_clock::now();
|
||||
dt = std::chrono::duration_cast<std::chrono::microseconds>(now - prevTime).count() / 1000000.f;
|
||||
|
||||
prevTime = std::chrono::steady_clock::now();
|
||||
|
||||
if (__isOpenDebugView)
|
||||
{
|
||||
dtSum += dt;
|
||||
++jsbInvocationTotalFrames;
|
||||
jsbInvocationTotalCount += __jsbInvocationCount;
|
||||
|
||||
if (dtSum > 1.0f)
|
||||
{
|
||||
dtSum = 0.0f;
|
||||
setJSBInvocationCountJNI(jsbInvocationTotalCount / jsbInvocationTotalFrames);
|
||||
jsbInvocationTotalCount = 0;
|
||||
jsbInvocationTotalFrames = 0;
|
||||
}
|
||||
}
|
||||
__jsbInvocationCount = 0;
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeOnPause)()
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
if (g_app)
|
||||
g_app->onPause();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeOnResume)()
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
if (g_app)
|
||||
g_app->onResume();
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeInsertText)(JNIEnv* env, jobject thiz, jstring text)
|
||||
{
|
||||
//REFINE
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeDeleteBackward)(JNIEnv* env, jobject thiz)
|
||||
{
|
||||
//REFINE
|
||||
}
|
||||
|
||||
JNIEXPORT jstring JNICALL JNI_RENDER(nativeGetContentText)()
|
||||
{
|
||||
//REFINE
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeOnSurfaceChanged)(JNIEnv* env, jobject thiz, jint w, jint h)
|
||||
{
|
||||
//REFINE
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Cocos2dxAccelerometer native functions implementation.
|
||||
***********************************************************/
|
||||
|
||||
JNIEXPORT void JNICALL JNI_ACCELEROMETER(onSensorChanged)(JNIEnv* env, jobject thiz, jfloat x, jfloat y, jfloat z, jlong timeStamp)
|
||||
{
|
||||
//REFINE
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Touches native functions implementation.
|
||||
***********************************************************/
|
||||
|
||||
static void dispatchTouchEventWithOnePoint(JNIEnv* env, cocos2d::TouchEvent::Type type, jint id, jfloat x, jfloat y)
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
cocos2d::TouchEvent touchEvent;
|
||||
touchEvent.type = type;
|
||||
|
||||
uint8_t devicePixelRatio = Application::getInstance()->getDevicePixelRatio();
|
||||
cocos2d::TouchInfo touchInfo;
|
||||
touchInfo.index = id;
|
||||
touchInfo.x = x / devicePixelRatio;
|
||||
touchInfo.y = y / devicePixelRatio;
|
||||
touchEvent.touches.push_back(touchInfo);
|
||||
|
||||
cocos2d::EventDispatcher::dispatchTouchEvent(touchEvent);
|
||||
}
|
||||
|
||||
static void dispatchTouchEventWithPoints(JNIEnv* env, cocos2d::TouchEvent::Type type, jintArray ids, jfloatArray xs, jfloatArray ys)
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
cocos2d::TouchEvent touchEvent;
|
||||
touchEvent.type = type;
|
||||
|
||||
int size = env->GetArrayLength(ids);
|
||||
jint id[size];
|
||||
jfloat x[size];
|
||||
jfloat y[size];
|
||||
|
||||
env->GetIntArrayRegion(ids, 0, size, id);
|
||||
env->GetFloatArrayRegion(xs, 0, size, x);
|
||||
env->GetFloatArrayRegion(ys, 0, size, y);
|
||||
|
||||
uint8_t devicePixelRatio = Application::getInstance()->getDevicePixelRatio();
|
||||
for(int i = 0; i < size; i++)
|
||||
{
|
||||
cocos2d::TouchInfo touchInfo;
|
||||
touchInfo.index = id[i];
|
||||
touchInfo.x = x[i] / devicePixelRatio;
|
||||
touchInfo.y = y[i] / devicePixelRatio;
|
||||
touchEvent.touches.push_back(touchInfo);
|
||||
}
|
||||
|
||||
cocos2d::EventDispatcher::dispatchTouchEvent(touchEvent);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeTouchesBegin)(JNIEnv * env, jobject thiz, jint id, jfloat x, jfloat y)
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
dispatchTouchEventWithOnePoint(env, cocos2d::TouchEvent::Type::BEGAN, id, x, y);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeTouchesEnd)(JNIEnv * env, jobject thiz, jint id, jfloat x, jfloat y)
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
dispatchTouchEventWithOnePoint(env, cocos2d::TouchEvent::Type::ENDED, id, x, y);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeTouchesMove)(JNIEnv * env, jobject thiz, jintArray ids, jfloatArray xs, jfloatArray ys)
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
dispatchTouchEventWithPoints(env, cocos2d::TouchEvent::Type::MOVED, ids, xs, ys);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_RENDER(nativeTouchesCancel)(JNIEnv * env, jobject thiz, jintArray ids, jfloatArray xs, jfloatArray ys)
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return;
|
||||
}
|
||||
dispatchTouchEventWithPoints(env, cocos2d::TouchEvent::Type::CANCELLED, ids, xs, ys);
|
||||
}
|
||||
|
||||
JNIEXPORT jboolean JNICALL JNI_RENDER(nativeKeyEvent)(JNIEnv * env, jobject thiz, jint keyCode, jboolean isPressed)
|
||||
{
|
||||
if (g_isGameFinished) {
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
int keyInWeb = -1;
|
||||
// key values in web, refer to http://docs.cocos.com/creator/api/en/enums/KEY.html
|
||||
switch(keyCode)
|
||||
{
|
||||
case KEYCODE_BACK:
|
||||
keyInWeb = 6;
|
||||
break;
|
||||
case KEYCODE_ENTER:
|
||||
keyInWeb = 13;
|
||||
break;
|
||||
case KEYCODE_MENU:
|
||||
keyInWeb = 18;
|
||||
break;
|
||||
case KEYCODE_DPAD_UP:
|
||||
keyInWeb = 1003;
|
||||
break;
|
||||
case KEYCODE_DPAD_DOWN:
|
||||
keyInWeb = 1004;
|
||||
break;
|
||||
case KEYCODE_DPAD_LEFT:
|
||||
keyInWeb = 1000;
|
||||
break;
|
||||
case KEYCODE_DPAD_RIGHT:
|
||||
keyInWeb = 1001;
|
||||
break;
|
||||
case KEYCODE_DPAD_CENTER:
|
||||
keyInWeb = 1005;
|
||||
break;
|
||||
default:
|
||||
keyInWeb = 0; // If the key can't be identified, this value is 0
|
||||
}
|
||||
KeyboardEvent event;
|
||||
event.key = keyInWeb;
|
||||
event.action = isPressed ? KeyboardEvent::Action::PRESS : KeyboardEvent::Action::RELEASE;
|
||||
EventDispatcher::dispatchKeyboardEvent(event);
|
||||
|
||||
return JNI_TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Cocos2dxHelper native functions implementation.
|
||||
***********************************************************/
|
||||
|
||||
JNIEXPORT void JNICALL JNI_HELPER(nativeSetApkPath)(JNIEnv* env, jobject thiz, jstring apkPath)
|
||||
{
|
||||
g_apkPath = JniHelper::jstring2string(apkPath);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_HELPER(nativeSetContext)(JNIEnv* env, jobject thiz, jobject context, jobject assetManager)
|
||||
{
|
||||
JniHelper::setClassLoaderFrom(context);
|
||||
FileUtilsAndroid::setassetmanager(AAssetManager_fromJava(env, assetManager));
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_HELPER(nativeSetAudioDeviceInfo)(JNIEnv* env, jobject thiz, jboolean isSupportLowLatency, jint deviceSampleRate, jint deviceAudioBufferSizeInFrames)
|
||||
{
|
||||
g_deviceSampleRate = deviceSampleRate;
|
||||
g_deviceAudioBufferSizeInFrames = deviceAudioBufferSizeInFrames;
|
||||
LOGD("nativeSetAudioDeviceInfo: sampleRate: %d, bufferSizeInFrames: %d", g_deviceSampleRate, g_deviceAudioBufferSizeInFrames);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL JNI_HELPER(nativeSetEditTextDialogResult)(JNIEnv* env, jobject obj, jbyteArray text)
|
||||
{
|
||||
jsize size = env->GetArrayLength(text);
|
||||
|
||||
if (size > 0)
|
||||
{
|
||||
jbyte * data = (jbyte*)env->GetByteArrayElements(text, 0);
|
||||
char* buffer = (char*)malloc(size+1);
|
||||
if (buffer != nullptr)
|
||||
{
|
||||
memcpy(buffer, data, size);
|
||||
buffer[size] = '\0';
|
||||
// pass data to edittext's delegate
|
||||
if (s_editTextCallback)
|
||||
s_editTextCallback(buffer, s_ctx);
|
||||
free(buffer);
|
||||
}
|
||||
env->ReleaseByteArrayElements(text, data, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s_editTextCallback)
|
||||
s_editTextCallback("", s_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Cocos2dxAudioFocusManager native functions implementation.
|
||||
***********************************************************/
|
||||
|
||||
JNIEXPORT void JNICALL JNI_AUDIO(nativeOnAudioFocusChange)(JNIEnv* env, jobject thiz, jint focusChange)
|
||||
{
|
||||
// cocos_audioengine_focus_change(focusChange);
|
||||
}
|
||||
} // end of extern "C"
|
||||
|
||||
void restartJSVM()
|
||||
{
|
||||
g_isStarted = false;
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
* Functions invoke from cpp to Java.
|
||||
***********************************************************/
|
||||
|
||||
std::string getApkPathJNI()
|
||||
{
|
||||
return g_apkPath;
|
||||
}
|
||||
|
||||
std::string getPackageNameJNI()
|
||||
{
|
||||
return JniHelper::callStaticStringMethod(JCLS_HELPER, "getPackageName");
|
||||
}
|
||||
|
||||
int getObbAssetFileDescriptorJNI(const std::string& path, long* startOffset, long* size)
|
||||
{
|
||||
JniMethodInfo methodInfo;
|
||||
int fd = 0;
|
||||
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo, JCLS_HELPER, "getObbAssetFileDescriptor", "(Ljava/lang/String;)[J"))
|
||||
{
|
||||
jstring stringArg = methodInfo.env->NewStringUTF(path.c_str());
|
||||
jlongArray newArray = (jlongArray)methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID, stringArg);
|
||||
jsize theArrayLen = methodInfo.env->GetArrayLength(newArray);
|
||||
|
||||
if (3 == theArrayLen)
|
||||
{
|
||||
jboolean copy = JNI_FALSE;
|
||||
jlong *array = methodInfo.env->GetLongArrayElements(newArray, ©);
|
||||
fd = static_cast<int>(array[0]);
|
||||
*startOffset = array[1];
|
||||
*size = array[2];
|
||||
methodInfo.env->ReleaseLongArrayElements(newArray, array, 0);
|
||||
}
|
||||
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
methodInfo.env->DeleteLocalRef(stringArg);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int getDeviceSampleRateJNI()
|
||||
{
|
||||
return g_deviceSampleRate;
|
||||
}
|
||||
|
||||
int getDeviceAudioBufferSizeInFramesJNI()
|
||||
{
|
||||
return g_deviceAudioBufferSizeInFrames;
|
||||
}
|
||||
|
||||
void convertEncodingJNI(const std::string& src, int byteSize, const std::string& fromCharset, std::string& dst, const std::string& newCharset)
|
||||
{
|
||||
JniMethodInfo methodInfo;
|
||||
|
||||
if (JniHelper::getStaticMethodInfo(methodInfo, JCLS_HELPER, "conversionEncoding", "([BLjava/lang/String;Ljava/lang/String;)[B"))
|
||||
{
|
||||
jbyteArray strArray = methodInfo.env->NewByteArray(byteSize);
|
||||
methodInfo.env->SetByteArrayRegion(strArray, 0, byteSize, reinterpret_cast<const jbyte*>(src.c_str()));
|
||||
|
||||
jstring stringArg1 = methodInfo.env->NewStringUTF(fromCharset.c_str());
|
||||
jstring stringArg2 = methodInfo.env->NewStringUTF(newCharset.c_str());
|
||||
|
||||
jbyteArray newArray = (jbyteArray)methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID, strArray, stringArg1, stringArg2);
|
||||
jsize theArrayLen = methodInfo.env->GetArrayLength(newArray);
|
||||
methodInfo.env->GetByteArrayRegion(newArray, 0, theArrayLen, (jbyte*)dst.c_str());
|
||||
|
||||
methodInfo.env->DeleteLocalRef(strArray);
|
||||
methodInfo.env->DeleteLocalRef(stringArg1);
|
||||
methodInfo.env->DeleteLocalRef(stringArg2);
|
||||
methodInfo.env->DeleteLocalRef(newArray);
|
||||
methodInfo.env->DeleteLocalRef(methodInfo.classID);
|
||||
}
|
||||
}
|
||||
|
||||
std::string getCurrentLanguageJNI()
|
||||
{
|
||||
return JniHelper::callStaticStringMethod(JCLS_HELPER, "getCurrentLanguage");
|
||||
}
|
||||
|
||||
std::string getCurrentLanguageCodeJNI()
|
||||
{
|
||||
return JniHelper::callStaticStringMethod(JCLS_HELPER, "getCurrentLanguageCode");
|
||||
}
|
||||
|
||||
std::string getSystemVersionJNI()
|
||||
{
|
||||
return JniHelper::callStaticStringMethod(JCLS_HELPER, "getSystemVersion");
|
||||
}
|
||||
|
||||
bool openURLJNI(const std::string& url)
|
||||
{
|
||||
return JniHelper::callStaticBooleanMethod(JCLS_HELPER, "openURL", url);
|
||||
}
|
||||
|
||||
void copyTextToClipboardJNI(const std::string& text)
|
||||
{
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "copyTextToClipboard", text);
|
||||
}
|
||||
|
||||
void setPreferredFramesPerSecondJNI(int fps)
|
||||
{
|
||||
JniHelper::callStaticVoidMethod(JCLS_RENDERER, "setPreferredFramesPerSecond", fps);
|
||||
}
|
||||
|
||||
void setGameInfoDebugViewTextJNI(int index, const std::string& text)
|
||||
{
|
||||
if (!__isOpenDebugView)
|
||||
return;
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "setGameInfoDebugViewText", index, text);
|
||||
}
|
||||
|
||||
void setJSBInvocationCountJNI(int count)
|
||||
{
|
||||
if (!__isOpenDebugView)
|
||||
return;
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "setJSBInvocationCount", count);
|
||||
}
|
||||
|
||||
void openDebugViewJNI()
|
||||
{
|
||||
if (!__isOpenDebugView)
|
||||
{
|
||||
LOGD("openDebugViewJNI ...");
|
||||
__isOpenDebugView = true;
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "openDebugView");
|
||||
if (!__isGLOptModeEnabled)
|
||||
{
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "disableBatchGLCommandsToNative");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void disableBatchGLCommandsToNativeJNI()
|
||||
{
|
||||
__isGLOptModeEnabled = false;
|
||||
if (__isOpenDebugView)
|
||||
{
|
||||
JniHelper::callStaticVoidMethod(JCLS_HELPER, "disableBatchGLCommandsToNative");
|
||||
}
|
||||
}
|
||||
|
||||
void exitApplication()
|
||||
{
|
||||
g_isGameFinished = true;
|
||||
}
|
||||
|
||||
|
||||
bool getApplicationExited()
|
||||
{
|
||||
return g_isGameFinished;
|
||||
}
|
||||
|
||||
int getAndroidSDKInt()
|
||||
{
|
||||
return g_SDKInt;
|
||||
}
|
||||
|
||||
|
54
cocos2d-x/cocos/platform/android/jni/JniImp.h
Normal file
54
cocos2d-x/cocos/platform/android/jni/JniImp.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
http://www.cocos.com
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
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.
|
||||
****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
typedef void (*EditTextCallback)(const std::string& text, void* ctx);
|
||||
|
||||
extern bool getApplicationExited();
|
||||
|
||||
extern void restartJSVM();
|
||||
extern void exitApplication();
|
||||
|
||||
extern std::string getApkPathJNI();
|
||||
extern std::string getPackageNameJNI();
|
||||
extern int getObbAssetFileDescriptorJNI(const std::string& path, long* startOffset, long* size);
|
||||
extern void convertEncodingJNI(const std::string& src, int byteSize, const std::string& fromCharset, std::string& dst, const std::string& newCharset);
|
||||
|
||||
extern int getDeviceSampleRateJNI();
|
||||
extern int getDeviceAudioBufferSizeInFramesJNI();
|
||||
|
||||
extern std::string getCurrentLanguageJNI();
|
||||
extern std::string getCurrentLanguageCodeJNI();
|
||||
extern std::string getSystemVersionJNI();
|
||||
extern bool openURLJNI(const std::string& url);
|
||||
extern void copyTextToClipboardJNI(const std::string& text);
|
||||
extern void setPreferredFramesPerSecondJNI(int fps);
|
||||
extern void setGameInfoDebugViewTextJNI(int index, const std::string& text);
|
||||
extern void setJSBInvocationCountJNI(int count);
|
||||
extern void openDebugViewJNI();
|
||||
extern void disableBatchGLCommandsToNativeJNI();
|
||||
extern int getAndroidSDKInt();
|
Reference in New Issue
Block a user