第一步:首先在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 Projectcom.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
#defineDEV_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 {
publicnative String stringFromJNI();
publicnativeint OPEN();
publicnativeint IOCTL(int fd,int controlcode,int ledID);
publicnativeint 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,总是报错:insomethingnotastructureorunion
error:requestformember'GetStringUTFChars'insomethingnotastructureorunion
问题解决了,原来是这样的:
如果是c程序,要用(*env)->
如果是C++要用env->
在linux下如果.c文件中用“env->”编译会找不到此结构,必须用“(*env)->”,或者改成.cpp文件,以c++的方式来编译
以下是两者的区别:
jni.h中
structJNINativeInterface_;
structJNIEnv_;
#ifdef__cplusplus
typedefJNIEnv_JNIEnv;
#else
typedefconststructJNINativeInterface_*JNIEnv;
#endif
/*
*WeuseinlinedfunctionsforC++sothatprogrammerscanwrite:
*env->FindClass("java/lang/String")
*inC++ratherthan:
*(*env)->FindClass(env,"java/lang/String")
*inC.
*/
即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)//获取引脚的输入电平状态
相关推荐
NULL 博文链接:https://liuzongming.iteye.com/blog/1945751
NULL 博文链接:https://liuzongming.iteye.com/blog/1922200
这个是一个简单的JNI小实验,提供完整的过程附图以及实验成功,一看即懂!
jni编写的一个示例,示例中包含一带参数的有返回值的函数。
android通过JNI控制LED http://blog.csdn.net/newairzhang/article/details/38469271
JNI调用驱动 打开LED灯 动过JNI调用底层驱动开关LED灯 以后调用驱动如同一样 可举一反三,切记切记一定要下
Android串口发送接收demo,开源的jni打开串口,接收与发送,代码简单明了.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
学习JNI编译时,缺少的jni.h和jni_md.h头文件,Java调用C和C++函数时的JNI使用区别: 注意:jni.h头文件中对于***.c & ***.cpp采用不同的定义
NULL 博文链接:https://conkeyn.iteye.com/blog/1597188
关于jni编程一些资料和一些实例。适合初学者
JNI开发教程 包含: JNI简介 JNI接口函数详细介绍
Android 6.0 AS平台 JNI 实验
解压后,有4个JNI资料,如下: JNI Specification.CHM JNI 简介与实现.pdf JNI编程指南.pdf JNI程序员指南与规范.pdf
Android通过jni控制LED灯.zip,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
通过jni将一张彩色图片转换为黑白图片,通过这个demo,可以深入了解jni的应用
基于老罗的《Android内核源代码情景分析》第二章freg实例,使用NDK编译jni层从而调用驱动程序,能大大缩短项目开发周期。
一个简单的demo。安卓通过jni直接驱动/dev下的led灯设备。不区分硬件,只要在/dev下能看到驱动的设备文件就可以用这种方式
生成jni 高用的c的so文件,并通过java调用该接口,实现能/dev/下的设备驱动的操作
mac 下jni编译详见文章: http://blog.csdn.net/qwezcl/article/details/17766397