Android:通过JNI调用c++代码
来源:互联网 发布:投资组合优化模型 编辑:程序博客网 时间:2024/06/05 04:13
一些说明
//查找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 __cplusplusextern "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_staticinclude $(BUILD_MULTI_PREBUILT)#在所有源文件中增加一个宏定义#define MARKUP_STDCONVLOCAL_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中如何通过jni调用c,c++代码
- android通过jni调用C代码socket出错问题
- android 通过JNI调用C/C++代码(linux)
- 通过JNI接口在Android中调用C/C++代码
- android通过jni调用C代码socket出错问题
- Android App中通过JNI调用C/C++代码
- Android:通过JNI调用c++代码
- Android C 通过JNI 调用JAVA
- 用Android Studio通过Java代码调用C代码的JNI流程
- Android Studio中通过jni实现对C/C++代码的调用,HelloJni,Ubuntu
- Android App中通过JNI调用C/C++代码(二)
- Java 通过JNI调用C或者CPP代码
- Java 通过JNI调用C或者CPP代码
- 使用Qt / C + +通过JNI调用Java代码
- win7下java通过JNI调用C代码
- android实现app通过jni调用C/C++方法
- android实现app通过jni调用C/C++方法
- Android JNI 通过C/C++调用JAVA方法
- Java的Runtime
- 使用maven多模块构建dubbo第一个分布式HelloWorld
- install 安装apk正常push到系统目录运行报错问题
- mysql字符串包含的四种写法
- 软工文档总结
- Android:通过JNI调用c++代码
- Run Time中请求系统权限Requesting Permissions at Run Time
- 一行代码实现java list去重
- PAT04-树6 Complete Binary Search Tree 【JAVA实现】
- File操作-RandomAccessFile
- CentOS7与MySQL
- Android 并发二三事之AsyncTask
- 《iOS移动开发从入门到精通》图书连载5:Xcode 8的使用(上)
- EditText的部分操作