首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > 移动开发 >

JNI综合实验2:IO控制及驱动打开与关闭

2013-10-27 
JNI综合实验二:IO控制及驱动打开与关闭第一步:首先在linux下添加驱动1.查看原理图,找出未使用的引脚,这里

JNI综合实验二:IO控制及驱动打开与关闭

第一步:首先在linux下添加驱动

1.查看原理图,找出未使用的引脚,这里是:GPJ0_0 GPJ0_1

2.添加char字符设备驱动,找到LINUX源代码下的char设备驱动路径: FriendlyArm /Linux3.0.8/ Drivers/char/目录,在目录下新建里一个文件lzm_fjicc.c 用来写驱动用。

需要注册设备、设备的打开、关闭、取消设备等操作。

源代码如综合实验一:

?

第二步:建立Android测试代码,第一步要实现.so文件:

1.打开eclipseàFileàNewàAndroid Application Project? com.example.TEST

2.新建jni文件夹,在文件夹内新建两个文件:test-jni.c和Android.mk

Android.mk内容如下:

# Copyright (C) 2009 The Android Open Source Project

#

# Licensed under the Apache License, Version 2.0 (the "License");

# you may not use this file except in compliance with the License.

# You may obtain a copy of the License at

#

#????? http://www.apache.org/licenses/LICENSE-2.0

#

# Unless required by applicable law or agreed to in writing, software

# distributed under the License is distributed on an "AS IS" BASIS,

# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

# See the License for the specific language governing permissions and

# limitations under the License.

#

LOCAL_PATH := $(call my-dir)

?

include$(CLEAR_VARS)

?

LOCAL_MODULE??? := test-jni

LOCAL_SRC_FILES := test-jni.c

?

include$(BUILD_SHARED_LIBRARY)

jni0922.c内容如下:

/*

?* Copyright (C) 2009 The Android Open Source Project

?*

?* Licensed under the Apache License, Version 2.0 (the "License");

?* you may not use this file except in compliance with the License.

?* You may obtain a copy of the License at

?*

?*????? http://www.apache.org/licenses/LICENSE-2.0

?*

?* Unless required by applicable law or agreed to in writing, software

?* distributed under the License is distributed on an "AS IS" BASIS,

?* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

?* See the License for the specific language governing permissions and

?* limitations under the License.

?*

?*/

#include<termios.h>

#include<unistd.h>

#include<sys/types.h>

#include<sys/stat.h>

#include<sys/ioctl.h>

#include<fcntl.h>

#include<string.h>

#include<jni.h>

#include<errno.h>

//#include <utils/Log.h>

//#include <system.h>

?

#define VIB_ON 0x11

#define VIB_OFF 0x22

?

?

?

#define? DEV_NAME "/dev/LZM_FJICC"

/* This is a trivial JNI example where we use a native method

?* to return a new VM String. See the corresponding Java source

?* file located at:

?*

?*?? /project/app/TEST/src/com.example.TEST/MainActivity.java

?*?? /project/app/TEST/src/com.example.TEST/TESTCLASS.java

?*/

jstring

Java_com_example_TEST_TESTCLASS_stringFromJNI( JNIEnv* env, jobject thiz )

{

??? return (*env)->NewStringUTF(env, "Hello from JNI !");

}

?

jint

Java_com_example_TEST_TESTCLASS_IOCTL( JNIEnv* env, jobject thiz, jint fd ,jint controlcode,jint ledid)

{

?????? /* LED */

??? int CTLCODE = controlcode;

??? int value =-1;

??? switch(CTLCODE)

??? {? case VIB_ON:

????????????? {

????????????? ioctl(fd,1,ledid);//setLedState( 0, 1 );//调用驱动程序中的ioctrl接口,把命令传下去,实现硬件操作

????????????? break;

????????????? }

??? ?? case VIB_OFF:

??? ?? ??????{

??? ?? ???????ioctl(fd,0,ledid);////?? ? setLedState( 0, 0 );//调用驱动程序中的ioctrl接口,把命令传下去,实现硬件操作

??? ?? ??????break;

??? ?? ??????}

?

??? ?? default:break;

??? ?}

?????? return fd;

}

?

jint

Java_com_example_TEST_TESTCLASS_OPEN(JNIEnv* env,jobject thiz)

{

?

??? ? jint fd;

??? ? fd=open(DEV_NAME,O_RDWR);

??? ? return fd;

}

?

jint

Java_com_example_TEST_TESTCLASS_CLOSE( JNIEnv* env, jobject thiz, jint fd)

{

?????? ?jint ret;

?????? ?ret = close(fd);

?????? ?return ret;

}

?

?

注意如果需要头文件Alog.h需要自己写,然后放在jni文件夹下的

#pragma once

#include<android/log.h>

#define LOG_TAG "debug log"

#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, fmt, ##args)

#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, fmt, ##args)

#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, fmt, ##args)

?

?

?

3.建立完毕,打开Cygwin工具,并进入到工程目录下的jni目录下:

