Android驅動使用JNI調用
學習Android驅動是一個漫長的過程,當然你也可以說有了Linux裝置驅動開發經驗學習Android驅動是很簡單的,呵呵,的卻如此,畢竟Android核心是跑在linux核心上,Android的應用調用的其實是linux驅動。Android Application調用Linux驅動可以這麼說有兩種方法,也就是兩種處理的流程。
Android應用程式層調用Linux驅動的方式:
第一,通過在Android核心源碼(不是linux核心源碼)中添加HAL層、JNI層、開啟系統服務,這是一個比較複雜的過程,很多標準的裝置都採用這種方式設計,比如說wifi、gps、sensor等,這種調用過程看起來比較標準,但是如果作為第三方開發就會很麻煩,HAL層、JNI層,系統服務層,每層都需要編譯Android核心源碼,這樣就會延長了產品的開發週期;第二,通過配置NDK環境,在NDK環境中直接編寫JNI層,然後在Android應用程式層中添加類,載入JNI庫即可調用裝置的驅動。
現在我們以Tiny210上的LED驅動作為例子講解如何使用NDK環境編寫JNI庫來調用裝置的驅動程式。
一、首先是編寫linux驅動程式,:
1、源碼:linux-2.6.36-android\drivers\char\tiny210_leds.c
2、修改目前的目錄(linux-2.6.36-android\drivers\char)的kconfig,添加如下內容:
config TINY210_LEDS
tristate "LED Support for Tiny210 GPIO LEDs"
depends on CPU S5PV210
default y
help
This option enables support for LEDs connected to GPIO lines
on Tiny210 boards.
3、修改目前的目錄(linux-2.6.36-android\drivers\char)下的makefile檔案,添加如下內容:
obj-$(CONFIG_TINY210_LEDS) += tiny210_leds.o
4、到源碼目錄執行make menuconfig 配置LED驅動編譯進核心,系統起來就載入驅動
5、執行 make 產生zImage鏡像檔案
二、 重新使用剛剛編譯好的zImage燒寫Android系統,系統起來以後通過adb查看Android系統載入的驅動程式
#ls /dev
可以看到系統載入的驅動,(leds)
修改init.rc載入的驅動的讀寫權限
chmod 0666 /dev/leds
這樣JNI層才可以開啟這個裝置
三、編寫JNI檔案
在android工程目錄下建立檔案jni,然後添加檔案ledjni.c,內容如下:
#include <string.h>
#include <jni.h>
#include <fcntl.h>
#define DEV_NAME "/dev/leds"
jstring
Java_com_hellojnipwzh_HardwareControlClass_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
jint
Java_com_hellojnipwzh_HardwareControlClass_Init(JNIEnv *env,
jobject thiz)
{
int fd=open(DEV_NAME,O_RDWR);
return fd;
}
jint
Java_com_hellojnipwzh_HardwareControlClass_IOCTLLED(JNIEnv *env,
jobject thiz,
jint ledid,
jint controlcode,
jint fd)
{
int CTLCODE = controlcode;
ioctl(fd,controlcode,ledid);
return 0;
}
說明:“Java_com_hellojnipwzh_HardwareControlClass_IOCTLLED”,在工程中添加JNI類時,使用com.hellojnipwzh作為packets name,HardwareControlClass這個作為class name ,IOCTLLED(int id,int code,int fd)作為調用的介面函數,類成員。
添加指令碼Android.mk,內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ledjni
LOCAL_SRC_FILES := ledjni.c
include $(BUILD_SHARED_LIBRARY)
使用Cygwin工具,配置好NDK環境,添加NDK環境到系統變數中,然後進到jni目錄,進行
#ndk-build
這樣就會在android工程的libs目錄下的armeabi目錄下產生ledjni.so
這樣JNI庫已經完成了,接下來就是添加類來調用JNI庫
四、JNI類
在Android工程中添加一個類,包名:com.hellojnipwzh 類名:HardwareControlClass,具體內容如下:
package com.hellojnipwzh;
import android.util.Log;
public class HardwareControlClass {
static public native String stringFromJNI();
static public native int Init();
static public native int IOCTLLED(int ledID, int ledState ,int fd);
static {
try {
System.loadLibrary("ledjni");
} catch (UnsatisfiedLinkError e) {
Log.d("HardwareControler", "HardwareControler ibrary not found!");
}
}
}
五、接下來就是在Android應用程式層代碼中通過類來訪問驅動了
package com.hellojnipwzh;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
public class HelloJniPwzh extends Activity {
int fd = -1;
TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello_jni_pwzh);
fd = HardwareControlClass.Init();
if (-1 == fd)
Log.d("JNI", "open device error!");
tv = (TextView)findViewById(R.id.tvid);
String tstr = "ssss";
tstr = HardwareControlClass.stringFromJNI();
tv.setText(tstr);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_hello_jni_pwzh, menu);
return true;
}
public void onclickLedOn1(View v)
{
if (fd != -1)
HardwareControlClass.IOCTLLED(1, 1, fd);
}
public void onclickLedOff1(View v)
{
if (fd != -1)
HardwareControlClass.IOCTLLED(1, 0, fd);
}
public void onclickLedOn2(View v)
{
if (fd != -1)
HardwareControlClass.IOCTLLED(2, 1, fd);
}
public void onclickLedOff2(View v)
{
if (fd != -1)
HardwareControlClass.IOCTLLED(2, 0, fd);
}
public void onclickLedOn3(View v)
{
if (fd != -1)
HardwareControlClass.IOCTLLED(3, 1, fd);
}
public void onclickLedOff3(View v)
{
if (fd != -1)
HardwareControlClass.IOCTLLED(3, 0, fd);
}
public void onclickLedOn4(View v)
{
if (fd != -1)
HardwareControlClass.IOCTLLED(4, 1, fd);
}
public void onclickLedOff4(View v)
{
if (fd != -1)
HardwareControlClass.IOCTLLED(4, 0, fd);
}
}
至此JNI的調用過程也已經完成,接下來就是將Android軟體安裝到Tiny210上,然後點擊下按鈕,你就會發現你可以通過Android軟體來控制Linux驅動程式了。