您的位置:首页 > 移动开发 > Android开发

Android通过JNI操作串口

2014-07-09 10:01 295 查看
1.
本地类TtyNativeControl

package com.notioni.uart.manager;

import java.lang.ref.WeakReference;

import android.os.Handler;

import android.os.Looper;

import android.os.Message;

import android.util.Log;

/**

*
本地方法类

*/

public
class TtyNativeControl {

private
final
static String
TAG =
"TtyNativeControl";

static{

System.loadLibrary("uart_ctl");

}

private
static
final
int
TTY_MSG_RECEIVE = 1;

private
static
final
int
TTY_CLOSE_DEVICE =
TTY_MSG_RECEIVE+1;

private
EventHandler mEventHandler;

private
ReceiveCallback mReceiveCallBack;

TtyNativeControl(){

mReceiveCallBack
= null;

Looper looper;

if((looper
= Looper.myLooper()) != null){

mEventHandler
= new EventHandler(this,
looper);

}else
if((looper = Looper.getMainLooper())
!= null){

mEventHandler
= new EventHandler(this,
looper);

}else{

mEventHandler
= null;

}

native_setup(new
WeakReference<TtyNativeControl>(this));

}

/**

*
打开驱动

*
@return
是否打开成功

*/

public
int openTty(){

return
_openTty();

}

/**

*
关闭驱动,需要一定时间,所以采用Handler机制

*/

public
int closeTty(){

// mEventHandler.obtainMessage(TTY_CLOSE_DEVICE).sendToTarget();

// return 1;

return
_closeTty();

}

/**

*
发送数据

*
@param data

*
@return

*/

public
int sendMsgToTty(byte[]
data){

return
_sendMsgToTty(data);

}

/**

*
接收数据

*
@param callback

*/

public
final
void receiveMsgFromTty(ReceiveCallback callback){

mReceiveCallBack
= callback;

_receiveMsgFromTty();

}

/**

*
设置串口数据位,校验位,速率,停止位

*
@param databits
数据位
取值
位7或8

*
@param event
校验类型
取值N ,E, O,

*
@param speed
速率
取值 2400,4800,9600,115200

*
@param stopBit
停止位
取值1
或者 2

*/

public
int configTty(int
databits,char event,int
speed,int stopBit){

return
_configTty(databits, event, speed, stopBit);

}

/**

*
@param mode
是否使用原始模式(Raw Mode)方式来通讯
取值0,1,2
说明:0=nothing,1=Raw mode,2=no raw mode

*
@param showLog
打印出串口信息Log
取值1,0

*/

public
int setMode(int
mode ,int showLog){

return
_setMode(mode, showLog);

}

/**

*
接收数据回调接口

*/

public
interface ReceiveCallback{

void
onReceiveData(byte[] data,TtyNativeControl
tty);

}

/****************************************************************

*
本地方法

*/

private
native
final
void native_setup(Object tty_this);

private
native
int _openTty();

private
native
int _closeTty();

private
native
int _sendMsgToTty(byte[]
data);

private
native
void _receiveMsgFromTty();

private
native
int _configTty(int
databits,char event,int
speed,intstopBit);

private
native
int _setMode(int
mode,int showLog);

/*

*
实现底层回调

*/

private
static
void postEventFromNative(Object tty_ref,int
what ,intarg1,int
arg2,Object obj){

Log.i(TAG,
"[postEventFromNative] what:"+what);

TtyNativeControl t = (TtyNativeControl)((WeakReference)tty_ref).get();

if(t
== null)return;

if(t.mEventHandler
!= null){

Message m = t.mEventHandler.obtainMessage(what,
arg1, arg2,obj);

t.mEventHandler.sendMessage(m);

}

}

private
class EventHandler
extends Handler{

private
TtyNativeControl mTty;

public
EventHandler(TtyNativeControl t,Looper looper){

super(looper);

mTty
= t;

}

@Override

public
void handleMessage(Message msg) {

switch(msg.what){

case
TTY_MSG_RECEIVE://底层接收数据回调上来的事件

if(mReceiveCallBack
!= null){

mReceiveCallBack.onReceiveData((byte[])msg.obj,mTty);

}

return;

case
TTY_CLOSE_DEVICE://关闭驱动

_closeTty();

break;

}

}

}

}

2.
JNI
类头文件

#include
<jni.h>


#ifndef _Included_com_notioni_uart_manager_TtyNativeControl

#define _Included_com_notioni_uart_manager_TtyNativeControl

#ifdef __cplusplus

