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)
- Android通过JNI操作串口
- Android通过JNI操作串口
- Android通过JNI操作串口《一》
- Android通过JNI操作串口《二》
- Android通过JNI操作串口《三》
- Android通过JNI操作串口《四》
- Android通过JNI实现与C语言的串口通讯操作蓝牙硬件模块
- Android - JNI 串口通信
- android 串口通讯 JNI
- android 串口jni 开发流程
- Android Studio 串口jni开发
- Android开发之jni串口
- Android开发之jni串口
- Android JNI操作指南
- android jni操作数组
- android jni操作数组
- Android JNI数组操作
- android串口操作
- Golang(Go语言)的三大设计目标
- java23种设计模式详解
- Apple Pay出场带热NFC 国产手机厂商拥抱银联
- openwrt make menuconfig 选项
- 二层攻击之:mac层攻击
- Android通过JNI操作串口
- protoc-gen-lua message之间相互引用问题 导致 upvalue 'message_type' (a nil value)
- MySQL server has gone away
- validation插件
- CodeForces 628A Tennis Tournament
- OpenWrt路由器WIFI开启13信道
- iOS socket
- 如何增量导入MYSQL数据库中的数据
- Swift - whose view is not in the window hierarchy 问题解决方法