android jni的编写, 控制led灯
2013-06-17 18:11
302 查看
jni, java native interface, java的本地接口,如果java代码想去调用native方法(实际就是c/c++函数),就需要用jni技术,在传统的java中jni技术就已经存在,但是由于传统的java代码中,不太去写架构或者平台相关的代码,所以以前jni不是太惹人注意,直到android出现后,android本身是一个linux操作系统, linux中的应用编程中就使用c/c++代码去调用驱动,假如android的应用apk想去调用底层的设备驱动,那么就必须要去调用c/c++代码,所以此时jni就显得很重要,它起着承上启下的作用.
jni的写法有好几种,在这里先介绍在android源码包+linux环境下的jni编程方式,随后会介绍ndk中的jni的编程方式
编程之前首先需要给大家介绍一个大体的框架,我们需要在apk中去点一个led灯,此时就像做饭一样,介绍几个主料:
1, apk,实现button点灯
2, jni代码,调用linux的系统调用,去控制驱动
3, 驱动,完成控制led硬件
首先介绍apk中使用jni中的几个接口
接口一: 调用动态库
static{
System.loadLibrary("led_jni"); // /system/lib/libled_jni.so
}
接口二: 声明本地方法
public native int OpenDev();
public native int DevOn();
public native int DevOff();
public native int CloseDev();
接口三: 直接调用本地方方法
OpenDev();
apk代码的内容如下,非常简单
vm->GetEnv((void **)&env, JNI_VERSION_1_4)该方法是dvm给我们提供的方法,用于获取环境变量对象JNIEnv* env,同时会检测jni的版本是否是1.4, 该方法正常返回JNI_OK
myRegisterNatives(env);该法是自己去实现的,参数就是通过vm->GetENv方法获取的
b,
myRegisterNatives(env)的实现,主要是为了完成映射表的注册,会调用env->RegisterNatives()方法
第三个参数: 映射表表的成员个数sizeof(myMethods)/sizeof(myMethods[0])
返回: JNI_OnLoad正常 返回JNI_VERSION_1_4
错误返回一个负数
c,接下来就是介绍映射表的构造了:
d,代码写好了,Android.mk是为了编译我们写的代码,代码最终会编译成动态库:
jni的写法有好几种,在这里先介绍在android源码包+linux环境下的jni编程方式,随后会介绍ndk中的jni的编程方式
编程之前首先需要给大家介绍一个大体的框架,我们需要在apk中去点一个led灯,此时就像做饭一样,介绍几个主料:
1, apk,实现button点灯
2, jni代码,调用linux的系统调用,去控制驱动
3, 驱动,完成控制led硬件
首先介绍apk中使用jni中的几个接口
接口一: 调用动态库
static{
System.loadLibrary("led_jni"); // /system/lib/libled_jni.so
}
接口二: 声明本地方法
public native int OpenDev();
public native int DevOn();
public native int DevOff();
public native int CloseDev();
接口三: 直接调用本地方方法
OpenDev();
apk代码的内容如下,非常简单
jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint ret = -1; jint result = -1; if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) { LOGE("ERROR: GetEnv failed"); goto bail; } ret = myRegisterNatives(env); if(ret != JNI_TRUE) { LOGE("ERROR: registerNatives failed"); goto bail; } result = JNI_VERSION_1_4; bail: return result; }
vm->GetEnv((void **)&env, JNI_VERSION_1_4)该方法是dvm给我们提供的方法,用于获取环境变量对象JNIEnv* env,同时会检测jni的版本是否是1.4, 该方法正常返回JNI_OK
myRegisterNatives(env);该法是自己去实现的,参数就是通过vm->GetENv方法获取的
b,
myRegisterNatives(env)的实现,主要是为了完成映射表的注册,会调用env->RegisterNatives()方法
static JNINativeMethod myMethod[] ={ {"OpenDev", "()I", (void *)led_open}, {"DevOn", "()I", (void *)led_on}, {"DevOff", "()I", (void *)led_off}, {"DevClose", "()I", (void *)led_close}, };
第三个参数: 映射表表的成员个数sizeof(myMethods)/sizeof(myMethods[0])
返回: JNI_OnLoad正常 返回JNI_VERSION_1_4
错误返回一个负数
c,接下来就是介绍映射表的构造了:
#define LOG_TAG "myledjni"
#include <utils/Log.h>
#include "jni.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#define GPG3DAT2_ON _IO('L', 0x31)
#define GPG3DAT2_OFF _IO('L', 0x31)
static int fd = -1;
static jint led_open(JNIEnv *env, jobject obj)
{
//绯荤粺璋冪敤
LOGD("%s\n", __FUNCTION__);
fd = open("/dev/led", O_RDWR);
if(fd < 0)
{
LOGE("open dev error");
return -1;
}
return 0;
}
static jint led_on(JNIEnv *env, jobject obj)
{
LOGD("%s\n", __FUNCTION__);
int ret = -1;
ret = ioctl(fd,GPG3DAT2_ON,NULL);
if(ret < 0)
{
LOGE("ioctl error\n");
return -1;
}
return 0;
}
static jint led_off(JNIEnv *env, jobject obj)
{
LOGD("%s\n", __FUNCTION__);
int ret = -1;
ret = ioctl(fd,GPG3DAT2_OFF,NULL);
if(ret < 0)
{
LOGE("ioctl error\n");
return -1;
}
return 0;
}
static jint led_close(JNIEnv *env, jobject obj)
{
LOGD("%s\n", __FUNCTION__);
close(fd);
return 0;
}
static jint led_read(JNIEnv *env, jobject obj)
{
//read(fd, buf, size);
return 0 ;
}
static jint led_write(JNIEnv *env, jobject obj)
{
//write();
return 0 ;
}
static JNINativeMethod myMethod[] ={ {"OpenDev", "()I", (void *)led_open}, {"DevOn", "()I", (void *)led_on}, {"DevOff", "()I", (void *)led_off}, {"DevClose", "()I", (void *)led_close}, };
static char *clsStr = "fs/hq/LedActivity";
static int myRegisterNatives(JNIEnv* env)
{
jint ret = -1;
jclass myClz = env->FindClass(clsStr);
if (myClz == NULL) {
LOGE("Native registration unable to find class '%s'", clsStr);
return JNI_FALSE;
}
ret = env->RegisterNatives(myClz, myMethod, sizeof(myMethod)/sizeof(myMethod[0]));
if(ret < 0)
{
LOGE("%s, RegisterNatives failed", __FUNCTION__);
return JNI_FALSE;
}
LOGD("RegisterNatives Ok\n");
return JNI_TRUE;
}
jint JNI_OnLoad(JavaVM* vm, void* reserved) { JNIEnv* env = NULL; jint ret = -1; jint result = -1; if (vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK) { LOGE("ERROR: GetEnv failed"); goto bail; } ret = myRegisterNatives(env); if(ret != JNI_TRUE) { LOGE("ERROR: registerNatives failed"); goto bail; } result = JNI_VERSION_1_4; bail: return result; }
d,代码写好了,Android.mk是为了编译我们写的代码,代码最终会编译成动态库:
/* * Simple - REALLY simple memory mapping demonstration. */ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/init.h> #include <linux/kernel.h> /* printk() */ #include <linux/slab.h> /* kmalloc() */ #include <linux/fs.h> /* everything... */ #include <linux/errno.h> /* error codes */ #include <linux/types.h> /* size_t */ #include <linux/mm.h> #include <linux/kdev_t.h> #include <linux/cdev.h> #include <linux/delay.h> #include <linux/device.h> #include <asm/io.h> #include <asm/uaccess.h> #define pGPG3CON 0xE03001C0 #define pGPG3DAT 0xE03001C4 static void *vGPG3CON , *vGPG3DAT; #define GPG3CON (*(volatile unsigned int *) vGPG3CON) #define GPG3DAT (*(volatile unsigned int *) vGPG3DAT) #define LED_ON _IO('L', 0x31) #define LED_OFF _IO('L', 0x30) static int simple_major = 252; module_param(simple_major, int, 0); MODULE_AUTHOR("farsight"); MODULE_LICENSE("Dual BSD/GPL"); //static int flag = 0; /* * Open the device; in fact, there's nothing to do here. */ int simple_open (struct inode *inode, struct file *filp) { vGPG3CON=ioremap(pGPG3CON,0x10); vGPG3DAT=vGPG3CON+0x04; GPG3CON=0x1111; //GPG3DAT=0xff; return 0; } ssize_t simple_read(struct file *file, char __user *buff, size_t count, loff_t *offp) { return 0; } ssize_t simple_write(struct file *file, const char __user *buff, size_t count, loff_t *offp) { return 0; } void led_off( void ) { GPG3DAT=GPG3DAT&(~(1<<2)); //printk("stop led\n"); } void led_on( void ) { GPG3DAT=GPG3DAT|(1<<2 printk="" start="" led="" n="" static="" int="" simple_ioctl="" struct="" inode="" inode="" struct="" file="" file="" unsigned="" int="" cmd="" unsigned="" long="" arg="" switch="" cmd="" case="" led_on:="" led_on="" break="" case="" led_off:="" led_off="" break="" default:="" break="" return="" 0="" static="" int="" simple_release="" struct="" inode="" node="" struct="" file="" file="" return="" 0="" set="" up="" the="" cdev="" structure="" for="" a="" device="" static="" void="" simple_setup_cdev="" struct="" cdev="" dev="" int="" minor="" struct="" file_operations="" fops="" int="" err="" devno="MKDEV(simple_major," minor="" cdev_init="" dev="" fops="" dev-="">owner = THIS_MODULE; dev->ops = fops; err = cdev_add (dev, devno, 1); /* Fail gracefully if need be */ if (err) printk (KERN_NOTICE "Error %d adding simple%d", err, minor); } /* * Our various sub-devices. */ /* Device 0 uses remap_pfn_range */ static struct file_operations simple_remap_ops = { .owner = THIS_MODULE, .open = simple_open, .release = simple_release, .read = simple_read, .write = simple_write, .ioctl = simple_ioctl, }; /* * We export two simple devices. There's no need for us to maintain any * special housekeeping info, so we just deal with raw cdevs. */ static struct cdev SimpleDevs; /* * Module housekeeping. */ static struct class *my_class; static int simple_init(void) { int result; dev_t dev = MKDEV(simple_major, 0); /* Figure out our device number. */ if (simple_major) result = register_chrdev_region(dev, 1, "simple"); else { result = alloc_chrdev_region(&dev, 0, 1, "simple"); simple_major = MAJOR(dev); } if (result < 0) { printk(KERN_WARNING "simple: unable to get major %d\n", simple_major); return result; } if (simple_major == 0) simple_major = result; /* Now set up two cdevs. */ simple_setup_cdev(&SimpleDevs, 0, &simple_remap_ops); printk("simple device installed, with major %d\n", simple_major); my_class= class_create(THIS_MODULE, "simple"); device_create(my_class, NULL, MKDEV(simple_major, 0), NULL, "led"); return 0; } static void simple_cleanup(void) { cdev_del(&SimpleDevs); unregister_chrdev_region(MKDEV(simple_major, 0), 1); device_destroy(my_class,MKDEV(simple_major,0)); printk("simple device uninstalled\n"); } module_init(simple_init); module_exit(simple_cleanup);
相关文章推荐
- 友善之臂4412开发板android应用层通过jni直接控制除LED、蜂鸣器外的其它IO口,系统直接重启问题
- UVC系列5-编写Android jni代码实现控制PTZ
- android通过JNI控制LED
- 【转】Android应用程序:(jni方式)控制LED/GPIO
- ok6410Android应用程序:(jni方式)控制LED/GPIO
- android通过JNI控制LED
- Freescale IMX6 Android (5): APP通过JNI控制LED
- Android应用程序通过JNI控制LED
- android平台中编写jni模块的方法(1)
- TQ210搭载Android4.0.3系统构建之LED从驱动到HAL到JNI到应用程序(驱动篇)
- Android For JNI(六)——交叉编译,NDK概述以及文件结构,编写自己的第一个JNI工程
- android4.0平台通过IOCTL控制LED-基于x210v3开发板
- android studio编写jni成功
- jni集成第3方third party动态库libwebrtc_audio_preprocessing.so时android.mk的编写
- **Android环境下的JNI 编写及所遇到的坑**
- 基于mini2440嵌入式linux上整合一套Domoticz智能家居系统(九)使用domoticz+mosquitto+Android客户端实现控制mini2440上的LED(二)
- Android驱动入门-Led控制+app+ndk库+底层驱动
- 在Ubuntu为Android硬件抽象层(HAL)模块编写JNI方法提供Java访问硬件服务接口
- Android--Led_Demo_APK控制LED灯
- 浅析android通过jni控制service服务程序的简易流程