1、JNI代码:heartrate_ppg.cpp
#define LOG_TAG "heartrate_ppg"
#include <utils/Log.h>
#include <log/log.h>
#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <poll.h>
#include <unistd.h>
#include <dirent.h>
#include <stdlib.h>
#include <pthread.h>
#include <linux/input.h>
#include <sys/select.h>
#include <android/log.h>
#include <cutils/log.h>
#include "jni.h"
#ifdef __cplusplus
extern "C" {
#endif
#define DEV_PATH "dev/bd1662rate"
typedef struct CallbackJavaMethod {
int fd = -1;
JNIEnv* jniEnv;
JavaVM* javaVM;
jclass clazz;
jclass jclassRef;
pthread_t jvmThread;
pthread_t thread;
jmethodID mtd_method;
} CallbackJavaMethod, *pCallbackJavaMethod;
pthread_mutex_t mutex;
pCallbackJavaMethod javaMethod = NULL;
void *call_back(void *arg){
int arr[35] ={0};
uint16_t raw_data[200] = {0};
ALOGI("thread callback funtion\n");
pthread_mutex_lock(&mutex);
memcpy(raw_data, arg, sizeof(raw_data));
for (int i = 0; i < 35; ++i){
arr[i] = raw_data[i];
//ALOGD("call_back raw_data[%2d]:%6d raw_data[%2d]:%6d raw_data[%2d]:%6d\n", i, raw_data[i], i+35, raw_data[i+35], i+70, raw_data[i+70]);
}
if ((*(javaMethod->javaVM)).AttachCurrentThread(&javaMethod->jniEnv, NULL) < 0) {
ALOGE("AttachCurrentThread is failed");
pthread_mutex_unlock(&mutex);
pthread_detach(pthread_self());
pthread_exit(NULL);
return 0;
}
jintArray array = javaMethod->jniEnv->NewIntArray(35);
javaMethod->jniEnv->SetIntArrayRegion(array,0,35,arr);
if(javaMethod->jvmThread != pthread_self()){
javaMethod->jniEnv->CallStaticVoidMethod(javaMethod->jclassRef, javaMethod->mtd_method, array);
}
(*(javaMethod->javaVM)).DetachCurrentThread();
//javaMethod->jniEnv->DeleteLocalRef(array);
pthread_mutex_unlock(&mutex);
pthread_detach(pthread_self());
pthread_exit(NULL);
}
static void heartrate_ppg_fun(int sig){
int ret=-1;
uint16_t raw_data[200] = {0};
read(javaMethod->fd, raw_data, 200);
ret = pthread_create(&javaMethod->thread, NULL, call_back, raw_data);
if(ret != 0){
ALOGE("pthread_create is failed");
return;
}
}
static int open_file_dev(JNIEnv *env, jobject thiz)
{
uint8_t val[3] = {0x03, true};
ALOGI("open_file_dev start\n");
pthread_mutex_init(&mutex, NULL);
javaMethod =(pCallbackJavaMethod)malloc(sizeof(CallbackJavaMethod));
if(javaMethod == NULL ){
ALOGE("javaMethod malloc failed");
return -EFAULT;
}
javaMethod->fd = open(DEV_PATH ,O_RDWR);
if(javaMethod->fd < 0){
ALOGE("open : %s\n", strerror(errno));
return -1;
}
signal(SIGIO, heartrate_ppg_fun);
fcntl(javaMethod->fd, F_SETOWN, getpid());
fcntl(javaMethod->fd, F_SETFL, fcntl(javaMethod->fd, F_GETFL) | FASYNC);
(*env).GetJavaVM(&javaMethod->javaVM);
javaMethod->jniEnv = env;
javaMethod->jvmThread = pthread_self();
javaMethod->clazz = env->FindClass("com/hsc/HearTratePpg");
if(javaMethod->clazz == NULL){
ALOGE("Can't find com.hsc.heartratePpg");
goto exit;
}
javaMethod->jclassRef = (jclass)env->NewGlobalRef(javaMethod->clazz);
javaMethod->mtd_method = env->GetStaticMethodID(javaMethod->jclassRef,"CallFun","([I)V");
if(javaMethod->mtd_method == NULL){
ALOGE("mtd_method is failed");
goto exit;
}
write(javaMethod->fd, val, sizeof(val));
ALOGI("open_file_dev is successful\n");
return 0;
exit:
close(javaMethod->fd);
free(javaMethod);
javaMethod = NULL;
return -1;
}
static int close_file_dev(JNIEnv *env, jobject thiz){
uint8_t val[3] = {0x03, false};
ALOGI("thread callback funtion\n");
pthread_mutex_lock(&mutex);
write(javaMethod->fd, val, sizeof(val));
sleep(1);
close(javaMethod->fd);
env->DeleteLocalRef(javaMethod->clazz);
free(javaMethod);
javaMethod = NULL;
pthread_mutex_unlock(&mutex);
return 0;
}
static JNINativeMethod heartrate_ppg_methods[] ={
{"OpenDev", "()I", (void *)open_file_dev},
{"CloseDev", "()I", (void *)close_file_dev},
};
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
JNIEnv *env = NULL;
jclass clazz;
jint ret;
ALOGI("JNI_OnLoad start\n");
ret = vm->GetEnv((void * * )&env, JNI_VERSION_1_4);
if(ret != 0){
ALOGE("vm->GetEnv error\n");
return -1;
}
clazz = env->FindClass("com/hsc/HearTratePpg");
if(clazz == NULL){
ALOGE("env->FindClass error\n");
return -1;
}
if ((env->RegisterNatives(clazz, heartrate_ppg_methods, sizeof(heartrate_ppg_methods)/sizeof(heartrate_ppg_methods[0]))) < 0) {
ALOGE("Can not RegisterNatives\n");
return -1;
}
ALOGI("JNI_OnLoad is successful\n");
return JNI_VERSION_1_4;
}
#ifdef __cplusplus
}
#endif
2、JNI编译so库的Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := \
libcutils \
libhardware
LOCAL_MODULE_TAGS := optional
LOCAL_LDLIBS := -lm -llog
LOCAL_SRC_FILES:= heartrate_ppg.cpp
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE)
LOCAL_MODULE:= libheartrate_ppg
include $(BUILD_SHARED_LIBRARY)
3、so库公布为系统公共库
--- a/idh.code/system/core/rootdir/etc/public.libraries.android.txt
+++ b/idh.code/system/core/rootdir/etc/public.libraries.android.txt
@@ -24,4 +24,5 @@ libvulkan.so
libwebviewchromium_plat_support.so
libz.so
libjni_step.so
libjni_sensor.so
+libheartrate_ppg.so
4、Java代码:src\com\hsc\HearTratePpg.java
package com.hsc;
import android.app.Activity;
import android.text.TextUtils;
import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import android.util.Log;
//public class HearTratePpg {
public class HearTratePpg extends Activity {
private String TAG = "HearTratePpg";
public static void CallFun(int raw_data[]){
for (int i = 0; i < 35; ++i){
Log.d("helloactivity","CallFun" +"raw_data["+i+"]:"+raw_data[i]);
}
//Log.d("helloactivity","CallFun" +raw_data);
}
public static native int OpenDev();
public static native int CloseDev();
static{
System.loadLibrary("heartrate_ppg");
}
}
5、Java部分主调代码:src\com\example\android\helloactivity\HelloActivity.java
package com.example.android.helloactivity;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.WindowManager;
import com.hsc.HearTratePpg;
import android.util.Log;
/**
* A minimal "Hello, World!" application.
*/
public class HelloActivity extends Activity {
/**
* Called with the activity is first created.
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set the layout for this activity. You can find it
// in res/layout/hello_activity.xml
View view = getLayoutInflater().inflate(R.layout.hello_activity, null);
setContentView(view);
//HearTratePpg.call_lxx(1,1,1,1);
if(HearTratePpg.OpenDev() == 0)
Log.d("helloactivity","successful");
}
@Override
protected void onPause() {
HearTratePpg.CloseDev();
super.onPause();
}
}
6、JAVA部分Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := samples
# Only compile source java files in this apk.
LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := HelloActivity
LOCAL_SDK_VERSION := current
LOCAL_DEX_PREOPT := false
LOCAL_PROGUARD_ENABLED:= disabled#代码混淆后会出现回调报错
include $(BUILD_PACKAGE)
# Use the following include to make our test apk.
include $(call all-makefiles-under,$(LOCAL_PATH))