《“透视”个人大数据》项目开发小记 --(三)Android APP 开发(3)使用jni调用c++/c 应用实例浅析
目前应用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} )
胡方珍(胡芳珍)
浙公网安备 33010602011771号