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;
        }

    }

}

点击按钮,将会看见设备上的灯亮了....

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2014-05-28 22:21  MMLoveMeMM  阅读(263)  评论(0)    收藏  举报