Android JNI 显示注册实例

显示注册native function有两种方法,这里是其中一种,更多参考:http://blog.csdn.net/thinkinwm/article/details/8637238


使用JNIHelp.h头文件中定义的jniRegisterNativeMethods来注册,jniRegisterNativeMethods和NELEM都是在头文件JNIHelp.h定义的,在CPP中得:

[plain]  view plain copy
  1. #include "JNIHelp.h"  

在Android.mk文件中得加上:

[plain]  view plain copy
  1. LOCAL_SHARED_LIBRARIES +=libnativehelper   


代码位置: frameworks\base\services\jni

Android.mk 

LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:= \
    com_android_server_AlarmManagerService.cpp \
    com_android_server_BatteryService.cpp \
    com_android_server_input_InputApplicationHandle.cpp \
    com_android_server_input_InputManagerService.cpp \
    com_android_server_input_InputWindowHandle.cpp \
    com_android_server_LightsService.cpp \
    com_android_server_PowerManagerService.cpp \
    com_android_server_SerialService.cpp \
    com_android_server_SystemServer.cpp \
    com_android_server_UsbDeviceManager.cpp \
    com_android_server_UsbHostManager.cpp \
    com_android_server_VibratorService.cpp \
    com_android_server_location_GpsLocationProvider.cpp \
    com_android_server_connectivity_Vpn.cpp \
    onload.cpp

LOCAL_C_INCLUDES += \
    $(JNI_H_INCLUDE) \
    frameworks/base/services \
    frameworks/base/core/jni \
    external/skia/include/core \
    libcore/include \
    libcore/include/libsuspend \
	$(call include-path-for, libhardware)/hardware \
	$(call include-path-for, libhardware_legacy)/hardware_legacy \

LOCAL_SHARED_LIBRARIES := \
    libandroid_runtime \
    libandroidfw \
    libcutils \
    libhardware \
    libhardware_legacy \
    libnativehelper \
    libsystem_server \
    libutils \
    libui \
    libinput \
    libskia \
    libgui \
    libusbhost \
    libsuspend

ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
    LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK
endif

LOCAL_MODULE:= libandroid_servers

include $(BUILD_SHARED_LIBRARY)



当程序在java层运行System.loadLibrary("jnitest");这行代码后,程序会去载入libjnitest.so文件,与此同时,产生一个"Load"事件,这个事件触发后,程序默认会在载入的.so文件的函数列表中查找JNI_OnLoad函数并执行,与"Load"事件相对,当载入的.so文件被卸载时,“Unload”事件被触发,此时,程序默认会去在载入的.so文件的函数列表中查找JNI_OnUnload函数并执行,然后卸载.so文件。需要注意的是,JNI_OnLoad与JNI_OnUnload这两个函数在.so组件中并不是强制要求的,用户也可以不去实现。之所以在C组件中去实现这两个函数(特别是JNI_OnLoad函数),往往是做一个初始化工作或“善后”工作。可以这样认为,将JNI_ONLoad看成是.so组件的初始化函数,当其第一次被装载时被执行(window下的dll文件也可类似的机制,在_DLL_Main()函数中,通过一个swith case语句来识别当前是载入还是卸载)。将JNI_OnUnload函数看成是析构函数,当其被卸载时被调用。

onload.cpp

#include "JNIHelp.h"
#include "jni.h"
#include "utils/Log.h"
#include "utils/misc.h"

namespace android {
int register_android_server_AlarmManagerService(JNIEnv* env);
int register_android_server_BatteryService(JNIEnv* env);
int register_android_server_InputApplicationHandle(JNIEnv* env);
int register_android_server_InputWindowHandle(JNIEnv* env);
int register_android_server_InputManager(JNIEnv* env);
int register_android_server_LightsService(JNIEnv* env);
int register_android_server_PowerManagerService(JNIEnv* env);
int register_android_server_SerialService(JNIEnv* env);
int register_android_server_UsbDeviceManager(JNIEnv* env);
int register_android_server_UsbHostManager(JNIEnv* env);
int register_android_server_VibratorService(JNIEnv* env);
int register_android_server_SystemServer(JNIEnv* env);
int register_android_server_location_GpsLocationProvider(JNIEnv* env);
int register_android_server_connectivity_Vpn(JNIEnv* env);
};

