Android通过JNI操作串口

Android通过JNI操作串口

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,int stopBit);

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

   

    /*

     * 实现底层回调

     */

    private static void postEventFromNative(Object tty_ref,int what ,int arg1,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,jobject clazz,int speed);
//JNIEXPORT  int JNICALL com_notioni_uart_manager_TtyNativeControl__setParity(JNIEnv *env,jobject clazz,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;
    }
    return AndroidRuntime::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 implements Preference.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)




  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值