码迷,mamicode.com
首页 > 移动开发 > 详细

Android驱动之JNI(GPIO控制两个外接点灯)

时间:2015-08-28 16:55:02      阅读:400      评论:0      收藏:0      [点我收藏+]

标签:

要想用java去调用C函数接口那么就需要使用JNI(Java Native Interface,Java 本地调用)去访问本地的动态链接库。

 

关于NDK的安装,现在有linux环境下的版本,也有windows环境下的版本,这个可自行百度,这里不多说

 

生成.so文件需要三个文件,东西不多,就直接上代码了。

com_pngcui_HelloJni.c

 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <fcntl.h>
 4 #include <errno.h>
 5 #include <unistd.h>
 6 #include <sys/types.h>
 7 #include <sys/stat.h>
 8 #include <string.h>
 9 #include <stdint.h>
10 #include <termios.h>
11 #include <android/log.h>
12 #include <sys/ioctl.h>
13 
14 #include "com_pngcui_helloJni.h"
15 
16 #undef TCSAFLUSH
17 #define TCSAFLUSH TCSETSF
18 #ifndef _TERMIOS_H_
19 #define _TERMIOS_H_
20 #endif
21 
22 
23 int fd = 0;
24 
25 
26 /*open()*/
27 JNIEXPORT jint JNICALL Java_com_pngcui_helloJni_HelloJni_open
28     (JNIEnv *env , jobject obj){
29         /*只允许打开一次设备!*/
30         if(fd<=0)
31             fd = open("/dev/jni",O_RDWR|O_NDELAY|O_NOCTTY);
32         if(fd<=0)
33             __android_log_print(ANDROID_LOG_INFO,"serial","open /dev/jni Error..");
34         else
35             __android_log_print(ANDROID_LOG_INFO,"serial","open /dev/jni Sucess fd = %d",fd);
36     }
37     
38 JNIEXPORT jint JNICALL Java_com_pngcui_helloJni_HelloJni_close
39     (JNIEnv *env,jobject obj){
40         
41         if(fd > 0)
42             close(fd);
43     }
44     
45 JNIEXPORT jint JNICALL Java_com_pngcui_helloJni_HelloJni_ioctl
46     (JNIEnv *env,jobject obj,jint num , jint en){
47         
48         ioctl(fd,en,num);
49     }

com_pngcui_HelloJni.h,注意这里的命名规则!Java_包名_java类名_接口名

 1 /* DO NOT EDIT THIS FILE - it is machine generated */
 2 #include <jni.h>
 3 /* Header for class com_neojet_scanner_key */
 4 
 5 #ifndef _Include_com_pngcui_helloJni
 6 #define _Inlcude_com_pngcui_helloJni
 7 
 8 #ifdef _cplusplus
 9 extern "C"{
10 #endif
11     
12     /*Java_packagename_classname_methodname*/
13     /*open()*/
14     JNIEXPORT jint JNICALL Java_com_pngcui_helloJni_Jni_open
15     (JNIEnv *,jobject);
16     
17     /*close()*/
18     JNIEXPORT jint JNICALL Java_com_pngcui_helloJni_Jni_close
19     (JNIEnv *,jobject);
20     
21     /*ioctl()*/
22     JNIEXPORT jint JNICALL Java_com_pngcui_helloJni_Jni_ioctl
23     (JNIEnv *,jobject,jint num,jint en);
24     
25 #ifdef _cplusplus
26 }
27 #endif
28 #endif

 

第三个编译文件Android.mk

1 LOCAL_PATH := $(call my-dir)
2 include $(CLEAR_VARS)
3 LOCAL_MODULE    := HelloJni
4 LOCAL_SRC_FILES := com_pngcui_helloJni.c
5 LOCAL_LDLIBS += -llog 
6 LOCAL_LDLIBS +=-lm
7 include $(BUILD_SHARED_LIBRARY)

在android.mk文件中我们可以知道最后会生成一个libHelloJni.so本地库文件。

 

在Eclipse中的android工程中加入NDK

把以上三个文件放入jni文件夹中,最后编写一个java类,也就是命名规则的那个java类名

