目前应用Android Studio 可以很方便的构建完成通过JNI调用c++/c 的基本架构(CMakeLists,JNI调用C部分,java连接JNI 部分)。希望通过APP开发中应用实例的简要介绍,可以为使用JNI调用c++/c提供有益的参考借鉴。
一,java连接JNI 部分
由于APP开发中,涉及到了多个C++ Library,为了便于管理特别设置了一个独立的包名(JavaLoadCppLib),将有关库的Java类放到一个包名下。
本篇以“ActEventDataClass”为例来进行说明。"ActEventDataClass" Java类,对应的是“ActEventData-lib”C++/C库。
package com.bi3eview.newstart60.local.JavaLoadCppLib; import android.content.Context; import android.content.res.AssetManager; import com.bi3eview.newstart60.local.NetServer.NETCOMSTATIC; import com.bi3eview.newstart60.local.Person.PersonData; import com.bi3eview.newstart60.local.bs60Application; import com.bi3eview.newstart60.local.R; public class ActEventDataClass { static boolean sysloadbv = false; static { try { System.loadLibrary("ActEventData-lib"); sysloadbv = true; }catch (Throwable e) { sysloadbv = false; // Log.d("zzzzz","加载xx库异常 :"+e.toString()); } } /** * Java call JNI interface */ public static void Startgo(){ Start(); } public static int JavaJNIsaveSsysData(){ // int iretv = JNIsaveSsysData(); return iretv; } public static int JavaJNIgetSetNoteBookItem(int iobjctrl,int[] daparv,int idajno,byte[] RbyteArr,int jmaxByten) { int iretv = JNIgetSetNoteBookItem(iobjctrl,daparv,idajno,RbyteArr,jmaxByten); return iretv; } public static int JavaJNIgetRecordEventViewDataLst(int iobjctrl,int[] daparv,int idajno,byte[] RbyteArr,int jmaxByten) { int iretv = JNIgetRecordEventViewDataLst(iobjctrl,daparv,idajno,RbyteArr,jmaxByten); return iretv; } public static int JavaJNIgetSetDataParaModelInfo(int iobjctrl,int[] daparv,int idajno,byte[] RbyteArr,int jmaxByten) { int iretv = JNIgetSetDataParaModelInfo(iobjctrl,daparv,idajno,RbyteArr,jmaxByten); return iretv; } public static int JavaJNIgetSetPersonDataItem(int iobjctrl,int[] daparv,int idajno,byte[] RbyteArr,int jmaxByten) { int iretv = JNIgetSetPersonDataItem(iobjctrl,daparv,idajno,RbyteArr,jmaxByten); return iretv; } public static int JavaJNIgetSetDoubleValueDaItem(int iobjctrl,double[] daparv,int idajno,byte[] RbyteArr,int jmaxByten) { int iretv = JNIgetSetDoubleValueDaItem(iobjctrl,daparv,idajno,RbyteArr,jmaxByten); return iretv; } public static int JavaJNIgetSetDbaseUnitItem(int iobjctrl,int[] daparv,int idajno,byte[] RbyteArr,int jmaxByten) { int iretv = JNIgetSetDbaseUnitItem(iobjctrl,daparv,idajno,RbyteArr,jmaxByten); return iretv; } public static int JavaJNIcheckAssetFileIfExist(AssetManager assetManager,String strAssetFile) { int iretv = JNIcheckAssetFileIfExist(assetManager,strAssetFile); return iretv; } public static int JavaJNIgetSetDbaseTextItem(int iobjctrl,int[] daparv,int idajno,byte[] RbyteArr,int jmaxByten) { int iretv = JNIgetSetDbaseTextItem(iobjctrl,daparv,idajno,RbyteArr,jmaxByten); return iretv; } public static int JavaJNIbuildEventModel(int iobjctrl,byte[] RbyteArr,int nameByten) { int iretv = JNIbuildEventModel(iobjctrl,RbyteArr,nameByten); return iretv; } // 。。。。。。。。。。。。。。。。 /** * JNI fuction */ private native static int Start(byte[] byteArrda,int[] charItemjn); private native static int JNIsaveSsysData(); private native static int JNIgetSetNoteBookItem(int iobjctrl,int[] iparv,int idajno,byte[] byteArrda,int maxByten); private native static int JNIgetRecordEventViewDataLst(int iobjctrl,int[] chkparv,int idajno,byte[] byteArrda,int maxByten); private native static int JNIgetSetDataParaModelInfo(int iobjctrl,int[] chkparv,int idajno,byte[] byteArrda,int maxByten); private native static int JNIgetSetPersonDataItem(int iobjctrl,int[] chkparv,int idajno,byte[] byteArrda,int maxByten); private native static int JNIgetSetDoubleValueDaItem(int iobjctrl,double[] chkparv,int idajno,byte[] byteArrda,int maxByten); private native static int JNIgetSetDbaseUnitItem(int iobjctrl,int[] chkparv,int idajno,byte[] byteArrda,int maxByten); private native static int JNIgetSetDbaseTextItem(int iobjctrl,int[] chkparv,int idajno,byte[] byteArrda,int maxByten); private native static int JNIcheckAssetFileIfExist(AssetManager assetManager,String strAssetFile); // 。。。。。。。 /** system exsample */ public native String stringFromJNI(); }
为了能在不同的Fragment中,简便的调用JNI函数,Java 调用JNI接口类中使用了static类型。在Java中通过JNI应用C++/c 设置(或提取)数据,用的主要是String和byte数据类型,经常要使用 byte 转String 及String 转byte 的函数,这里也顺便提供部分代码供参考。
---- byte 转 String
byte[] tmpRbyteArr = new byte[388]; int[] daparv = new int[18]; daparv[0] = 0; daparv[1] = 0; daparv[2] = 0; daparv[3] = 0; daparv[4] = 0; daparv[5] = 0; daparv[6] = 0; int iretItemNum = ActEventDataClass.JavaJNIgetSetNoteBookItem(NOTEBOOK_GETLSTNUM,daparv,-1,tmpRbyteArr,380); if(iretItemNum >= 0) { NoteBookData.mcurItemMode = tmpRbyteArr[0]; int icol1Namecn = daparv[1]; int iboffv = 1; if (icol1Namecn > 0) { String Col1Name = new String(tmpRbyteArr, iboffv, icol1Namecn); iboffv = iboffv + icol1Namecn; //.... mcol1_nameTitle.setText(Col1Name); } int icol2Notecn = daparv[2]; if (icol2Notecn > 0) { String Col2Note = new String(tmpRbyteArr, iboffv, icol2Notecn); iboffv = iboffv + icol2Notecn; //... mcol2_noteTitle.setText(Col2Note); } // 。。。。。。。 }
--- String 转 byte
byte[] tmpRbyteArr = new byte[288]; int[] daparv = new int[18]; String Col1Name = "名称"; byte[] byteName = Col1Name.getBytes(); int iclen = byteName.length; if(iclen > 26) iclen = 26; for(int jb = 0;jb < iclen;jb++) tmpRbyteArr[jb+1] = byteName[jb]; int iboffv = 1+iclen; daparv[0] = iclen; String Col2Note = "备注"; byte[] byteNote = Col2Note.getBytes(); iclen = byteNote.length; if(iclen > 26) iclen = 26; for(int jb = 0;jb < iclen;jb++) tmpRbyteArr[jb+iboffv] = byteNote[jb]; daparv[1] = iclen; int iretItemNum = ActEventDataClass.JavaJNIgetSetNoteBookItem(NOTEBOOK_UPDATEHEADCOLNAME,daparv,-1,tmpRbyteArr,280);
二,JNI调用C++/C部分
由于APP中的C++/c 部分是个比较大的数据管理系统,因此将“JNI调用C++/C”做为了单独部分。通过C++类指针进行操作。
#include <jni.h> #include "eventManager.h" #include <string> #include <stdio.h> #include <dirent.h> #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <android/bitmap.h> #include <android/asset_manager_jni.h> #include <android/asset_manager.h> // CPP class 2019.10.10 by bs60 create static eventManager* pEventManager = NULL; // JNI Call interface extern "C" JNIEXPORT int JNICALL Java_com_bi3eview_newstart60_local_JavaLoadCppLib_ActEventDataClass_Start (JNIEnv * env, jobject obj){ if(pEventManager == NULL){ pEventManager = new eventManager(); if(pEventManager != NULL){ pEventManager->initSet(); } } return 0; } extern "C" JNIEXPORT int JNICALL Java_com_bi3eview_newstart60_local_JavaLoadCppLib_ActEventDataClass_JNIsaveSsysData (JNIEnv * env, jobject obj){ int iretv = -3; if(pEventManager != NULL){ iretv =pEventManager->SaveAppSysData(); } return iretv; } extern "C" JNIEXPORT int JNICALL Java_com_bi3eview_newstart60_local_JavaLoadCppLib_ActEventDataClass_JNIgetRecordEventViewDataLst (JNIEnv * env, jobject obj,jint icobjkd,jintArray RintArr,jint idajno,jbyteArray RbyteArr,jint jmaxByten) { int iretv = 0; jsize len = env->GetArrayLength(RintArr); if(NULL != pEventManager && len >= 6){ jint* c_RintArr = env->GetIntArrayElements(RintArr, NULL); jbyte* pArraydata = env->GetByteArrayElements(RbyteArr,0); iretv = pEventManager->GetRecordEventViewDataLst(icobjkd,c_RintArr,idajno,pArraydata,jmaxByten); env->ReleaseIntArrayElements(RintArr, c_RintArr, 0); env->ReleaseByteArrayElements(RbyteArr,pArraydata,0); } return iretv; } // task and share data parameter model ----- 2021.02.21----------- extern "C" JNIEXPORT int JNICALL Java_com_bi3eview_newstart60_local_JavaLoadCppLib_ActEventDataClass_JNIgetSetDataParaModelInfo (JNIEnv * env, jobject obj,jint icobjkd,jintArray RintArr,jint idajno,jbyteArray RbyteArr,jint jmaxByten) { int iretv = 0; jsize len = env->GetArrayLength(RintArr); if(NULL != pEventManager && len >= 2){ jint* c_RintArr = env->GetIntArrayElements(RintArr, NULL); jbyte* pArraydata = env->GetByteArrayElements(RbyteArr,0); iretv = pEventManager->GetSetDataParaModelInfo(icobjkd,c_RintArr,idajno,pArraydata,jmaxByten); env->ReleaseIntArrayElements(RintArr, c_RintArr, 0); env->ReleaseByteArrayElements(RbyteArr,pArraydata,0); } return iretv; } // person data ----- 2021.07.02 ------------ extern "C" JNIEXPORT int JNICALL Java_com_bi3eview_newstart60_local_JavaLoadCppLib_ActEventDataClass_JNIgetSetPersonDataItem (JNIEnv * env, jobject obj,jint icobjkd,jintArray RintArr,jint idajno,jbyteArray RbyteArr,jint jmaxByten) { int iretv = 0; jsize len = env->GetArrayLength(RintArr); if(NULL != pEventManager && len >= 2){ jint* c_RintArr = env->GetIntArrayElements(RintArr, NULL); jbyte* pArraydata = env->GetByteArrayElements(RbyteArr,0); iretv = pEventManager->GetSetPersonDataItem(icobjkd,c_RintArr,idajno,pArraydata,jmaxByten); env->ReleaseIntArrayElements(RintArr, c_RintArr, 0); env->ReleaseByteArrayElements(RbyteArr,pArraydata,0); } return iretv; } extern "C" JNIEXPORT int JNICALL Java_com_bi3eview_newstart60_local_JavaLoadCppLib_ActEventDataClass_JNIgetSetDoubleValueDaItem (JNIEnv * env, jobject obj,jint icobjkd,jdoubleArray RdoubleArr,jint idajno,jbyteArray RbyteArr,jint jmaxByten) { int iretv = 0; jsize len = env->GetArrayLength(RdoubleArr); if(NULL != pEventManager && len >= 2){ jdouble* d_RdoubleArr = env->GetDoubleArrayElements(RdoubleArr, NULL); jbyte* pArraydata = env->GetByteArrayElements(RbyteArr,0); iretv = pEventManager->GetSetDoubleValueDaItem(icobjkd,d_RdoubleArr,idajno,pArraydata,jmaxByten); env->ReleaseDoubleArrayElements(RdoubleArr, d_RdoubleArr, 0); env->ReleaseByteArrayElements(RbyteArr,pArraydata,0); } return iretv; } // dbase unit ----- 2021.07.19 ------------ extern "C" JNIEXPORT int JNICALL Java_com_bi3eview_newstart60_local_JavaLoadCppLib_ActEventDataClass_JNIgetSetDbaseUnitItem (JNIEnv * env, jobject obj,jint icobjkd,jintArray RintArr,jint idajno,jbyteArray RbyteArr,jint jmaxByten) { int iretv = 0; jsize len = env->GetArrayLength(RintArr); if(NULL != pEventManager && len >= 2){ jint* c_RintArr = env->GetIntArrayElements(RintArr, NULL); jbyte* pArraydata = env->GetByteArrayElements(RbyteArr,0); iretv = pEventManager->GetSetDbaseUnitItem(icobjkd,c_RintArr,idajno,pArraydata,jmaxByten); env->ReleaseIntArrayElements(RintArr, c_RintArr, 0); env->ReleaseByteArrayElements(RbyteArr,pArraydata,0); } return iretv; } // dbase text ----- 2021.10.30 ------------ extern "C" JNIEXPORT int JNICALL Java_com_bi3eview_newstart60_local_JavaLoadCppLib_ActEventDataClass_JNIgetSetDbaseTextItem (JNIEnv * env, jobject obj,jint icobjkd,jintArray RintArr,jint idajno,jbyteArray RbyteArr,jint jmaxByten) { int iretv = 0; jsize len = env->GetArrayLength(RintArr); if(NULL != pEventManager && len >= 2){ jint* c_RintArr = env->GetIntArrayElements(RintArr, NULL); jbyte* pArraydata = env->GetByteArrayElements(RbyteArr,0); iretv = pEventManager->GetSetDbaseTextItem(icobjkd,c_RintArr,idajno,pArraydata,jmaxByten); env->ReleaseIntArrayElements(RintArr, c_RintArr, 0); env->ReleaseByteArrayElements(RbyteArr,pArraydata,0); } return iretv; } extern "C" JNIEXPORT int JNICALL Java_com_bi3eview_newstart60_local_JavaLoadCppLib_ActEventDataClass_JNIcheckAssetFileIfExist (JNIEnv * env, jobject obj,jobject assetManager, jstring dataFileName) { int iretv = -1; if(NULL != pEventManager){ AAssetManager* mManeger = AAssetManager_fromJava(env, assetManager); jboolean iscopy; const char *dataFile = env->GetStringUTFChars(dataFileName, &iscopy); //open file AAsset *assetFile = AAssetManager_open(mManeger, dataFile, AASSET_MODE_BUFFER); if(assetFile != NULL){ iretv = 1; AAsset_close(assetFile); } env->ReleaseStringUTFChars(dataFileName, dataFile); } return iretv; } // note book extern "C" JNIEXPORT int JNICALL Java_com_bi3eview_newstart60_local_JavaLoadCppLib_ActEventDataClass_JNIgetSetNoteBookItem (JNIEnv * env, jobject obj,jint icobjkd,jintArray RintArr,jint idajno,jbyteArray RbyteArr,jint jmaxByten) { int iretv = 0; jsize len = env->GetArrayLength(RintArr); if(NULL != pEventManager && len >= 6){ jint* c_RintArr = env->GetIntArrayElements(RintArr, NULL); jbyte* pArraydata = env->GetByteArrayElements(RbyteArr,0); iretv = pEventManager->GetSetNoteBookItem(icobjkd,c_RintArr,idajno,pArraydata,jmaxByten); env->ReleaseIntArrayElements(RintArr, c_RintArr, 0); env->ReleaseByteArrayElements(RbyteArr,pArraydata,0); } return iretv; } // 。。。。。。。。。。 // test remain example 2019.10.09 ------------------------------------------ extern "C" JNIEXPORT jstring JNICALL Java_com_bi3eview_newstart60_local_JavaLoadCppLib_ActEventDataClass_stringFromJNI (JNIEnv* env, jobject obj) { std::string hello = "Hello from JNI C++ 2019.09.09 "; return env->NewStringUTF(hello.c_str()); } extern "C" JNIEXPORT jstring JNICALL Java_com_bi3eview_newstart60_local_JavaLoadCppLib_ActEventDataClass_createFileFromJNI( JNIEnv *env, jobject obj) { std::string hello = "Hello from C++"; char *strDirPath="D:/test/test1/test2"; mkdir(strDirPath,0775); FILE* file = NULL; file = fopen("/data/data/com.example.clientfile/hello.txt","a"); //创建文件 if(file == NULL){ //容错 // LOG_D("文件创建失败%s","222"); } fwrite("1111",3,1,file); //往文件中写文件 fclose(file); //关闭文件 return env->NewStringUTF(hello.c_str()); }
"eventManager"类的的部分代码。
// // Created by hufz on 2019/10/7. // #ifndef BIDAEVIEWCYBORG_EVENTMANAGER_H #define BIDAEVIEWCYBORG_EVENTMANAGER_H #include <jni.h> #include <android/log.h> #include <stdio.h> #include <sys/time.h> #include <math.h> #include <stdlib.h> #include<string.h> #include "eventShare_struct.h" #include "eventDetail.h" #include "netShareBook.h" #include "publishTaskrec.h" #include "finishTaskRecord.h" #include "AccountTaskInfo.h" #include "Account2Notify.h" #include "AccountNetpal.h" #include "taskCheckDataLst.h" #include "PersonData.h" #include "pcDbaseUnit.h" #include "modelEvent.h" #include "noteBook.h" #include "ClockIn.h" #include "pcDbaseComText.h" /** * create by bs60 on 2019.9.23 */ // event manager class class eventManager { static const int EVENTMAXJN = 30; static const int CHARBULISTAXJN = EVENTMAXJN*6; static const int LONGCHARBULISTAXJN = EVENTMAXJN*3; static const int TASKLISTMAXJN = EVENTMAXJN*8; static const int EVENTNAME_MAXN = 20; static const int EVENTNOTE_MAXN = 40; static const int EVENTFIND_ONIDNO = 1234567; static const int TASKACTIVE_MAXNUM = 200; static const int EDITEVENTTASK_MAXNUM = 100; static const int PRIVATEDATALIST_MAXNUM = 5; // 。。。。。。。。。。。。。。。 public: eventManager(); ~eventManager(); void init(); void destroy(); int exitSaveData(); int SaveAppSysData(); // 。。。。。。。。。。。。。。。。 private: int checkBasicWorkDir(char* SDcardp, int iclen); int LoadEventManagerList(char* eventManagerfile); int CreateBasicEventManagerLis(char* eventManagerfile); int CreateBasicEventOldManagerLis(char* eventManagerfile); static int get_file_size_time(const char *filename); static int ReadDirFile(const char *dirname); void initEventDetailData(EVENTMANAGERDETAIL* pEventDetail); unsigned short buildCharNameList(char* strName); unsigned short UpdateSetCharNameList(int ioldcharposj,jbyte* cretItemcp,int maxcn); int createEventSoreDir(char* dirName); int getCharListContext(int icharLstj,jbyte* cretItemcp,int maxcn,int ioffv); int appendBuildContext(int igetStposj,jbyte* getItemcp,int maxcn,char* starMark,char* char2next,int chindexcp,char* endMark); int AppendCharListContext(char* newChar,int inewposj,jbyte* cretItemcp,int maxcn); // 。。。。。。。。。。。。。。。。。。。。。 }; #endif //BIDAEVIEWCYBORG_EVENTMANAGER_H
三, CMakeLists
# For more information about using CMake with Android Studio, read the # documentation: https://d.android.com/studio/projects/add-native-code.html # Sets the minimum version of CMake required to build the native library. cmake_minimum_required(VERSION 3.4.1) # Creates and names a library, sets it as either STATIC # or SHARED, and provides the relative paths to its source code. # You can define multiple libraries, and CMake builds them for you. # Gradle automatically packages shared libraries with your APK. add_library( # Sets the name of the library. comtools-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). src/main/cpp/global_para.cpp / src/main/cpp/copy_write.cpp / src/main/cpp/global_para_JNI.cpp src/main/cpp/CppByteNetSerial.cpp / src/main/cpp/JNICallNetSerial.cpp ) add_library( # Sets the name of the library. ActEventData-lib # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). src/main/cpp/eventDetail.cpp / src/main/cpp/eventDataDetail.cpp / src/main/cpp/eventManager.cpp / src/main/cpp/eventManager_cybertask.cpp / src/main/cpp/eventManager_sharebook.cpp / src/main/cpp/netShareBook.cpp / src/main/cpp/publishTaskrec.cpp / src/main/cpp/finishTaskRecord.cpp / src/main/cpp/eventManager_publishtask.cpp / src/main/cpp/eventManager_accountinfo.cpp / src/main/cpp/eventManager_accountNotify.cpp / src/main/cpp/eventManager_accountNetpal.cpp / src/main/cpp/AccountTaskInfo.cpp / src/main/cpp/Account2Notify.cpp / src/main/cpp/AccountNetpal.cpp / src/main/cpp/taskCheckDataLst.cpp / src/main/cpp/PersonData.cpp / src/main/cpp/pcDbaseUnit.cpp / src/main/cpp/pcDbaseComText.cpp / src/main/cpp/eventManager_pcDbase.cpp / src/main/cpp/eventManager_personData.cpp / src/main/cpp/eventManager_model.cpp / src/main/cpp/eventManager_modelEvent.cpp / src/main/cpp/modelEvent.cpp / src/main/cpp/eventManager_noteBook.cpp / src/main/cpp/noteBook.cpp / src/main/cpp/eventManager_ClockIn.cpp / src/main/cpp/ClockIn.cpp / src/main/cpp/eventManager_JNI.cpp ) # Searches for a specified prebuilt library and stores the path as a # variable. Because CMake includes system libraries in the search path by # default, you only need to specify the name of the public NDK library # you want to add. CMake verifies that the library exists before # completing its build. find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log ) # Specifies libraries CMake should link to your target library. You # can link multiple libraries, such as libraries you define in this # build script, prebuilt third-party libraries, or system libraries. target_link_libraries( # Specifies the target library. ActEventData-lib comtools-lib #lib to link android # other libs # Links the target library to the log library # included in the NDK. ${log-lib} )
标签:--,APP,int,RintArr,env,cpp,iretv,浅析,RbyteArr From: https://www.cnblogs.com/newstart60/p/16975249.html