JNI的方法的注册-在_onload文件中进行注册

JNI方法的声明

  • 在Java代码中声明native方法。以下
import java.util.concurrent.atomic.AtomicBoolean;

public class FaceDtr {

    private static final String TAG = "FaceDtr";
    private static final String LIBRARY = "facedetection";

    private static boolean isLoaded;

    static {
        if (!isLoaded) {
            System.loadLibrary(LIBRARY);
            isLoaded = true;
        }
    }


    private static FaceDtr mFaceDtr = new FaceDtr();
    private volatile AtomicBoolean mIsInitFaceDtrSuccess = new AtomicBoolean(false);

    private FaceDtr() {
    }
    //native method ======start======
    private static final native int nativeSendStream(byte[] buffer, int timeout);
    //native method ======end======
}
  • 建立_onload.h头文件
    声明JNI_Onload(JavaVM *vm,void*reserved)方法。以下:
#ifndef ONLOAD_H_
#define ONLOAD_H_

#pragma interface

#include <jni.h>

#ifdef __cplusplus
extern "C" {
#endif

jint JNI_OnLoad(JavaVM *vm, void *reserved);

#ifdef __cplusplus
}
#endif
#endif
  • 建立_onload.cpp文件
    导入_onload.h头文件,实现JNI_Onload方法
#include "_onload.h"
#define LOCAL_DEBUG 0

extern int register_libFaceDtr(JNIEnv *env);

jint JNI_OnLoad(JavaVM *vm, void *reserved) {
#if LOCAL_DEBUG
    LOGD("JNI_OnLoad");
#endif

    JNIEnv *env;
    if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return JNI_ERR;
    }
    // register native methods
    int result = register_libFaceDtr(env);
    setVM(vm);
#if LOCAL_DEBUG
    LOGD("JNI_OnLoad:finshed:result=%d", result);
#endif
    return JNI_VERSION_1_6;
}
  • 建立与FaceDtr中native方法对应的c/cpp文件face_dtr_jni.cpp。文件内容以下:
#include <jni.h>
#include <libusb/libusb/libusbi.h>
__attribute__((section (".mytext"))) static static int
nativeSendStream(JNIEnv *env, jobject thiz, jbyteArray byteArray, int timeout) {
    if (mFaceDtr == NULL || mFaceDtr->mFaceDtrDev == NULL) {
        LOGE("facedtr not init");
        return -1;
    }
    if (byteArray == NULL) {
        LOGE("Byte array is null");
        return -1;
    }
    jsize length = env->GetArrayLength(byteArray);
    if (length == 0) {
        LOGE("Byte array is empty");
        return -1;
    }
    jbyte *jbuffer = env->GetByteArrayElements(byteArray, NULL);
    int len = 0;
    int result = libusb_bulk_transfer(mFaceDtr->mFaceDtrDev->handle,
                                      mFaceDtr->mFaceDtrDev->bulk_endpoint_out,
                                      (unsigned char *) jbuffer, length,
                                      &len,
                                      timeout);
    if (jbuffer != NULL) {
        env->ReleaseByteArrayElements(byteArray, jbuffer, JNI_ABORT);
        env->DeleteLocalRef(byteArray);
    }
    env->DeleteLocalRef(byteArray);
    if (result != LIBUSB_SUCCESS) {
        len = -1;
    }
    return len;

}


static JNINativeMethod methods[] = {
        {"nativeSendStream",               "([BI)I",                     (void *) nativeSendStream},
};

jint registerNativeMethods(JNIEnv *env, const char *class_name, JNINativeMethod *methods,
                           int num_methods) {
    int result = 0;

    jclass clazz = env->FindClass(class_name);
    if (LIKELY(clazz)) {
        int result = env->RegisterNatives(clazz, methods, num_methods);
        if (UNLIKELY(result < 0)) {
            LOGE("registerNativeMethods failed(class=%s)", class_name);
        }
    } else {
        LOGE("registerNativeMethods: class'%s' not found", class_name);
    }
    return result;
}

int register_libFaceDtr(JNIEnv *env) {
    LOGV("register_libfacedtr:");
    if (registerNativeMethods(env,
                              "com/xxx/xx/FaceDtr",
                              methods, NUM_ARRAY_ELEMENTS(methods)) < 0) {
        return -1;
    }
    return 0;
}
  • 在Android.mk文件中注册代码
# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_C_INCLUDES := \
        $(LOCAL_PATH)/ \
        $(LOCAL_PATH)/../ \

LOCAL_MODULE    := facedetection

LOCAL_CFLAGS := -fvisibility=hidden

LOCAL_LDLIBS +=  -llog
LOCAL_SRC_FILES := \
        _onload.cpp \
        face_dtr_jni.cpp \
include $(BUILD_SHARED_LIBRARY)
  • 在build.gradle 目录中声明ndk编译支持的版本
android{
···
defaultConfig {
        minSdkVersion versionMinTarget
        targetSdkVersion versionTarget
        externalNativeBuild { 
            ndkBuild {
                arguments "NDK_APPLICATION_MK:=src/main/jni/Application.mk"
                cFlags "-DTEST_C_FLAG1", "-DTEST_C_FLAG2"
                cppFlags "-DTEST_CPP_FLAG2", "-DTEST_CPP_FLAG2"
                abiFilters  "armeabi", "x86" ,"arm64-v8a" //编译的版本
            }
        }
    }

    externalNativeBuild {
        ndkBuild {
            path 'src/main/jni/Android.mk'
        }
    }
 }
 ···