Android通过JNI操作串口

来源:互联网 发布:windows hadoop安装包 编辑:程序博客网 时间:2024/05/20 10:10

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 __cplusplusextern "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)




0 0
原创粉丝点击