Android 驱动测试程序H-M-S <4>
这一节先介绍如何在jni中直接调用driver节点,下面还是点亮一盏LED为例,步骤如下:
<1> : 新建一个android应用工程,再新建一个org包,和jni文件夹,直接将前面的onLoad.h和onLoad.cpp文件拷贝过来.基本上不需要修改,因为是通用的:
onLoad.h:
#include<jni.h> #ifndef _ON_LOAD_HEADER_H__ #define _ON_LOAD_HEADER_H__ JNIEnv* getJNIEnv(); int jniThrowException(JNIEnv *env,const char* className,const char* msg); int jniRegisterNativeMethods(JNIEnv* env,const char* className,const JNINativeMethod* gMethod,int numMethods); #endif
onLoad.cpp:
#include<stdlib.h> #include<android/log.h> #include "onLoad.h" extern int register_android_jni_demo_android(JNIEnv *env); static JavaVM *sEnv; int jniThrowException(JNIEnv *env, const char* className, const char* msg) { jclass exceptionClass = env->FindClass(className); if (exceptionClass == NULL) { return -1; } if (env->ThrowNew(exceptionClass, msg) != JNI_OK) { } return 0; } JNIEnv* getJNIEnv() { JNIEnv* env = NULL; if (sEnv->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { return NULL; } return env; } int jniRegisterNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods) { jclass clazz; clazz = env->FindClass(className); if (clazz == NULL) { return -1; } if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) { return -1; } return 0; } jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint result = JNI_ERR; sEnv = vm; /*JavaVM::GetEnv 原型为 jint (*GetEnv)(JavaVM*, void**, jint); * GetEnv()函数返回的 Jni 环境对每个线程来说是不同的, * 由于Dalvik虚拟机通常是Multi-threading的。每一个线程调用JNI_OnLoad()时, * 所用的JNI Env是不同的,因此我们必须在每次进入函数时都要通过vm->GetEnv重新获取 * */ if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) { return result; } /*开始注册 * 传入参数是JNI env * 由于下面有很多class,只以register_android_media_FFMpegPlayerAndroid(env)为例子 */ if (register_android_jni_demo_android(env) != JNI_OK) { goto end; } //following could do it as the previous the way of register /*if (register_android_jni_demo_android_1(env) != JNI_OK) { goto end; } ... if (register_android_jni_demo_android_n(env) != JNI_OK) { goto end; }*/ return JNI_VERSION_1_4; end: return result; }
<2> : 调用驱动的写在openDriver.cpp文件中:
#include "onLoad.h" #include<android/log.h> #include<jni.h> #include<fcntl.h> #include<stdio.h> #include<stdlib.h> #define TAG "OPEN_DRIVER" #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)) #define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN,TAG,__VA_ARGS__)) #define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)) #define DEVICE_NAME "/sys/devices/platform/leds-gpio/leds/gpio-led3/brightness" #define CLASS_PACKAGE_NAME "org/controlLed" namespace android{ void setLedon(){ int fd=-1; int val=0; char ctrl[2]="0"; fd=open(DEVICE_NAME,O_RDWR); if(fd==-1){ return; } // write(fd,ctrl,sizeof(ctrl)); write(fd,ctrl,1); close(fd); } int getLibVersion(){ return 1; } } using namespace android; static JNINativeMethod mNativeMethod[]={ { "control_led3","()V",(void*)setLedon }, { "getLibraryVersion","()I",(void*)getLibVersion } }; int register_android_jni_demo_android(JNIEnv* env){ return jniRegisterNativeMethods(env,CLASS_PACKAGE_NAME,mNativeMethod,sizeof(mNativeMethod)/sizeof(mNativeMethod[0])); }
<3> : 对应脚本文件:
Android.mk :
LOCAL_PATH:=$(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:=controlledlib LOCAL_SRC_FILES:=onLoad.cpp openDriver.cpp LOCAL_SHARED_LIBRARY := libnativehelper liblog LOCAL_LDLIBS:= -llog include $(BUILD_SHARED_LIBRARY)
<4> : 然后在android工程下新建的org包下新建controlLed.java:
package org; public class controlLed { static{ System.loadLibrary("controlledlib"); } public controlLed(){ } public native void control_led3(); public native int getLibraryVersion(); }
<5> : 在具体app工程的调用:
package com.example.androidopendriverdemo; import org.controlLed; import android.os.Bundle; import android.app.Activity; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.Toast; public class MainActivity extends Activity implements OnClickListener { private Button mCtrlBtn; private Button mLibVerBtn; private controlLed mCtrl; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mCtrlBtn = (Button) findViewById(R.id.ctrl); mCtrlBtn.setOnClickListener(this); mLibVerBtn = (Button) findViewById(R.id.version); mLibVerBtn.setOnClickListener(this); mCtrl = new controlLed(); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public void onClick(View arg0) { // TODO Auto-generated method stub int id = arg0.getId(); switch (id) { case R.id.ctrl: mCtrl.control_led3(); break; case R.id.version: Toast.makeText(this, "library version : " + mCtrl.getLibraryVersion(), Toast.LENGTH_SHORT).show(); break; } } }
点击按钮,将会看见设备上的灯亮了....