extern
"C"{

#endif

/**

* Class com_notioni_uart_TtyNativeControl

* Method

*/

JNIEXPORT
static
void
JNICALL com_notioni_uart_manager_TtyNativeControl_native_setup(JNIEnv *env,jobject clazz,jobject weak_this);


JNIEXPORT
static
int
JNICALL com_notioni_uart_manager_TtyNativeControl__openTty(JNIEnv *env,jobject clazz);


JNIEXPORT
static
int
JNICALL com_notioni_uart_manager_TtyNativeControl__closeTty(JNIEnv *env,jobject clazz);


JNIEXPORT
static
int
JNICALL com_notioni_uart_manager_TtyNativeControl__sendMsgToTty(JNIEnv *env,jobject clazz,jbyteArray data);


JNIEXPORT
static
void
JNICALL com_notioni_uart_manager_TtyNativeControl__receiveMsgFromTty(JNIEnv *env,jobject clazz);


JNIEXPORT
static
int
JNICALL com_notioni_uart_manager_TtyNativeControl__configTty(JNIEnv *env,jobject clazz,
int
nBits,jchar nEvent,
int
nSpeed,
int
nStop);


JNIEXPORT
static
int
JNICALL com_notioni_uart_manager_TtyNativeControl__setMode(JNIEnv *env,jobject clazz,
int
nMode,
int
showLog);


//JNIEXPORT
int JNICALL com_notioni_uart_manager_TtyNativeControl__setSpeed(JNIEnv *env,jobjectclazz,int speed);

//JNIEXPORT
int JNICALL com_notioni_uart_manager_TtyNativeControl__setParity(JNIEnv *env,jobjectclazz,int databits,int stopbits,int parity);

#ifdef __cplusplus

}

#endif

#endif

3.
JNI
实现类

#include
"JNIHelp.h"


#include
"android_runtime/AndroidRuntime.h"


#include
<utils/misc.h>


#include
<utils/Log.h>


#include
<utils/threads.h>


#include
<pthread.h>


#include
<stdio.h>


#include
<sys/types.h>


#include
<sys/stat.h>


#include
<fcntl.h>


#include
<string.h>


#include
<utils/Log.h>


#include
<sys/ioctl.h>


#include
<termios.h>


#include
"com_notioni_uart_manager_TtyNativeControl.h"

using
namespace android;

struct
fields_t{

jfieldID
tty;

jmethodID
post_event;

};

static
fields_t fields;

JavaVM* g_JavaVM;

#define TTY_DEVICE
"/dev/ttyS2"

#define LOG_TAG
"TtyNativeControl"

#define RECEIVE_DATA_INDEX
(1)

#define POST_EVENT()

static
int mTtyfd = -1;

static
int mOpen = 0;

/**

* class Listener

*/

class
JNIMyObserver{

public:

JNIMyObserver(JNIEnv* env,jobject thiz,jobject weak_thiz);

~JNIMyObserver();

void
OnEvent(const
char* buffer,int
length,int what);

private:

JNIMyObserver();

jclass
mClass;

jobject
mObject;

Mutex
mLock;

};

JNIMyObserver::JNIMyObserver(JNIEnv*
env,jobject thiz,jobject weak_thiz){

jclass clazz = env->GetObjectClass(thiz);

if(clazz
== NULL){

// jniThrowException(env,"java/lang/Exception",NULL);

LOGE("clazz is null");

return;

}

mClass
= (jclass)env->NewGlobalRef(clazz);

mObject
= env->NewGlobalRef(weak_thiz);

LOGW("mClass=%d",mClass);

LOGW("mObject=%d",mObject);

}

JNIMyObserver::~JNIMyObserver(){

JNIEnv *env = AndroidRuntime::getJNIEnv();

env->DeleteGlobalRef(mObject);

env->DeleteGlobalRef(mClass);

}

void
JNIMyObserver::OnEvent(const
char* buffer,int
length,int what){

LOGW("OnEvent");

Mutex::Autolock _l(mLock);

if(NULL
== g_JavaVM){

LOGE("JNIObserver::Event g_JavaVM is NULL");

return;

}

bool
isAttacked = false;

/*

*
创建env指针

*/

JNIEnv* env;

bool
status = (g_JavaVM->GetEnv((void**)
&env,JNI_VERSION_1_4) != JNI_OK);

if(status){

g_JavaVM->AttachCurrentThread(&env,NULL);

}

/*

*
创建JAVA byte[]数组

*/

jbyteArray obj = NULL;

if(buffer
!=NULL && buffer != 0){

const
jbyte* data = reinterpret_cast<const
jbyte*>(buffer);

obj = env->NewByteArray(length);

env->SetByteArrayRegion(obj,0,length,data);

}

env->CallStaticVoidMethod(mClass,fields.post_event,mObject,what,0,0,obj);

if(obj){

env->DeleteLocalRef(obj);

}

if(isAttacked){

g_JavaVM->DetachCurrentThread();//分离线程

}

}

/**

* class Listener end -----------------

*/

JNIMyObserver* listener;

/*

* setup

*/

