#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <jni.h>
#include <stdarg.h>
#include <assert.h>
#include <android/log.h>
//#define DYN_NATIVE
#ifdef DYN_NATIVE
#include "platform/android/NativeGLAppView.hpp"
#include "platform/android/PackageNameUtils.h"
#include "SFCodeNative.h"
#define LOG(...) __android_log_print(ANDROID_LOG_INFO, "RegNative", ##__VA_ARGS__);
#define CLS_GF_APP "/NativeGLAppView"
#define CLS_GF_ANDROID_HELP "/AndroidHelper"
#define CLS_GF_RUNLOOP "/AndroidRunLoop"
#define CLS_MAIN_GAME "/MainActivity"
static int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods);
//jobject s_jobjContext = NULL;
char s_localClass[256] = {0};
char s_unityClass[256] = {0};
jobject CallJavaObjectMethodVReturingObject(JNIEnv* pEnv, jobject obj, const char* name, const char* sig, va_list args)
{
if(!pEnv || !obj)
return NULL;
jclass cls = (*pEnv)->GetObjectClass(pEnv, obj);
if(ExceptionCheckClear(pEnv) == 0)
{
LOG("err CallJavaObjectMethodVReturingObject cls obj:%d", (int)obj);
return NULL;
}
jmethodID methodID = (*pEnv)->GetMethodID(pEnv, cls, name, sig);
if(ExceptionCheckClear(pEnv) == 0)
{
LOG("err CallJavaObjectMethodVReturingObject methodID:%d", (int)methodID);
(*pEnv)->DeleteLocalRef(pEnv, cls);
return NULL;
}
jobject ret = (*pEnv)->CallObjectMethodV(pEnv, obj, methodID, args);
if(ExceptionCheckClear(pEnv) == 0)
{
LOG("err CallJavaObjectMethodVReturingObject ret:%d", (int)ret);
(*pEnv)->DeleteLocalRef(pEnv, cls);
return NULL;
}
(*pEnv)->DeleteLocalRef(pEnv, cls);
return ret;
}
jobject CallJavaObjectMethodReturingObject(JNIEnv* pEnv, jobject obj, const char* name, const char* sig, ...)
{
va_list args;
va_start(args, sig);
jobject ret = CallJavaObjectMethodVReturingObject(pEnv, obj, name, sig, args);
va_end(args);
return ret;
}
jstring JavaStringFromString(JNIEnv* pEnv, const char* str)
{
jstring jstr = NULL;
jclass strClass = (*pEnv)->FindClass(pEnv, "java/lang/String");
jmethodID ctorID = (*pEnv)->GetMethodID(pEnv, strClass, "<init>", "([BLjava/lang/String;)V");
jbyteArray bytes = (*pEnv)->NewByteArray(pEnv, (jsize)strlen(str));
(*pEnv)->SetByteArrayRegion(pEnv, bytes, 0, (jsize)strlen(str), (jbyte*)str);
jstring encoding = (*pEnv)->NewStringUTF(pEnv, "utf-8");
jstr = (jstring)(*pEnv)->NewObject(pEnv, strClass, ctorID, bytes, encoding);
if(ExceptionCheckClear(pEnv) == 0)
{
}
(*pEnv)->DeleteLocalRef(pEnv, strClass);
(*pEnv)->DeleteLocalRef(pEnv, bytes);
(*pEnv)->DeleteLocalRef(pEnv, encoding);
return jstr;
}
char* charArrayFromJavaString(JNIEnv* pEnv, jstring jstr, char* des)
{
if(jstr)
{
const char* pChars;
pChars = (*pEnv)->GetStringUTFChars(pEnv, jstr, NULL);
int len = strlen(pChars);
if (len > 256)
len = 256;
memcpy(des, pChars, len);
des[len] = 0;
(*pEnv)->ReleaseStringUTFChars(pEnv, jstr, pChars);
}
return des;
}
int ExceptionCheckClear(JNIEnv* pEnv)
{
if((*pEnv)->ExceptionCheck(pEnv))
{
#ifdef DEBUG
(*pEnv)->ExceptionDescribe(pEnv);
#endif
(*pEnv)->ExceptionClear(pEnv);
return 0;
}
return 1;
}
JNIEXPORT void JNICALL initActivity(JNIEnv *env, jobject clazz, jobject jobjContext)
{
//s_jobjContext = (*env)->NewGlobalRef(jobjcontext);
char share[10] = "game_n";
jstring jshare = JavaStringFromString(env, share);
jobject localSharedPreferences = CallJavaObjectMethodReturingObject(env, jobjContext, "getSharedPreferences", "(Ljava/lang/String;I)Landroid/content/SharedPreferences;", jshare, 0);
if (localSharedPreferences == 0) {
LOG("localSharedPreferences:err");
}
char localKey[10] = "ac";
jstring jlocalKey = JavaStringFromString(env, localKey);
char localDef[128] = "com.cn.nw.a.a.n.LocalCode";
jstring jlocalDef = JavaStringFromString(env, localDef);
jstring local = (jstring)CallJavaObjectMethodReturingObject(env, localSharedPreferences, "getString", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", jlocalKey, jlocalDef);
char localCls[256] = {0};
charArrayFromJavaString(env, local, localCls);
//LOG("localCls:%s", localCls);
char unityKey[10] = "nc";
jstring junityKey = JavaStringFromString(env, unityKey);
char unityDef[128] = "com.cn.nw.a.a.n.UnityCode";
jstring junityDef = JavaStringFromString(env, unityDef);
jstring unity = (jstring)CallJavaObjectMethodReturingObject(env, localSharedPreferences, "getString", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;", junityKey, junityDef);
char unityCls[256] = {0};
charArrayFromJavaString(env, unity, unityCls);
(*env)->DeleteLocalRef(env, jshare);
(*env)->DeleteLocalRef(env, localSharedPreferences);
(*env)->DeleteLocalRef(env, jlocalKey);
(*env)->DeleteLocalRef(env, jlocalDef);
(*env)->DeleteLocalRef(env, local);
(*env)->DeleteLocalRef(env, junityKey);
(*env)->DeleteLocalRef(env, junityDef);
(*env)->DeleteLocalRef(env, unity);
JNINativeMethod gMethods[] = {
{ "initNative", "()V", (void*)Java_com_cn_nw_a_a_n_LocalCode_initNative },
{ "onSuccess", "(Ljava/lang/String;)V", (void*)Java_com_cn_nw_a_a_n_LocalCode_onSuccess },
{ "onFailed", "(Ljava/lang/String;)V", (void*)Java_com_cn_nw_a_a_n_LocalCode_onFailed },
};
int clsLen = strlen(localCls);
int i = 0;
for (i = 0; i < clsLen; i++) {
if(localCls[i] == '.') {
s_localClass[i] = '/';
} else {
s_localClass[i] = localCls[i];
}
}
s_localClass[clsLen] = 0;
//LOG("s_localClass:%s", s_localClass);
clsLen = strlen(unityCls);
i = 0;
for (i = 0; i < clsLen; i++) {
if(unityCls[i] == '.') {
s_unityClass[i] = '/';
} else {
s_unityClass[i] = unityCls[i];
}
}
s_unityClass[clsLen] = 0;
//LOG("s_unityClass:%s", s_unityClass);
setLocalClassName(s_localClass);
setUnityClassName(s_unityClass);
if (!registerNativeMethods(env, s_localClass, gMethods, sizeof(gMethods) / sizeof(gMethods[0]))) {
LOG("JNI_OnLoad reg LocalCode error");
return;
}
//LOG("JNI_OnLoad reg LocalCode success");
}
static JNINativeMethod mainMethods[] = {
{"initActivity", "(Landroid/content/Context;)V", (void*) initActivity },
};
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void* reserved)
{
LOG("JNI_OnLoad ++++++++ start");
JNIEnv* env = NULL;
jint result = -1;
if((*vm)->GetEnv(vm,(void**)&env, JNI_VERSION_1_4) != JNI_OK) {
LOG("JNI_OnLoad GetEnv null");
return -1;
}
char className[256] = {0};
getCurrClassName(env, className, CLS_GF_APP);
if (!registerNativeMethods(env, className, gf_NativeGLAppView_Methods, sizeof(gf_NativeGLAppView_Methods) / sizeof(gf_NativeGLAppView_Methods[0]))) {
LOG("JNI_OnLoad reg NativeGLAppView error");
return JNI_FALSE;
}
getCurrClassName(env, className, CLS_GF_ANDROID_HELP);
if (!registerNativeMethods(env, className, gf_AndroidHelper_Methods, sizeof(gf_AndroidHelper_Methods) / sizeof(gf_AndroidHelper_Methods[0]))) {
LOG("JNI_OnLoad reg AndroidHelper error");
return JNI_FALSE;
}
getCurrClassName(env, className, CLS_GF_RUNLOOP);
if (!registerNativeMethods(env, className, gf_AndroidRunLoop_Methods, sizeof(gf_AndroidRunLoop_Methods) / sizeof(gf_AndroidRunLoop_Methods[0]))) {
LOG("JNI_OnLoad reg AndroidRunLoop error");
return JNI_FALSE;
}
getCurrClassName(env, className, CLS_MAIN_GAME);
if (!registerNativeMethods(env, className, mainMethods, sizeof(mainMethods) / sizeof(mainMethods[0]))) {
LOG("reg mainMethods error");
return JNI_FALSE;
}
result = JNI_VERSION_1_4;
LOG("JNI_OnLoad --------- end");
return result;
}
int registerNativeMethods(JNIEnv* env, const char* className, JNINativeMethod* gMethods, int numMethods) {
//LOG("registerNativeMethods s