$ cd d:/Program/Android/workspace/TEST /jni

$$NDK/ndk-build

?

这样就OK了,生成了libtest-jni.so文件了,自动生成到了工程目录下的libs/armeabi/ libtest-jni.so,发现test-jni是我们刚才在.mk文件里面的命名。

?

第三步:写应用程序:

1.在应用程序类com.example.TEST目录下建立一个类:TESTCLASS.java,输入如下代码,这是用来引用libtest-jni.so文件的。

package com.example.TEST;

?

import android.util.Log;

?

publicclass TESTCLASS {

?

public? native String stringFromJNI();

public? nativeint OPEN();

public? nativeint IOCTL(int fd,int controlcode,int ledID);

public? nativeint CLOSE(int fd);

?

static {

??? try {

??? System.loadLibrary("test-jni");

??? } catch (UnsatisfiedLinkError e) {

??????? Log.d("HardwareControler", "HardwareControler ibrary not found!");

??? }

}

}

?

2.编写应用程序,调用TESTCLASS类中的函数OPEN()/CLOSE()/IOCTL()就可以实现底层的控制了。

添加按钮,用来打开和关闭LED灯,以及关闭驱动

<Button

??????????? android:id="@+id/button1"

??????????? style="?android:attr/buttonStyleSmall"

??????????? android:layout_width="wrap_content"

??????????? android:layout_height="wrap_content"

??????????? android:layout_gravity="center_horizontal"

??????????? android:layout_weight="0.76"

??????????? android:text="ON" />

?

??????? <Button

??????????? android:id="@+id/button2"

??????????? style="?android:attr/buttonStyleSmall"

??????????? android:layout_width="wrap_content"

??????????? android:layout_height="wrap_content"

??????????? android:layout_weight="1.26"

??????????? android:text="OFF" />

?

??????? <Button

??????????? android:id="@+id/button5"

??????????? style="?android:attr/buttonStyleSmall"

??????????? android:layout_width="wrap_content"

??????????? android:layout_height="wrap_content"

??????????? android:layout_weight="0.76"

??????????? android:text="close" />

2.编写MainActivity,添加响应函数:

package com.example.TEST;

?

import java.io.DataOutputStream;

import java.io.IOException;

?

import android.os.Bundle;

import android.app.Activity;

import android.view.Menu;

import android.view.View;

import android.widget.Button;

import android.widget.Toast;

?

publicclass MainActivity extends Activity {

?

??? private Button btn_on;

??? private Button btn_off,btn_close;

???

??? publicstaticfinalintVIB_ON = 0x11;?

??? publicstaticfinalintVIB_OFF = 0x22;??

??? intfd;

??? intvalue = -1;

??? TESTCLASS mTESTCLASS1;

???

??? @Override

??? protectedvoid onCreate(Bundle savedInstanceState) {

?????? super.onCreate(savedInstanceState);

??????

?????? setContentView(R.layout.activity_main);

?????? mTESTCLASS1 = new TESTCLASS();

?????? String s = mTESTCLASS1.stringFromJNI().toString();

??????

?????? //修改驱动的权限LZM_FJICC

?????? changePerm();

?????????????

?????????????

?????? fd = mTESTCLASS1.OPEN();

?????? Toast.makeText(MainActivity.this, "open,fd="+fd, Toast.LENGTH_SHORT).show();

??????

?????? btn_on = (Button)findViewById(R.id.button1);

?????? btn_off = (Button)findViewById(R.id.button2);???

?????? btn_close= (Button)findViewById(R.id.button5);

??????

??????

??????

??????

?????? if(fd == -1)

?????????? Toast.makeText(MainActivity.this, "没有打开设备", Toast.LENGTH_SHORT).show();

?????? else

?????????? Toast.makeText(MainActivity.this, "打开设备", Toast.LENGTH_SHORT).show();

??????

?????? Toast.makeText(MainActivity.this,""+s, Toast.LENGTH_SHORT).show();

??????

?????? btn_on.setOnClickListener(new Button.OnClickListener(){

?

?????????? @Override

?????????? publicvoid onClick(View arg0) {

????????????? // TODO Auto-generated method stub

????????????? fd=mTESTCLASS1.IOCTL(fd, VIB_ON,0);

????????????? Toast.makeText(MainActivity.this, "ioctl,fd="+fd, Toast.LENGTH_SHORT).show();

?????????? }

?????? });

??????

??????

?????? btn_off.setOnClickListener(new Button.OnClickListener(){

?

?????????? @Override

?????????? publicvoid onClick(View v) {

????????????? // TODO Auto-generated method stub

????????????? mTESTCLASS1.IOCTL(fd, VIB_OFF,0);

?

?????????? }});

??????

??????

??????

?????? btn_close.setOnClickListener(new Button.OnClickListener(){

?

?????????? @Override

?????????? publicvoid onClick(View v) {????????????

?????????? // TODO Auto-generated method stub

????????????? Toast.makeText(MainActivity.this, "close,fd="+fd, Toast.LENGTH_SHORT).show();

????????????? if(fd != -1){

???????????????????? value = mTESTCLASS1.CLOSE(fd);

???????????????????? if(value == -1)

???????????????????????? Toast.makeText(MainActivity.this, "close fail,fd="+value, Toast.LENGTH_SHORT).show();

???????????????????? else

???????????????????????? Toast.makeText(MainActivity.this, "close success,fd="+value, Toast.LENGTH_SHORT).show();

????????????? }else{

????????????? Toast.makeText(MainActivity.this, "设备未打开,无需关闭", Toast.LENGTH_SHORT).show();

????????????? }

?????????? }

??????????

?????? });

??????

???

??? }

???

??? void changePerm()

??? {

??? ??? Process chperm;

??? ??? try {

??? ??????? chperm=Runtime.getRuntime().exec("su");

?

?

??? ?? DataOutputStream os =

??? ????????? new DataOutputStream(chperm.getOutputStream());

??? ??????? os.writeBytes("chmod 777 /dev/LED_LZM_FJICC\n");

??? ??????? os.flush();

?

??? ??????? os.writeBytes("exit\n");

??? ??????? os.flush();

?

??? ????????? chperm.waitFor();

?

??? } catch (IOException e) {

??? ??? // TODO Auto-generated catch block

??? ??? e.printStackTrace();

??? } catch (InterruptedException e) {

??? ??? // TODO Auto-generated catch block

??? ??? e.printStackTrace();

??? }

??? }

}

