android java 与 c++ 相互调用的方法
程序员文章站
2022-06-12 19:42:38
...
android java 与 c++ 相互调用的方法
最近在写native部分的代码,需要c++和java相互调用。记得JK之前说过他弄了一个新的方法,在写jni的时候会*一点,我对了一下他的代码,根据我的场景写了一个出来。在这里给自己做一点笔记吧。
Android.mk
LOCAL_MODULE := SDKBridge_shared
LOCAL_MODULE_FILENAME := libSDKBridge
LOCAL_SRC_FILES := $(LOCAL_PATH)/hellocpp/sdk_bridge.cpp
LOCAL_CPPFLAGS += -fexceptions # enable try...catch
LOCAL_LDLIBS := -llog # enable android logcat
include $(BUILD_SHARED_LIBRARY)
如果要引用自己的so库的时候
LOCAL_SHARED_LIBRARIES := SDKBridge_shared
java层中这样引用这个库
package org.cocos2dx.cpp;
public class SDKBridge {
static {
System.loadLibrary("SDKBridge");
}
public static void quit() {
Log.d(TAG, "Java quit");
AppActivity ac = AppActivity.getActivity();
if (ac != null) ac.quit();
}
public static native void _init();
public static native void _onQuit();
}
重点就是在 cpp 中的 JNI_OnLoad 的方法,这样设计
sdk_bridge.cpp
#include <android/log.h>
#include <stdio.h>
#include <jni.h>
#include <cstdlib>
#include "sdk_bridge.h"
#include "stddef.h"
#define LOG_TAG "SDKBridge"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define JAVA_SDK_CLASS_PATH "org/cocos2dx/cpp/SDKBridge"
namespace sdk {
JavaVM *_vm = NULL;
jclass _sdk_bridge_cls = NULL;
jmethodID _sdk_quit = NULL;
void check_jni_ready(JNIEnv *env) {
if (NULL == env || NULL == _sdk_bridge_cls
|| NULL == _sdk_login || NULL == _sdk_logout
|| NULL == _sdk_pay || NULL == _sdk_quit) {
LOGE("jni is not ready! init error!");
abort();
}
}
JNIEnv *getEnv() {
if (NULL == _vm) {
LOGE("jni is not ready! Please call _init first!");
abort();
}
JNIEnv *env;
_vm->AttachCurrentThread(&env, nullptr);
return env;
}
void java_quit(JNIEnv *env) {
check_jni_ready(env);
env->CallStaticVoidMethod(_sdk_bridge_cls, _sdk_quit);
}
void native_init(JNIEnv *env) {
LOGI("init");
}
void native_on_quit() {
LOGE("TODO:native on quit");
if (NULL != sCallbackFunction) {
sCallbackFunction("onQuit","");
}
}
}
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *unused) {
JNIEnv *env = NULL;
jclass sdk_bridge_cls;
static JNINativeMethod methods[] = {
{"_init", "()V", (void *) sdk::native_init},
{"_onQuit", "()V", (void *) sdk::native_on_quit}
};
if ((*vm).GetEnv((void **) &env, JNI_VERSION_1_6) != JNI_OK) {
LOGE("get env error, abort!");
abort();
}
sdk_bridge_cls = env->FindClass(JAVA_SDK_CLASS_PATH);
if (!sdk_bridge_cls) {
LOGE("native registration unable to find class '%s'!", JAVA_SDK_CLASS_PATH);
abort();
}
if (env->RegisterNatives(sdk_bridge_cls, methods, sizeof(methods) / sizeof(methods[0])) <
0) {
LOGE("native registration failed!");
abort();
}
sdk::_sdk_login = env->GetStaticMethodID(sdk_bridge_cls, "quit", "()V");
if (!sdk::_sdk_login) {
LOGE("can not get login method id!");
abort();
}
sdk::_vm = vm;
sdk::_sdk_bridge_cls = (jclass) env->NewGlobalRef(sdk_bridge_cls);
(*env).DeleteLocalRef(sdk_bridge_cls);
return JNI_VERSION_1_6;
}
sdk_bridge.h
#ifndef PROJ_ANDROID_SDK_BRIDGE_H
#define PROJ_ANDROID_SDK_BRIDGE_H
#include <jni.h>
#include <string>
namespace sdk {
typedef void (*OnJavaCallback)(std::string, std::string);
OnJavaCallback sCallbackFunction = NULL;
void register_print(OnJavaCallback callback) {
sCallbackFunction = callback;
}
JNIEnv *getEnv();
void java_quit(JNIEnv *env);
}
#endif //PROJ_ANDROID_SDK_BRIDGE_H
一个注意点就是 JNIEnv 不能做缓存,能缓存的只有 JavaVM
上一篇: 整库备份mysql_MySQL
下一篇: MySQL5新特点(视图)_MySQL
推荐阅读
-
Android编程使用WebView实现与Javascript交互的方法【相互调用参数、传值】
-
Android WebView的使用方法及与JS 相互调用
-
android图片文件的路径地址与Uri的相互转换方法
-
安卓应用开发通过java调用c++ jni的图文使用方法
-
调用android的getColor()方法出现 java.lang.NoSuchMethodError: android.content.res.Resources.getColor
-
android图片文件的路径地址与Uri的相互转换方法
-
JAVA方法调用中的解析与分派
-
Python与C/C++的相互调用案例
-
Android WebView的使用方法及与JS 相互调用
-
Android JNI c/c++调用java的实例