Android:通过JNI调用c++代码
2016-11-16 14:30
405 查看
一些说明
//查找JNIAPI类,得到类的class,包名每级用/分隔
jclass clazz = env->FindClass("com/g/im/JNIAPI");
//通过类查找静态方法,得到方法的引用,callBackLogin为方法名称,"Ljava/lang/String;"表示函数参数为String类型,要用括号括起来,V表示函数返回值为void
jmethodID methodId = env -> GetStaticMethodID(clazz, "callBackLogin", "(Ljava/lang/String;)V")
//调用此方法,第三个参数为
env->CallStaticVoidMethod(clazz, id, jstring类型的字符串)
在JNI中与Java类型对应的类型如下,一个方法有多个参数时直接组合使用:
类类型:L包名/类名; 需要以分号结尾,如:Ljava/lang/String;
类类型[]:[L包名/类名; 需要以分号结尾,如:[Ljava/lang/String;
boolean:Z 如:env -> GetStaticMethodID(clazz, "callBackLogin", "(Z)V")
boolean[]:[Z
byte:B
byte[]:[B
char:C
char[]:[C
short:S
short[]:[S
int:I
int[]:[I
long:J
long[]:[J
float:F
float[]:[F
double:D
double[]:[D
void:V
Java调用类:
与Java对应的.h头文件:
.h的实现cpp文件,此类用于java与c++交互数据用:
与上面对应的.h头文件:
Android.mk文件:
Application.mk文件:
//查找JNIAPI类,得到类的class,包名每级用/分隔
jclass clazz = env->FindClass("com/g/im/JNIAPI");
//通过类查找静态方法,得到方法的引用,callBackLogin为方法名称,"Ljava/lang/String;"表示函数参数为String类型,要用括号括起来,V表示函数返回值为void
jmethodID methodId = env -> GetStaticMethodID(clazz, "callBackLogin", "(Ljava/lang/String;)V")
//调用此方法,第三个参数为
env->CallStaticVoidMethod(clazz, id, jstring类型的字符串)
在JNI中与Java类型对应的类型如下,一个方法有多个参数时直接组合使用:
类类型:L包名/类名; 需要以分号结尾,如:Ljava/lang/String;
类类型[]:[L包名/类名; 需要以分号结尾,如:[Ljava/lang/String;
boolean:Z 如:env -> GetStaticMethodID(clazz, "callBackLogin", "(Z)V")
boolean[]:[Z
byte:B
byte[]:[B
char:C
char[]:[C
short:S
short[]:[S
int:I
int[]:[I
long:J
long[]:[J
float:F
float[]:[F
double:D
double[]:[D
void:V
Java调用类:
/** * Java与C/C++互调 * (JNI调用动态库接口) */ public class JNIAPI { static { System.loadLibrary("GIM"); } /** * 登录 */ public native void login(String username, String ticket, String deviceId); /** * C++层异步回调 */ public void callbackLogin(String jsonData) { //解析返回的数据 } }
与Java对应的.h头文件:
#include <jni.h> #ifndef _Included_com_g_im_biz_JNIAPI #define _Included_com_g_im_biz_JNIAPI #ifdef __cplusplus extern "C" { #endif /** * 登录 */ JNIEXPORT void JNICALL Java_com_g_im_biz_JNIAPI_login(JNIEnv *, jobject, jstring, jstring, jstring); #ifdef __cplusplus } #endif #endif
.h的实现cpp文件,此类用于java与c++交互数据用:
#include <string.h> #include <jni.h> #include <locale.h> #include <stdlib.h> #include <list> #include <vector> #include "com_g_im_biz_JNIAPI.h" #include "com_g_im_biz_JNIAPI_impl.h" #include "GTPIM/common/CommUtility.h" #include<stdio.h> #include <android/log.h> #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "ProjectName", __VA_ARGS__) #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , "ProjectName", __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO , "ProjectName", __VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN , "ProjectName", __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , "ProjectName", __VA_ARGS__) JavaVM* mJvm; jobject mJNIAPI_obj; jobject mStr_obj; void processSignal(int signo); /**jstring转换char**/ char* jstringToChar(JNIEnv* env, jstring jstr) { if (jstr == NULL){ return NULL; } char* rtn = new char; jclass clsstring = env->FindClass("java/lang/String"); jstring strencode = env->NewStringUTF("utf-8"); jmethodID mid = env->GetMethodID(clsstring, "getBytes","(Ljava/lang/String;)[B"); jbyteArray barr = (jbyteArray) env->CallObjectMethod(jstr, mid, strencode); jsize alen = env->GetArrayLength(barr); jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE); if (alen > 0){ rtn = (char*) malloc(alen + 1); memcpy(rtn, ba, alen); rtn[alen] = 0; }else { rtn = ""; } /**资源清理**/ env->ReleaseByteArrayElements(barr, ba, 0); if(clsstring != NULL){ env->DeleteLocalRef(clsstring); clsstring = NULL; } if(strencode != NULL){ env->DeleteLocalRef(strencode); strencode = NULL; } mid = NULL; return rtn; } /**char转换jstring**/ jstring charToJstring(JNIEnv* env, const char* pat){ jclass str_class = env->GetObjectClass(mStr_obj); jmethodID ctorID = env->GetMethodID(str_class, "<init>", "([BLjava/lang/String;)V"); jbyteArray bytes = env->NewByteArray(strlen(pat)); env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat); jstring encoding = env->NewStringUTF("utf-8"); jstring str = (jstring)env->NewObject(str_class, ctorID, bytes, encoding); jbyte* ba = env->GetByteArrayElements(bytes, JNI_FALSE); /**资源清理**/ env->ReleaseByteArrayElements(bytes, ba, 0); if(str_class != NULL){ env->DeleteLocalRef(str_class); str_class = NULL; } if(encoding != NULL){ env->DeleteLocalRef(encoding); encoding = NULL; } ctorID = NULL; return str; } /**得到对象**/ jobject getInstance(JNIEnv* env, jclass JNIAPI_class){ jmethodID JNIAPI_method = env->GetMethodID(JNIAPI_class, "<init>", "()V"); jobject JNIAPI_obj = env->NewObject(JNIAPI_class, JNIAPI_method); return JNIAPI_obj; } /** * 回调java中的方法 * @param methodName 方法名 * @param jsonData json数据 */ void callbackJava(const char* methodName, const char* jsonData){ JNIEnv* env; int status = mJvm->AttachCurrentThread(&env, NULL); if(status >= 0){ jclass JNIAPI_class = env->GetObjectClass(mJNIAPI_obj); jmethodID JNIAPI_method = env->GetMethodID(JNIAPI_class, methodName,"(Ljava/lang/String;)V"); if(JNIAPI_method != 0){ jstring str = charToJstring(env, xmlData); env->CallVoidMethod(mJNIAPI_obj, JNIAPI_method, str); /**资源清理**/ if(JNIAPI_class != NULL){ env->DeleteLocalRef(JNIAPI_class); JNIAPI_class = NULL; } if(str != NULL){ env->DeleteLocalRef(str); str = NULL; } JNIAPI_method = NULL; } if(strcmp(methodName, "printSignLog") != 0 && strcmp(methodName,"addMsgCache") != 0 && strcmp(methodName,"removeMsgCache") != 0){ mJvm->DetachCurrentThread(); } } } /** * 登录 */ JNIEXPORT void JNICALL Java_com_glodon_im_service_JNIAPI_login(JNIEnv* env, jobject thiz, jstring name, jstring ticket, jstring deviceId) { char* rtticket = jstringToChar(env, ticket); char* rtdeviceId = jstringToChar(env, deviceId); comm.login(rtname, rtticket, rtdeviceId); if(rtname != NULL){ free(rtname); rtname = NULL; } if(rtticket != NULL){ free(rtticket); rtticket = NULL; } if(rtdeviceId != NULL){ free(rtdeviceId); rtdeviceId = NULL; } } void callbackLogin(const char* jsonData){ callbackJava("callbackLogin", jsonData); }
与上面对应的.h头文件:
#include <string.h> #include <jni.h> #include <locale.h> #include <stdlib.h> #include <signal.h> #include <list> #include <vector> #include <android/log.h> #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, "ProjectName", __VA_ARGS__) #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , "ProjectName", __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO , "ProjectName", __VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN , "ProjectName", __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , "ProjectName", __VA_ARGS__) void callbackLogin(const char* jsonData);
Android.mk文件:
#指定Android.mk的路径 LOCAL_PATH := $(call my-dir) #用于重置除LOCAL_PATH变量外的,所有LOCAL_XXX系列变量 include $(CLEAR_VARS) #使用标准库,系统默认使用system(最小的C++运行库,部分功能将无法支持) APP_STL := stlport_static include $(BUILD_MULTI_PREBUILT) #在所有源文件中增加一个宏定义#define MARKUP_STDCONV LOCAL_CFLAGS := \ -DMARKUP_STDCONV #生成的so文件名 LOCAL_MODULE := GIM $(warning $(SYSROOT)) #添加系统库 LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog #需要参与编译的cpp源文件 LOCAL_SRC_FILES := \ com_g_im_biz_JNIAPI_impl.cpp \ #编译静态库 #include $(BUILD_STATIC_LIBRARY) #编译动态库 include $(BUILD_SHARED_LIBRARY)
Application.mk文件:
# C++异常 C++ RTTI C++标准库 #System默认的 不支持 不支持 不支持 #gabi++_shared、gabi++_static 不支持 支持 不支持 #stlport_shared、stlport_static 不支持 支持 支持 #gnustl_shared、gnustl_static 支持 支持 支持 APP_STL := gnustl_static #表示生成哪些CPU架构的so,有这些值:all、armeabi、armeabi-v7a、x86、mips #APP_ABI := armeabi armeabi-v7a #STLPORT_FORCE_REBUILD := true #可以使用APP_GNUSTL_CPP_FEATURES,指使用C++异常(exceptions)或C++ RTTI特性(rtti) APP_CPPFLAGS += -fexceptions #NDK版本号 APP_PLATFORM := android-9
相关文章推荐
- Android App中通过JNI调用C/C++代码(二)
- Android(安卓)开发通过NDK调用JNI,使用opencv做本地c++代码开发配置方法 边缘检测 范例代码
- [转]Android通过NDK调用JNI,使用opencv做本地c++代码开发配置方法
- Android App中通过JNI调用C/C++代码
- android中如何通过jni调用c,c++代码
- Android(安卓)开发通过NDK调用JNI,使用opencv做本地c++代码开发配置方法实现边缘检测代码(2)
- 调试android通过jni调用的C++代码
- [安卓开发笔记二]android Studio通过jni调用C++代码
- Android(安卓)开发通过NDK调用JNI,使用opencv做本地c++代码开发配置方法 边缘检测 范例代码
- Android 学习笔记——利用JNI技术在Android中调用、调试C++代码
- AndroidJNI 通过C++调用JAVA
- Cocos2d-x游戏开发之Cocos2dx通过JNI调用Android的Java代码(webView实例)
- 利用JNI技术在Android中调用、调试C++代码
- 【iOS-cocos2d-X 游戏开发之十三】cocos2dx通过Jni调用Android的Java层代码(下)
- Android JNI简单实例(android 调用C/C++代码)
- Android 学习笔记——利用JNI技术在Android中调用、调试C++代码
- AndroidJNI 通过C++调用JAVA
- AndroidJNI 通过C++调用JAVA
- Android JNI通过C++调用JAVA
- AndroidJNI 通过C++调用JAVA