问题一:android NDK jni下的c文件 Unresolved inclusion

原因是在eclipse编辑环境中没有找到对应的include中的文件。解决方法是将包含该文件的include目录作为新的linked folder加入工程中。具体方法如下:
1. 右击工程->New->Folder

2. 对话框中点击Advanced

3. 选择Link to alternate location (Linked Folder),选择需要的include目录

4. Finish后刷新工程,问题解决。

include 目录可以在ndk的安装目录中找到

比如:在安装的NDK目录下找到/NDKDir/android-ndk-r7b/platforms/android-8/arch-arm/usr/include

?

问题二:在android?里使用JNI,总是报错:in?something?not?a?structure?or?union

?error:?request?for?member?'GetStringUTFChars'?in?something?not?a?structure?or?union

问题解决了,原来是这样的:
如果是c程序,要用?(*env)->
如果是C++要用?env->

在linux下如果.c文件中用?“env->”?编译会找不到此结构,必须用“(*env)->”,或者改成.cpp文件,以?c++的方式来编译

以下是两者的区别:
jni.h中
struct?JNINativeInterface_;
struct?JNIEnv_;
#ifdef?__cplusplus
typedef?JNIEnv_?JNIEnv;
#else
typedef?const?struct?JNINativeInterface_?*JNIEnv;
#endif

/*
*?We?use?inlined?functions?for?C++?so?that?programmers?can?write:
*???env->FindClass("java/lang/String")
*?in?C++?rather?than:
*????(*env)->FindClass(env,?"java/lang/String")
*?in?C.
*/
C++中使用
env->FindClass("java/lang/String")
C中使用
(*env)->FindClass(env,?"java/lang/String")

?

?

问题三:直接在应用程序中获取驱动的可执行权限#chmod 777

//用来修改驱动的权限问题否则需要在终端输入 #chmod 777 /dev/LZM_FJICC

??? void changePerm()

??? {

??? ??? Process chperm;

??? ??? try {

??? ??????? chperm=Runtime.getRuntime().exec("su");

??? ?? DataOutputStream os =

??? ????????? new DataOutputStream(chperm.getOutputStream());

??? ??????? os.writeBytes("chmod 777 /dev/LZM_FJICC\n");

??? ??????? os.flush();

??? ??????? os.writeBytes("exit\n");

??? ??????? os.flush();

??? ????????? chperm.waitFor();

??? } catch (IOException e) {

??? ??? // TODO Auto-generated catch block

??? ??? e.printStackTrace();

??? } catch (InterruptedException e) {

??? ??? // TODO Auto-generated catch block

??? ??? e.printStackTrace();

??? }

??? }

?

问题四:S5VP210端口设置小结

//???? 定义用到的引脚?? S5PV210_GPJ0(7)

//? 设置引脚的输出

?????? s3c_gpio_cfgpin(S5PV210_GPJ0(7),S3C_GPIO_SFN(1));//设置为输出

?????? gpio_direction_output(S5PV210_GPJ0(7),0);

?

//释放总线

?#define OW_Pin S5PV210_GPJ0(7)

?????? s3c_gpio_cfgpin(OW_Pin,S3C_GPIO_SFN(0));//设置为输入

?????? s3c_gpio_setpull(OW_Pin,S3C_GPIO_PULL_UP);

gpio_get_value(OW_Pin)//获取引脚的输入电平状态

?

热点排行