static
void
JNICALL com_notioni_uart_manager_TtyNativeControl_native_setup(JNIEnv *env,jobject clazz,jobject weak_this){


LOGW("com_notioni_uart_manager_TtyNativeControl_native_setup");

env->GetJavaVM(&g_JavaVM);

if(listener
!= NULL){


delete
listener;


}

listener =
new
JNIMyObserver(env,clazz,weak_this);


}

/*

* _openTty

*/

static
int
JNICALL com_notioni_uart_manager_TtyNativeControl__openTty(JNIEnv *env,jobject clazz){


LOGW("com_notioni_uart_manager_TtyNativeControl__openTty");

mTtyfd = open(TTY_DEVICE,O_RDWR|O_NONBLOCK);//读写方式

if(mTtyfd
< 0){


LOGE("mTtyfd open failure");

return
-1;


}

if(fcntl(mTtyfd,F_SETFL,0)<0){//恢复串口为堵塞状态

LOGE("mTtyfd fcntl failure");

}

// if(isatty(STDIN_FILENO)==0){//测试是否为中断设备,非0即使终端设备

// LOGE("standard inputs is not a terminal device");

// }else{

// LOGE("isatty success");

// }

mOpen = 1;

LOGW("open device success");

return
1;


}

/*

* _closeTty

*/

static
int
JNICALL com_notioni_uart_manager_TtyNativeControl__closeTty(JNIEnv *env,jobject clazz){


LOGW("com_notioni_uart_manager_TtyNativeControl__closeTty");

if(mTtyfd
< 0){


LOGE("mTtyfd open failure ,non't close");

return
-1;


}

mOpen = 0;

sleep(2);//等待线程退出

int
c = close(mTtyfd);


if(c
< 0){


LOGE("mTtyfd close failure");

return
-1;


}

LOGW("close device success");

return
1;


}

/*

* _sendMsgToTty

*/

static
int
JNICALL com_notioni_uart_manager_TtyNativeControl__sendMsgToTty(JNIEnv *env,jobject clazz,jbyteArray data){//byte[]


LOGW("com_notioni_uart_manager_TtyNativeControl__sendMsgToTty");

//jbyte * arrayBody = env->GetByteArrayElements(data,0);
jsize theArrayLengthJ = env->GetArrayLength(data); BYTE * starter = (BYTE *)arrayBody;


if(mTtyfd
< 0){


LOGE("mTtyfd open failure ,non't write");

return
-1;


}

jbyte* arrayData = (jbyte*)env->GetByteArrayElements(data,0);

jsize arrayLength = env->GetArrayLength(data);

char*
byteData = (
char*)arrayData;

int
len = (
int)arrayLength;

LOGW("write data len:%d",len);

int
re = write(mTtyfd,byteData,len);


if(re
== -1){


LOGE("write device error");

}

return
re;


}

/*

*
线程Run

*/

void*
threadreadTtyData(void*
arg){

LOGW("run read data");

if(!(arg)){

return
NULL;

}

char*
buf = new
char[200];

int
result = 0,ret;

fd_set readfd;

struct
timeval timeout;

while(mOpen){

timeout.tv_sec = 2;//设定超时秒数

timeout.tv_usec = 0;//设定超时毫秒数

FD_ZERO(&readfd);//清空集合

FD_SET(mTtyfd,&readfd);///*
把要检测的句柄mTtyfd加入到集合里
*/

ret = select(mTtyfd+1,&readfd,NULL,NULL,&timeout);/*
检测我们上面设置到集合readfd里的句柄是否有可读信息
*/

switch(ret){

case
-1:/*
这说明select函数出错
*/

result = -1;

LOGE("mTtyfd read failure");

break;

case
0:/*
说明在我们设定的时间值5秒加0毫秒的时间内,mTty的状态没有发生变化
*/

break;

default:/*
说明等待时间还未到5秒加0毫秒,mTty的状态发生了变化
*/

if(FD_ISSET(mTtyfd,&readfd)){/*
先判断一下mTty这外被监视的句柄是否真的变成可读的了
*/

int
len = read(mTtyfd,buf,sizeof(buf));

/**发送数据**/

if(!(arg))break;

JNIMyObserver
*l = static_cast<JNIMyObserver
*>(arg);

l->OnEvent(buf,len,RECEIVE_DATA_INDEX);

memset(buf,0,sizeof(buf));

}

break;

}

if(result
== -1){

break;

}

}

if(buf
!= NULL){

delete
buf;

buf = NULL;

}

LOGE("stop run!");

return
NULL;

}

/*

* _receiveMsgFromTty

*/

static
void
JNICALL com_notioni_uart_manager_TtyNativeControl__receiveMsgFromTty(JNIEnv *env,jobject clazz){


LOGW("com_notioni_uart_manager_TtyNativeControl__receiveMsgFromTty");

if(mTtyfd
< 0){


LOGE("mTtyfd open failure ,non't read");

return
;


}

pthread_t id;

int
ret;


ret = pthread_create(&id,NULL,threadreadTtyData,listener);

if(ret
!= 0){


LOGE("create receiver thread failure ");

}else{

LOGW("create read data thred success");

}



}