using namespace android;

extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    JNIEnv* env = NULL;
    jint result = -1;

    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        ALOGE("GetEnv failed!");
        return result;
    }
    ALOG_ASSERT(env, "Could not retrieve the env!");

    register_android_server_PowerManagerService(env);
    register_android_server_SerialService(env);
    register_android_server_InputApplicationHandle(env);
    register_android_server_InputWindowHandle(env);
    register_android_server_InputManager(env);
    register_android_server_LightsService(env);
    register_android_server_AlarmManagerService(env);
    register_android_server_BatteryService(env);
    register_android_server_UsbDeviceManager(env);
    register_android_server_UsbHostManager(env);
    register_android_server_VibratorService(env);
    register_android_server_SystemServer(env);
    register_android_server_location_GpsLocationProvider(env);
    register_android_server_connectivity_Vpn(env);

    return JNI_VERSION_1_4;
}


JNI_Onload会调用register_android_server_PowerManagerService函数,最终会呼叫jniRegisterNativeMethods来注册native函数

com_android_server_AlarmManagerService.cpp

#define LOG_TAG "AlarmManagerService"

#include "JNIHelp.h"
#include "jni.h"
#include <utils/Log.h>
#include <utils/misc.h>

#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <linux/ioctl.h>
#include <linux/android_alarm.h>

namespace android {

static jint android_server_AlarmManagerService_setKernelTimezone(JNIEnv* env, jobject obj, jint fd, jint minswest)
{
    struct timezone tz;

    tz.tz_minuteswest = minswest;
    tz.tz_dsttime = 0;

    int result = settimeofday(NULL, &tz);
    if (result < 0) {
        ALOGE("Unable to set kernel timezone to %d: %s\n", minswest, strerror(errno));
        return -1;
    } else {
        ALOGD("Kernel timezone updated to %d minutes west of GMT\n", minswest);
    }

    return 0;
}

static jint android_server_AlarmManagerService_init(JNIEnv* env, jobject obj)
{
    return open("/dev/alarm", O_RDWR);
}

static void android_server_AlarmManagerService_close(JNIEnv* env, jobject obj, jint fd)
{
	close(fd);
}

static void android_server_AlarmManagerService_set(JNIEnv* env, jobject obj, jint fd, jint type, jlong seconds, jlong nanoseconds)
{
    struct timespec ts;
    ts.tv_sec = seconds;
    ts.tv_nsec = nanoseconds;

	int result = ioctl(fd, ANDROID_ALARM_SET(type), &ts);
	if (result < 0)
	{
        ALOGE("Unable to set alarm to %lld.%09lld: %s\n", seconds, nanoseconds, strerror(errno));
    }
}

static jint android_server_AlarmManagerService_waitForAlarm(JNIEnv* env, jobject obj, jint fd)
{
	int result = 0;

	do
	{
		result = ioctl(fd, ANDROID_ALARM_WAIT);
	} while (result < 0 && errno == EINTR);

	if (result < 0)
	{
        ALOGE("Unable to wait on alarm: %s\n", strerror(errno));
        return 0;
    }

    return result;
}

static JNINativeMethod sMethods[] = {
     /* name, signature, funcPtr */
	{"init", "()I", (void*)android_server_AlarmManagerService_init},
	{"close", "(I)V", (void*)android_server_AlarmManagerService_close},
	{"set", "(IIJJ)V", (void*)android_server_AlarmManagerService_set},
    {"waitForAlarm", "(I)I", (void*)android_server_AlarmManagerService_waitForAlarm},
    {"setKernelTimezone", "(II)I", (void*)android_server_AlarmManagerService_setKernelTimezone},
};

int register_android_server_AlarmManagerService(JNIEnv* env)
{
    return jniRegisterNativeMethods(env, "com/android/server/AlarmManagerService",
                                    sMethods, NELEM(sMethods));
}

} /* namespace android */




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值