Jni.java

1 package com.pngcui.helloJni;
2 
3 public class Jni {
4     
5     public native int       Open();
6     public native int       Close();
7     public native int       Ioctl(int num, int en);
8 }

最后在调用Jni.java的类中需要声明本地库的路径

1 static {
2         System.loadLibrary("HelloJni");
3     }

附上完整的MainActivity.java代码

技术分享
  1 package com.pngcui.helloJni;
  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 MainActivity extends Activity {
 10 
 11     
 12     Jni jni = new Jni();
 13     
 14     private Button y1;
 15     private Button y2;
 16     private Button n1;
 17     private Button n2;
 18     private Button start;
 19     
 20     int i;
 21     
 22     @Override
 23     protected void onCreate(Bundle savedInstanceState) {
 24         super.onCreate(savedInstanceState);
 25         setContentView(R.layout.activity_main);
 26     
 27         y1 = (Button)findViewById(R.id.y1);
 28         y2 = (Button)findViewById(R.id.y2);
 29         n1 = (Button)findViewById(R.id.n1);
 30         n2 = (Button)findViewById(R.id.n2);
 31         start = (Button)findViewById(R.id.start);
 32         
 33         jni.Open();
 34         
 35         y1.setOnClickListener(new manager());
 36         n1.setOnClickListener(new manager());
 37         y2.setOnClickListener(new manager());
 38         n2.setOnClickListener(new manager());
 39         start.setOnClickListener(new manager());
 40         
 41         
 42     }
 43     
 44     class manager implements OnClickListener{
 45 
 46         @Override
 47         public void onClick(View v) {
 48             
 49             //gpio_set_value(led_gpio[i],cmd),且二极管为低电平有效
 50             
 51             switch(v.getId()){
 52         
 53             case R.id.y1:
 54                 jni.Ioctl(0, 0);
 55                 break;
 56             case R.id.n1:
 57                 jni.Ioctl(0, 1);
 58                 break;
 59                 
 60             case R.id.y2:
 61                 jni.Ioctl(1, 0);
 62                 break;
 63             case R.id.n2:
 64                 jni.Ioctl(1, 1);
 65                 break;
 66                 
 67             case R.id.start:
 68                 try {
 69                     start();
 70                 } catch (InterruptedException e) {
 71                     // TODO Auto-generated catch block
 72                     e.printStackTrace();
 73                 }
 74                 break;
 75             
 76             }
 77             
 78         }
 79 
 80         private void start() throws InterruptedException {
 81             // TODO Auto-generated method stub
 82             
 83             i = 10;
 84             while(i>0){
 85                 i--;
 86                 jni.Ioctl(1, 0);
 87                 jni.Ioctl(0, 1);
 88                 
 89                 Thread.sleep(200);
 90                 
 91                 jni.Ioctl(1, 1);
 92                 jni.Ioctl(0,0);
 93                 
 94                 Thread.sleep(200);
 95             }
 96             jni.Ioctl(1, 0);
 97         }
 98         
 99     
100         
101     }
102 
103     static {
104         System.loadLibrary("HelloJni");
105     }
106 }
View Code

最后还有一个问题,那就是权限问题!也就是说到现在我们还没有给我们的驱动程序生成的设备节点设置权限,也就是可读可写权限,如果不设置这个权限,那么我们的android应用时无法打开设备节点的!!!在调用open函数时会直接返回-1!!而在exynos4412平台上的android设置权限的文件在device/samsung/smdk4x12/conf/init.smdk4x12.rc中,而不是网上说的init.rcueventd.rc文件中,但是!!本人在里面设置了chmod 777 /dev/jni 依旧不能正常open,百思不得其解,有哪位大神知道怎么去自动设置权限,还麻烦教导我一下,不甚感激!

 

附上蠢蠢的解决办法:在串口终端使用命令chmod 777 /dev/jni然后运行app,可暂时性解决此问题,但是开发板重启以后就需要重修设置权限!!

 

Android驱动之JNI(GPIO控制两个外接点灯)

标签:

原文地址:http://www.cnblogs.com/pngcui/p/4766729.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!