zoukankan      html  css  js  c++  java
  • mini6410-JNI-led

    一、编写JNI模块

    当安装好NDK编译环境后,会在它的目录下找到sample目录,它里面有一些例子,可以参考这些例子来写我们自已的模块。

     

    1在/home/android/文件夹下,新建“ledjni”文件夹。

    2/ledjni/jni/目录下,新建“led-jni.c”

    led-jni.c文件

     

    1. #include <stdio.h>  
    2. #include <string.h>  
    3. #include <jni.h>  
    4. #include <fcntl.h> /*包括文件操作,如open() read() close()write()等*/  
    5. #include <android/log.h>  
    6. #define LOG_TAG "led-jni"  
    7.   
    8. #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)  
    9. #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)  
    10.   
    11. #define DEVICE_NAME "/dev/led_by_wenhui" //device point  
    12. //#define DEVICE_NAME "/dev/leds" //device point  
    13. //#define DEVICE_NAME "/dev/led_" //device point  
    14. #define LED_ON  1  
    15. #define LED_OFF 0  
    16.   
    17. int fd;  
    18.   
    19. jstring Java_com_auly_control_ledClass_stringFromJNI( JNIEnv* env, jobject thiz )  
    20. {  
    21.         return (*env)->NewStringUTF(env, "This is wenhui project ,Hello from JNI !");  
    22. }  
    23.   
    24. jint Java_com_auly_control_ledClass_Init( JNIEnv* env)  
    25. {  
    26.         LOGE("LEDclass_Init() ");  
    27.         fd = open(DEVICE_NAME, 0);  
    28.         LOGE("LEDclass_Init()-> fd = %d  ", fd);  
    29.         if (fd < 0){  
    30.             LOGE("open device %s error  ", DEVICE_NAME);  
    31.             return 0;  
    32.         }  
    33.           
    34.         return 1;  
    35. }  
    36.   
    37. jint Java_com_auly_control_ledClass_IOCTL( JNIEnv* env, jobject thiz , jint ledID, jint ledState)  
    38. {  
    39.       LOGE("IOCTL()-> %d ledState  ",ledState);  
    40.       LOGE("IOCTL()-> %d ledState  ",0);  
    41.       ioctl(fd,ledState, NULL);  
    42.             return 1;  
    43. }  
    44.   
    45. jint Java_com_auly_control_ledClass_CLOSE( JNIEnv* env, jobject thiz )  
    46. {  
    47.         close(fd);  
    48.         return 1;  
    49. }  
    #include <stdio.h>
    #include <string.h>
    #include <jni.h>
    #include <fcntl.h> /*包括文件操作,如open() read() close()write()等*/
    #include <android/log.h>
    #define LOG_TAG "led-jni"
    
    #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
    #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
    
    #define DEVICE_NAME "/dev/led_by_wenhui" //device point
    //#define DEVICE_NAME "/dev/leds" //device point
    //#define DEVICE_NAME "/dev/led_" //device point
    #define LED_ON  1
    #define LED_OFF 0
    
    int fd;
    
    jstring Java_com_auly_control_ledClass_stringFromJNI( JNIEnv* env, jobject thiz )
    {
    	    return (*env)->NewStringUTF(env, "This is wenhui project ,Hello from JNI !");
    }
    
    jint Java_com_auly_control_ledClass_Init( JNIEnv* env)
    {
    		LOGE("LEDclass_Init()
    ");
    		fd = open(DEVICE_NAME, 0);
    		LOGE("LEDclass_Init()-> fd = %d 
    ", fd);
    		if (fd < 0){
    			LOGE("open device %s error 
    ", DEVICE_NAME);
    			return 0;
    		}
    		
    		return 1;
    }
    
    jint Java_com_auly_control_ledClass_IOCTL( JNIEnv* env, jobject thiz , jint ledID, jint ledState)
    {
    	  LOGE("IOCTL()-> %d ledState 
    ",ledState);
    	  LOGE("IOCTL()-> %d ledState 
    ",0);
    	  ioctl(fd,ledState, NULL);
    		    return 1;
    }
    
    jint Java_com_auly_control_ledClass_CLOSE( JNIEnv* env, jobject thiz )
    {
    		close(fd);
    	    return 1;
    }
    

    3、相同目录下的新建Android.mk如下

    Android.mk文件

    1. LOCAL_PATH := $(call my-dir)  
    2.   
    3. include $(CLEAR_VARS)  
    4.   
    5. LOCAL_MODULE    :led-jni  
    6. LOCAL_SRC_FILES :led-jni.c  
    7. LOCAL_CFLAGS := -Werror  
    8. LOCAL_LDLIBS := -llog -lGLESv2  
    9.   
    10. include $(BUILD_SHARED_LIBRARY)  
    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE    := led-jni
    LOCAL_SRC_FILES := led-jni.c
    LOCAL_CFLAGS := -Werror
    LOCAL_LDLIBS := -llog -lGLESv2
    
    include $(BUILD_SHARED_LIBRARY)
    



    可以看到,主要是修改LOCAL_SRC_FILES指向源文件的名称!

    还有一点很重要,如果要使用调试LOG打印,也就是__android_log_print函数。要在LOCAL_LDLIBS中添加-llog,如上面的Android.mk所示。

    4、编译JNI模块

    #cd /home/android/ledjni

    进到刚才写的JNI目录

    #ndk-build

    编译JNI,编译成功后,会在ledjni文件夹下生成libsobj两个文件夹,并在

    ledjni/libs/armeabi下得到目标文件libled-jni.so

     

    (目前ledjni文件夹只有3个目录jni,libs,obj

     

    二、JAVA程序

    1Eclipse新建工程 LEDAPP

          注意   Location: 选刚才的 ledjni

     

     

    然后 Runas > Android application,就会出现android的模拟器了,里面跑个helloworld出来。

     

    2、加入button和文本输出

    程序到上面为止代码是ADT自动生成的,似乎与我们一点关系也没有。那我们来改一下代码,因为我们调用JNI接口是为了访问驱动程序操作硬件的,例如写,读,打开LED,关闭LED等等,由按钮触发的动作。

    第一步是,增加两个Button,,在main.xml里描述一下:打开Res> layout> main.xml 文件

    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    3.     android:orientation="vertical"  
    4.     android:layout_width="fill_parent"  
    5.     android:layout_height="fill_parent"  
    6.     >  
    7. <TextView    
    8.     android:layout_width="fill_parent"   
    9.     android:layout_height="wrap_content"   
    10.     android:text="@string/hello"  
    11.     />  
    12.       
    13. <Button android:id="@+id/led_on"  
    14.     android:layout_width="wrap_content"  
    15.     android:layout_height="wrap_content"  
    16.     android:text="@string/LEDon"  
    17.     />  
    18.       
    19.       
    20. <Button android:id="@+id/led_off"  
    21.     android:layout_width="wrap_content"  
    22.     android:layout_height="wrap_content"  
    23.     android:text="@string/LEDoff"  
    24.     />  
    25.       
    26. </LinearLayout>  
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
    <TextView  
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:text="@string/hello"
        />
        
    <Button android:id="@+id/led_on"
    	android:layout_width="wrap_content"
     	android:layout_height="wrap_content"
     	android:text="@string/LEDon"
     	/>
        
        
    <Button android:id="@+id/led_off"
    	android:layout_width="wrap_content"
    	android:layout_height="wrap_content"
    	android:text="@string/LEDoff"
    	/>
    	
    </LinearLayout>
    

    实际代码中,把注释去掉,否则编译不过的。

    3、加入输出字符串资源

    工程 >values > strings.xml文件

     

    修改如下

    <?xmlversion=
    "1.0"encoding="utf-8"?>
    <resources>
    <stringname=
    "hello">Led
    控制程序</string>
    <stringname=
    "app_name">LEDAPP</string>
    <stringname=
    "LEDon">
    打开LED</string>
    <stringname=
    "LEDoff">
    关闭LED</string>
    </resources>

    上面的”打开LED”等资源,就是用在按钮上显示出来的字符串

    经过上面的修改,现在程序界面上,已经有如下效果了

    鼠标右键工程名>Runas > Android application运行程序。

     

    4、加入按钮对应的动作

    关闭LED”按钮:

    打开LED”按扭:调用JNIIOCTL(int ledID, int ledState);

    操作:

    LEDAPP> src > com.auly.control >LEDAPPActivity.java文件

     

     

    1. package com.auly.control;  
    2.   
    3. import android.app.Activity;  
    4. import android.os.Bundle;  
    5. import android.view.View;  
    6. import android.view.View.OnClickListener;  
    7. import android.widget.Button;  
    8.   
    9. public class LEDAPPActivity extends Activity {  
    10.     /** Called when the activity is first created. */  
    11.     //定义变量  
    12.     public static final int LED_ON = 0X01;  
    13.     public static final int LED_OFF = 0x00;  
    14.     private  Button btn1 = null;  
    15.     private  Button btn2 = null;  
    16.       
    17.     //定义类  
    18.     ledClass myledclass;  
    19.   
    20.     @Override  
    21.     protected void onCreate(Bundle savedInstanceState) {  
    22.         // TODO Auto-generated method stub  
    23.         super.onCreate(savedInstanceState);  
    24.           
    25.         //初始化   
    26.         setContentView(R.layout.main);   
    27.         myledclass = new ledClass();   //声明类  
    28.         myledclass.Init();             //调用JNI库里的初始化函数   
    29.           
    30.         //按钮 打开 led  
    31.         btn1 = (Button)findViewById(R.id.led_on);  
    32.         btn1.setOnClickListener(new MyBtn1Listener());  //捆绑监听器  
    33.           
    34.         //按钮 关闭 led   
    35.         btn2 = (Button)findViewById(R.id.led_off);  
    36.         btn2.setOnClickListener(new MyBtn2Listener());  //捆绑监听器        
    37.     }  
    38.       
    39.     class MyBtn1Listener implements OnClickListener {  
    40.         @Override  
    41.         public void onClick(View v) {  
    42.             myledclass.Init();  
    43.             System.out.println("debug LED_ON");  
    44.             myledclass.IOCTL(0,LED_ON);  
    45.         }  
    46.     }  
    47.       
    48.     class MyBtn2Listener implements OnClickListener {  
    49.         @Override  
    50.         public void onClick(View v) {  
    51.             System.out.println("debug LED_OFF");  
    52.             myledclass.IOCTL(0,LED_OFF);  
    53.             myledclass.CLOSE();  
    54.         }  
    55.     }  
    56. }  
    package com.auly.control;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    
    public class LEDAPPActivity extends Activity {
        /** Called when the activity is first created. */
    	//定义变量
    	public static final int LED_ON = 0X01;
    	public static final int LED_OFF = 0x00;
        private  Button btn1 = null;
        private  Button btn2 = null;
    	
        //定义类
    	ledClass myledclass;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		// TODO Auto-generated method stub
    		super.onCreate(savedInstanceState);
    		
    		//初始化 
    		setContentView(R.layout.main); 
    		myledclass = new ledClass();   //声明类
            myledclass.Init();             //调用JNI库里的初始化函数 
            
            //按钮 打开 led
            btn1 = (Button)findViewById(R.id.led_on);
            btn1.setOnClickListener(new MyBtn1Listener());  //捆绑监听器
            
            //按钮 关闭 led 
            btn2 = (Button)findViewById(R.id.led_off);
            btn2.setOnClickListener(new MyBtn2Listener());  //捆绑监听器      
    	}
    	
    	class MyBtn1Listener implements OnClickListener {
        	@Override
        	public void onClick(View v) {
        		myledclass.Init();
        		System.out.println("debug LED_ON");
    			myledclass.IOCTL(0,LED_ON);
        	}
        }
    	
    	class MyBtn2Listener implements OnClickListener {
        	@Override
        	public void onClick(View v) {
        		System.out.println("debug LED_OFF");
    			myledclass.IOCTL(0,LED_OFF);
    			myledclass.CLOSE();
        	}
        }
    }

    5、添加类ledClass

    鼠标右键com.auly.control> new > Class

     

    填参数:

     

    Finish后,在/src/com/auly/control/得到如下的类文件

    ledClass.java

    修改如下

    package com.auly.control;

    public class ledClass {
        /*声明函数*/
        //初始化函数 对应 JNI 里面的 jint Java_com_auly_control_ledClass_Init( JNIEnv* env) 函数 以下的同理
        public native int Init();
        public native int IOCTL(int ledID, int ledState);
        public native String stringFromJNI();
        public native int CLOSE();
        static{
            System.loadLibrary("led-jni");/*加载JNI库*/
        }
    }

    三、 编译运行

    鼠标右键工程名,弹出菜单,选择 Runas > Android Application就可以看到编译过程,编译完成后,会自动调用android模拟器,看到界面效果

     

    安装到开发板:(方式有多种 adb ) 或直接用u盘拷贝(这样调试比较麻烦)

    LEDSJNI目录下,会看到bin文件夹,里面的LEDAPP.apk就是这个程序的安装文件,可以把它安装的开发板上,运行本程序,看控制开发板上的LED灯的效果。

    注意!运行前 要修改的驱动节点的权限

    #chmod777 /dev/vib

         这是为了使得led_by_wenhui这个节点可以被我们写的JNI操作,不然会open失败的,因为APK安装的JNI模块,权限不够,这个节点是我们的LED驱动生成的控制节点。

    也可以在android文件系统yaffs编译时,通过init.rc文件来实现这个操作,就是在该文件里随便一行,写上面的命令行,启动时会自动执行!这样就不用手动的改变该节点的属性了。

    拷贝LEDAPP.apk到开发板上,通过安装工具把它安装到开发板上

    运行程序,就能按程序上的近钮来控制开发板上的LED亮灭了!

  • 相关阅读:
    【JDK】JDK源码分析-LinkedList
    【JDK】JDK源码-Queue, Deque
    【JDK】JDK源码分析-Vector
    【JDK】JDK源码分析-ArrayList
    Jmeter-安装及配置(一)
    数据库连接池技术
    2017年度总结
    Windows重装系统
    Java + Selenium + Appium手机自动化测试
    DbVisualizer出现下列错误:Could not read XML file
  • 原文地址:https://www.cnblogs.com/luxiaolai/p/3695205.html
Copyright © 2011-2022 走看看