一、前言
众所周知,android系统不能直接控制底层硬件,像单片机那样简单的点个LED灯对于安卓系统来说可没那么简单,那么它是用什么方式来操作底层接口呢?本文对此一一进行探讨。
二、JNI是Android操作底层的利器
JNI是Java Native Interface的缩写,中文为Java本地调用。
Native方法一般用于两种情况:
1)在方法中调用一些不是由java语言写的代码。对于android来说就是C/C++。
2)在方法中用java语言直接操纵计算机硬件。对于android系统底层而已就是linux底层,通过linux C读写操作设备文件dev或者sys文件。
一般android操作硬件的流程是:app ==> JNI ==> linux硬件驱动 ==> 硬件。
三、android系统下的JNI格式。
下面以一个buzzer蜂鸣器的控制为例子演示一下android到底是如何使用jni的。
这个jni总共有三个源文件:com_topeet_buzzertest_buzzer.c ,com_topeet_buzzertest_buzzer.h, Android.mk。其中Android.mk其实就是android下面的Makefile。
1.Android.mk文件的内容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := buzzer
LOCAL_SRC_FILES := com_topeet_buzzertest_buzzer.c
LOCAL_LDLIBS += -llog
LOCAL_LDLIBS +=-lm
include $(BUILD_SHARED_LIBRARY)
2.com_topeet_buzzertest_buzzer.c 的文件内容如下:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdint.h>
#include <termios.h>
#include <android/log.h>
#include <sys/ioctl.h>
#include "com_topeet_buzzertest_buzzer.h"
#undef TCSAFLUSH
#define TCSAFLUSH TCSETSF
#ifndef _TERMIOS_H_
#define _TERMIOS_H_
#endif
int fd=0;
/*
* Class: com_topeet_buzzertest_buzzer
* Method: Open
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_topeet_buzzertest_buzzer_Open
(JNIEnv *env, jobject obj)
{
if(fd<=0)fd = open("/dev/buzzer_ctl", O_RDWR|O_NDELAY|O_NOCTTY);
if(fd <=0 )__android_log_print(ANDROID_LOG_INFO, "serial", "open /dev/buzzer_ctl Error");
else __android_log_print(ANDROID_LOG_INFO, "serial", "open /dev/buzzer_ctl Sucess fd=%d",fd);
}
/*
* Class: com_topeet_buzzertest_buzzer
* Method: Close
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_topeet_buzzertest_buzzer_Close
(JNIEnv *env, jobject obj)
{
if(fd > 0)close(fd);
}
/*
* Class: com_topeet_buzzertest_buzzer
* Method: Ioctl
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_topeet_buzzertest_buzzer_Ioctl
(JNIEnv *env, jobject obj, jint num, jint en)
{
ioctl(fd, en, num);
}
3.com_topeet_buzzertest_buzzer.h的文件内容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_neojet_scanner_key */
#ifndef _Included_com_topeet_buzzertest_buzzer
#define _Included_com_topeet_buzzertest_buzzer
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_topeet_buzzertest_buzzer
* Method: Open
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_topeet_buzzertest_buzzer_Open
(JNIEnv *, jobject);
/*
* Class: com_topeet_buzzertest_buzzer
* Method: Close
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_topeet_buzzertest_buzzer_Close
(JNIEnv *, jobject);
/*
* Class: com_topeet_buzzertest_buzzer
* Method: Ioctl
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_topeet_buzzertest_buzzer_Ioctl
(JNIEnv *, jobject, jint num, jint en);
#ifdef __cplusplus
}
#endif
#endif