Android APK通过JNI直接与底层互相调用

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))

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值