/**

*
设置串口数据,校验位,速率,停止位

* @param nBits
类型
int数据位
取值
位7或8

* @param nEvent
类型 char
校验类型
取值N ,E, O,,S

* @param mSpeed
类型
int 速率
取值 2400,4800,9600,115200

* @param mStop
类型
int 停止位
取值1
或者 2

*/

int
set_opt(int
nBits,char nEvent,int
nSpeed,int nStop){

LOGW("set_opt:nBits=%d,nEvent=%c,nSpeed=%d,nStop=%d",nBits,nEvent,nSpeed,nStop);

struct
termios newtio,oldtio;

if(tcgetattr(mTtyfd,&oldtio)
!= 0){

LOGE("setup serial failure");

return
-1;

}

bzero(&newtio,sizeof(newtio));

//c_cflag标志可以定义CLOCAL和CREAD,这将确保该程序不被其他端口控制和信号干扰,同时串口驱动将读取进入的数据。CLOCAL和CREAD通常总是被是能的

newtio.c_cflag |=CLOCAL|CREAD;

//newtio.c_cflag &=~CSIZE;

switch(nBits){//设置数据位数

case
7:

newtio.c_cflag &=~CSIZE;

newtio.c_cflag |=CS7;

break;

case
8:

newtio.c_cflag &=~CSIZE;

newtio.c_cflag |=CS8;

break;

default:

LOGW("nBits:%d,invalid
param",nBits);

break;

}

switch(nEvent){//设置校验位

case
'O':

newtio.c_cflag |=PARENB;//enable parity checking

newtio.c_cflag |=PARODD;//奇校验位

newtio.c_iflag |=(INPCK|ISTRIP);

//options.c_iflag |= INPCK;//Disable parity
checking

break;

case
'E':

newtio.c_cflag|=PARENB;//

newtio.c_cflag&=~PARODD;//偶校验位

newtio.c_iflag|=(INPCK|ISTRIP);

//options.c_iflag |= INPCK;//Disable parity
checking

break;

case
'N':

newtio.c_cflag &=~PARENB;//清除校验位

//options.c_iflag &=~INPCK;//Enable parity
checking

break;

//case 'S':

// options.c_cflag &= ~PARENB;//清除校验位

// options.c_cflag &=~CSTOPB;

// options.c_iflag |=INPCK;//Disable parity
checking

// break;

default:

LOGW("nEvent:%c,invalid
param",nEvent);

break;

}

switch(nSpeed){//设置速率

case
2400:

LOGW("B2400:%d",B2400);

cfsetispeed(&newtio,B2400);

cfsetospeed(&newtio,B2400);

break;

case
4800:

LOGW("B4800:%d",B4800);

cfsetispeed(&newtio,B4800);

cfsetospeed(&newtio,B4800);

break;

case
9600:

LOGW("B9600:%d",B9600);

cfsetispeed(&newtio,B9600);

cfsetospeed(&newtio,B9600);

break;

case
115200:

LOGW("B115200:%d",B115200);

cfsetispeed(&newtio,B115200);

cfsetospeed(&newtio,B115200);

break;

default:

cfsetispeed(&newtio,B9600);

cfsetospeed(&newtio,B9600);

LOGW("nSpeed:%d,invalid
param",nSpeed);

break;

}

switch(nStop){//设置停止位

case
1:

newtio.c_cflag &= ~CSTOPB;

break;

case
2:

newtio.c_cflag |= CSTOPB;

break;

default:

LOGW("nStop:%d,invalid
param",nStop);

break;

}

newtio.c_cc[VTIME] = 0;//设置等待时间

newtio.c_cc[VMIN] = 0;//设置最小接收字符

tcflush(mTtyfd,TCIFLUSH);

if(tcsetattr(mTtyfd,TCSANOW,&newtio)
!= 0){

LOGE("options set error");

return
-1;

}

return
1;

}

/*

* _configTty

*/

static
int
JNICALL com_notioni_uart_manager_TtyNativeControl__configTty(JNIEnv *env,jobject clazz,
int
nBits,jchar nEvent,
int
nSpeed,
int
nStop){


LOGW("com_notioni_uart_manager_TtyNativeControl__configTty");

return
set_opt(nBits,nEvent,nSpeed,nStop);


}

int
set_mode(int
nMode,int showLog){

LOGW("set_mode:nMode%d,nshowLog=%d",nMode,showLog);

struct
termios options;

if(tcgetattr(mTtyfd,&options)
!= 0){

LOGE("setup serial failure");

return
-1;

}

int
result = 1;

if(nMode
!= 0){

if(nMode
==1){

options.c_lflag &=~(ICANON | ECHO | ECHOE | ISIG);//input

options.c_oflag &=~OPOST;//out put

}else
if(nMode == 2){

options.c_lflag |=(ICANON | ECHO | ECHOE | ISIG);//input

options.c_oflag |=OPOST;//out put

}

if(tcsetattr(mTtyfd,TCSANOW,&options)
!= 0){

LOGE("tcsetattr device fail");

result = -1;

}

}

if(showLog
== 1){

LOGI("options c_cflag.CS7:%d,CS8:%d",options.c_cflag
& CS7,options.c_cflag & CS8);

LOGI("options c_cflag.PARENB:%d,PARODD:%d",options.c_cflag
& PARENB,options.c_cflag & PARODD);

LOGI("options c_iflag.INPCK%d,ISTRIP:%d",options.c_iflag
& INPCK,options.c_iflag & ISTRIP);

LOGI("option c_ispeed:%d,c_ospeed:%d",cfgetispeed(&options)
,cfgetospeed(&options));

LOGI("options c_cflag.CSTOPB:%d,",options.c_cflag
& CSTOPB);

LOGI("options c_cc.VTIME:%d,VMIN:%d",options.c_cc[VTIME],options.c_cc[VMIN]);

LOGI("options c_cflag.CLOCAL:%d,CREAD:%d",options.c_cflag
& CLOCAL,options.c_cflag&CREAD);

LOGI("options c_lflag.ICANON:%d,ECHO:%d,ECHOE:%d,ISIG:%d",options.c_lflag
& ICANON,options.c_lflag&ECHO,options.c_lflag&ECHOE,options.c_lflag&ISIG);

LOGI("options c_oflag.OPOST:%d,",options.c_oflag
&OPOST);

}

return
result;

}

static
int
JNICALL com_notioni_uart_manager_TtyNativeControl__setMode(JNIEnv *env,jobject clazz,
int
nMode,
int
showLog){


LOGW("com_notioni_uart_manager_TtyNativeControl__setMode");

return
set_mode(nMode,showLog);


}

static JNINativeMethod method_table[]
= {

{"native_setup","(Ljava/lang/Object;)V",(void*)com_notioni_uart_manager_TtyNativeControl_native_setup},

{"_openTty","()I",(void*)com_notioni_uart_manager_TtyNativeControl__openTty},

{"_closeTty","()I",(void*)com_notioni_uart_manager_TtyNativeControl__closeTty},

{"_sendMsgToTty","([B)I",(void*)com_notioni_uart_manager_TtyNativeControl__sendMsgToTty},

{"_receiveMsgFromTty","()V",(void*)com_notioni_uart_manager_TtyNativeControl__receiveMsgFromTty},

{"_configTty","(ICII)I",(void*)com_notioni_uart_manager_TtyNativeControl__configTty},

{"_setMode","(II)I",(void*)com_notioni_uart_manager_TtyNativeControl__setMode},

};

static
const
char* classPathName="com/notioni/uart/manager/TtyNativeControl";

static
int
register_com_notioni_uart_manager_TtyNativeControl(JNIEnv *env){

LOGW("register_com_notioni_uart_manager_TtyNativeControl");

jclass clazz;

clazz = env->FindClass(classPathName);

if(clazz
== NULL){

return
-1;

}

fields.post_event
= env->GetStaticMethodID(clazz,"postEventFromNative",

"(Ljava/lang/Object;IIILjava/lang/Object;)V");

if(fields.post_event
== NULL){

LOGE("Can't find
com/notioni/uart/manager.postEventFromNative");

return
-1;

}

returnAndroidRuntime::registerNativeMethods(env,classPathName,method_table,NELEM(method_table));

}

jint
JNI_OnLoad(JavaVM* vm,void*
reserved){

LOGW("JNI_OnLoad");

JNIEnv* env = NULL;

jint result = -1;

if(vm->GetEnv((void**)&env,JNI_VERSION_1_4)
!= JNI_OK){

goto
bail;

}

LOGW("register
mothod");

assert(env != NULL);

if(register_com_notioni_uart_manager_TtyNativeControl(env)
< 0){

goto
bail;

}

return
JNI_VERSION_1_4;

bail:

return
result;

}

4.
JAVA
层封装本地方法

package com.notioni.uart.manager;

import com.notioni.uart.manager.TtyNativeControl.ReceiveCallback;

/*

*
单例模式

*/

public
class UARTCTLManager
{

private
TtyNativeControl mTtyControl;

private
boolean
mIsOpen =
false;

private
static UARTCTLManager
mManager;

private
UARTCTLManager(){

mTtyControl
= new TtyNativeControl();

}

public
static UARTCTLManager
getInstance(){

if(mManager
== null){

mManager
= new UARTCTLManager();

}

return
mManager;

}

/*

*
打开驱动

*/

public
int openDevice(){

int
o = mTtyControl.openTty();

o=1;

if(o
== 1){

mIsOpen
= true;

}

return
o;

}

/*

*
关闭驱动

*/

public
int closeDevice(){

int
c = mTtyControl.closeTty();

if(c
== 1){

mIsOpen
= false;

}

return
c;

}

/*

*
判断驱动是否打开

*/

public
boolean isOpenDevice(){

return
mIsOpen;

}

/*

*
发送数据

*/

public
int sendDataToDevice(byte[]
data){

return
mTtyControl.sendMsgToTty(data);

}

/*

*
注入接收数据回调方法

*/

public
void receiveDataFromDevice(ReceiveCallback
callback){

mTtyControl.receiveMsgFromTty(callback);

}

/**

*
设置串口数据位,校验位,速率,停止位

*
@param
databits 数据位
取值
位7或8

*
@param
event 校验类型
取值N ,E, O,,S

*
@param
speed 速率
取值 2400,4800,9600,115200

*
@param
stopBit 停止位
取值1
或者 2

*/

public
int configDevice(int
databits,char event,int
speed,int stopBit){

if(!mIsOpen){

return
-1;

}

int
re = mTtyControl.configTty(databits,
event, speed, stopBit);

return
re;

}

/**

*
设置串口通信模式,打印串口信息

*
@param
mode 是否使用原始模式(Raw Mode)方式来通讯
取值0,1,2
说明:0=nothing,1=Raw mode,2=no raw mode

*
@param
showLog 打印出串口信息Log
取值1,0

*
@return

*/

public
int setMode(int
mode ,int showLog){

return
mTtyControl.setMode(mode, showLog);

}

/**

*

*
接收数据回调接口,接收驱动送到的数据要实现这个回调接口

*/

public
interface ReceiveDataCallBack
extends ReceiveCallback{

}

}

5.
JAVA
调用
Activity


package com.notioni.uart;

import com.notioni.uart.manager.TtyNativeControl;

import com.notioni.uart.manager.UARTCTLManager;

import android.app.Activity;

import android.content.Intent;

import android.os.Bundle;

import android.util.Log;

import android.view.Menu;

import android.view.MenuItem;

import android.view.View;

import android.widget.Button;

import android.widget.EditText;

import android.widget.TextView;

public
class UARTCTLActivity
extends Activity
implements View.OnClickListener{

private
static
final String
TAG =
"UARTCTLActivity";

private
UARTCTLManager mUartctlManager;

private
Button mOpenOrCloseBtn;

private
Button mSendBtn;

private
EditText mSendText;

private
TextView mReceiveText;

private
ReceiveData mReceiveData;

/** Called when the activity is first created.
*/

@Override

public
void onCreate(Bundle
savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

mUartctlManager
= UARTCTLManager.getInstance();

mReceiveData
= new ReceiveData();

mOpenOrCloseBtn
= (Button)findViewById(R.id.openOrcloseBtn);

mSendBtn
= (Button)findViewById(R.id.sendBtn);

mSendText
= (EditText)findViewById(R.id.sendMsg);

mReceiveText
= (TextView)findViewById(R.id.receiveMsg);

mOpenOrCloseBtn.setOnClickListener(this);

mSendBtn.setOnClickListener(this);

}

@Override

protected
void onResume() {

super.onResume();

}

@Override

public
void onClick(View
v) {

switch(v.getId()){

case
R.id.openOrcloseBtn://打开或关闭驱动

Log.i(TAG,
"isOpen:"+mUartctlManager.isOpenDevice());

if(mUartctlManager.isOpenDevice()){

mUartctlManager.closeDevice();

mOpenOrCloseBtn.setText(R.string.open);

}else{

int
i =mUartctlManager.openDevice();

Log.i(TAG,
"openDevice result:"+i);

mOpenOrCloseBtn.setText(R.string.close);

mUartctlManager.setMode(1,
1);//查看串口配置信息

}

break;

case
R.id.sendBtn:

openDevice();

int
re = mUartctlManager.sendDataToDevice(getSendText());

Log.i(TAG,
"send result:"+re);

break;

}

}

/*

*
打开驱动

*/

private
void openDevice(){

if(!mUartctlManager.isOpenDevice()){

mUartctlManager.openDevice();

mUartctlManager.receiveDataFromDevice(mReceiveData);

}

}

/*

*
关闭驱动

*/

public
void closeDevice(){

if(mUartctlManager.isOpenDevice()){

mUartctlManager.closeDevice();

}

}

/*

*
取出待发送的数据

*/

private
byte[] getSendText(){

String st =
mSendText.getText().toString()+"\r";

if(st
== null ||
"".equals(st)){

return
null;

}

return
st.getBytes();

}

/*

*
接收数据

*/

class
ReceiveData implements
UARTCTLManager.ReceiveDataCallBack{

@Override

public
void onReceiveData(byte[]
data, TtyNativeControl tty) {

if(mReceiveText
!= null && data !=
null){

Log.w(TAG,
"[onReceiveData] data:"+data.toString());

mReceiveText.setText(data.toString());

}

}

}

@Override

public
boolean onCreateOptionsMenu(Menu
menu) {

menu.add(1,1,0,R.string.config);

return
super.onCreateOptionsMenu(menu);

}

@Override

public
boolean onOptionsItemSelected(MenuItem
item) {

super.onOptionsItemSelected(item);

if(item.getItemId()
== 1){

Intent intent =
new Intent();

intent.setClass(this,
ConfigActivity.class);

startActivity(intent);

}

return
true;

}

@Override

protected
void onPause() {

super.onPause();

// closeDevice();

}

@Override

protected
void onDestroy() {

closeDevice();

super.onDestroy();

}

}

6.
JAVA
配置串口属性

package com.notioni.uart;

import com.notioni.uart.manager.UARTCTLManager;

import android.os.Bundle;

import android.preference.ListPreference;

import android.preference.Preference;

import android.preference.PreferenceActivity;

import android.preference.PreferenceScreen;

import android.util.Log;

import android.widget.Toast;

public
class ConfigActivity
extends PreferenceActivity
implementsPreference.OnPreferenceChangeListener{

private
static
final String
TAG =
"ConfigActivity";

private
static
final String
KEY_DATABITS =
"tty_databits";

private
static
final String
KEY_EVENT =
"tty_event";

private
static
final String
KEY_SPEED =
"tty_speed";

private
static
final String
KEY_STOPBITS =
"tty_stopbits";

ListPreference
dataBitsPrefer ;

ListPreference
eventPrefer ;

ListPreference
speedPrefer ;

ListPreference
stopBitsPrefer ;

Object
dataBitsValues =
null;

Object
eventValues =
null;

Object
speedValues =
null;

Object
stopbitsValues =
null;

@Override

protected
void onCreate(Bundle
savedInstanceState) {

//
TODO Auto-generated
method stub

super.onCreate(savedInstanceState);

addPreferencesFromResource(R.xml.config_options);

PreferenceScreen prefSet = getPreferenceScreen();

dataBitsPrefer
= (ListPreference)prefSet.findPreference(KEY_DATABITS);

eventPrefer
= (ListPreference)prefSet.findPreference(KEY_EVENT);

speedPrefer
= (ListPreference)prefSet.findPreference(KEY_SPEED);

stopBitsPrefer
= (ListPreference)prefSet.findPreference(KEY_STOPBITS);

dataBitsPrefer.setValueIndex(0);

eventPrefer.setValueIndex(0);

speedPrefer.setValueIndex(0);

stopBitsPrefer.setValueIndex(0);

dataBitsPrefer.setOnPreferenceChangeListener(this);

eventPrefer.setOnPreferenceChangeListener(this);

speedPrefer.setOnPreferenceChangeListener(this);

stopBitsPrefer.setOnPreferenceChangeListener(this);

}

@Override

public
boolean onPreferenceChange(Preference
preference, Object newValue) {

if(preference
== dataBitsPrefer){

dataBitsValues
= newValue;

}else
if(preference ==
eventPrefer){

eventValues
= newValue;

}else
if(preference ==
speedPrefer){

speedValues
= newValue;

}else
if(preference ==
stopBitsPrefer){

stopbitsValues
= newValue;

}

Log.i(TAG,
"newValue:"+newValue);

return
false;

}

@Override

protected
void onPause() {

super.onPause();

UARTCTLManager mUartctlManager = UARTCTLManager.getInstance();

int
databits=7,speed=9600,stopbits=1;//设置默认值

char
event='N';//设置默认值

if(dataBitsValues
!= null){

databits = Integer.parseInt(dataBitsValues.toString());

}

if(eventValues
!= null){

event =
eventValues.toString().charAt(0);

}

if(speedValues
!= null){

speed = Integer.parseInt(speedValues.toString());

}

if(stopbitsValues
!= null){

stopbits = Integer.parseInt(stopbitsValues.toString());

}

if(!mUartctlManager.isOpenDevice()){

mUartctlManager.openDevice();

}

Log.e(TAG,"databit="+databits+",event="+event+",speed="+speed+",stopbits="+stopbits);

if(databits
== -1 || speed == -1 || stopbits == -1 || event=='Q'){

Toast.makeText(this,
"有参数没有设置,不去配置串口!",
Toast.LENGTH_LONG).show();

return;

}

mUartctlManager.configDevice(databits, event, speed, stopbits);

mUartctlManager.setMode(0, 1);//查看串口配置信息

// Log.e(TAG, "databit="+databits+",event="+event+",speed="+speed+",stopbits="+stopbits);

}

}

7.
config_options.xml


<?xml
version="1.0"
encoding="utf-8"?>

<PreferenceScreen

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:settings="http://schemas.android.com/apk/res/com.android.settings"

android:key="video_call_fallback_setting"

android:title="@string/tty_settings"

android:persistent="false">

<ListPreference

android:key="tty_databits"

android:title="@string/databits"

android:persistent="true"

android:entries="@array/databits_entries"

android:entryValues="@array/databits_values"

android:summary="data bits"/>

<ListPreference

android:key="tty_event"

android:title="@string/event"

android:persistent="true"

android:entries="@array/event_entries"

android:entryValues="@array/event_values"

android:summary="data bits"/>

<ListPreference

android:key="tty_speed"

android:title="@string/speed"

android:persistent="true"

android:entries="@array/speed_entries"

android:entryValues="@array/speed_values"

android:summary="data bits"/>

<ListPreference

android:key="tty_stopbits"

android:title="@string/stopbits"

android:persistent="true"

android:entries="@array/stopbits_entries"

android:entryValues="@array/stopbits_values"

android:summary="data bits"/>

</PreferenceScreen>

8.
main.xml


<?xml
version="1.0"
encoding="utf-8"?>

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:orientation="vertical"
>

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="60dip"

android:orientation="horizontal"

>

<Button

android:id="@+id/openOrcloseBtn"

android:layout_gravity="center"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/open"

/>

</LinearLayout>

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="60dip"

android:orientation="horizontal"

>

<EditText

android:id="@+id/sendMsg"

android:layout_gravity="left"

android:layout_width="200dip"

android:layout_height="50dip"

/>

<Button

android:id="@+id/sendBtn"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="@string/send"

/>

</LinearLayout>

<LinearLayout

android:layout_width="fill_parent"

android:layout_height="100dip"

android:orientation="horizontal"

>

<TextView

android:id="@+id/receiveMsg"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:text="@string/receiveData"
/>

</LinearLayout>

</LinearLayout>

9.
string.xml


<?xml
version="1.0"
encoding="utf-8"?>

<resources>

<string
name="hello">Hello World, UARTCTLActivity!</string>

<string
name="receiveData">Receive data show!</string>

<string
name="app_name">UARTCTL</string>

<string
name="open">Open</string>

<string
name="close">Close</string>

<string
name="send">Send</string>

<string
name="config">Config</string>

<string
name="tty_settings">Settings</string>

<string
name="databits">Data bits</string>

<string
name="event">Event</string>

<string
name="speed">Speed</string>

<string
name="stopbits">Stop bits</string>

<string-array
name="databits_entries">

<item>-1</item>

<item>7</item>

<item>8</item>

</string-array>

<string-array
name="databits_values">

<item>-1</item>

<item>7</item>

<item>8</item>

</string-array>

<string-array
name="event_entries">

<item>Settings</item>

<item>None</item>

<item>Event</item>

<item>Odd</item>

</string-array>

<string-array
name="event_values">

<item>Q</item>

<item>N</item>

<item>E</item>

<item>O</item>

</string-array>

<string-array
name="speed_entries">

<item>-1</item>

<item>B2400</item>

<item>B4800</item>

<item>B9600</item>

<item>B115200</item>

</string-array>

<string-array
name="speed_values">

<item>-1</item>

<item>2400</item>

<item>4800</item>

<item>9600</item>

<item>115200</item>

</string-array>

<string-array
name="stopbits_entries">

<item>-1</item>

<item>1</item>

<item>2</item>

</string-array>

<string-array
name="stopbits_values">

<item>-1</item>

<item>1</item>

<item>2</item>

</string-array>

</resources>

10.
Android.mk


LOCAL_PATH:=$(call
my-dir)

include
$(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_SRC_FILES :=
$(call all-java-files-under,src)

#LOCAL_JAVA_LIBRARIES := uart-ctl

LOCAL_JNI_SHARED_LIBRARIES := uart_ctl #so文件打包到apk中

LOCAL_PACKAGE_NAME := UARTCTL

#LOCAL_CERTIFICATE := platform

include
$(BUILD_PACKAGE)

include
$(LOCAL_PATH)/jni/Android.mk

include
$(call all-makefiles-under,$(LOCAL_PATH))

11.
jni/Android.mk

LOCAL_PATH:=$(call
my-dir)

include
$(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_SRC_FILES:= \

com_notioni_uart_manager_TtyNativeControl.cpp

LOCAL_C_INCLUDES := \

$(JNI_H_INCLUDE)

LOCAL_SHARED_LIBRARIES := \

libcutils \

libutils \

libui \

libandroid_runtime

LOCAL_PRELINK_MODULE := false

LOCAL_MODULE := uart_ctl

include
$(BUILD_SHARED_LIBRARY)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: