Android串口例子
一个月后需要参加新大陆的物联网大赛,这几天开始集训了,我负责Android这一块,这里面需要用到android串口技术,然后就轰轰烈烈就开始做了,查资料。终于在今天做出来了一个,废话了,赶紧来。
这里需要用到官方提供的例程源代码开源的串口类android-serialport-api。其主页在这里http://code.google.com/p/android-serialport-api/但是下载下来发现并不知道怎么用,然后就又查资料。主要还是借鉴这位仁兄的。http://lpcjrflsa.iteye.com/blog/2097280。
1 首先做的是创建新的工程然后添加一下文件
我所说的添加的文件并不是和官方提供的例程源代码开源的串口类android-serialport-api。完全一样 我下的就是完全一样的 ,这个官方的好像是新的或是旧的,就两句代码是不样的
还有几处就不一一点出了,总之差别不大,多一个Tag参数,不过新手还是别管他。最好用我提供的代码。第一次发不知道怎么附件代码,一会再说把。
2 布局
接下来就是先写个布局呗,这是我写的 比我看到的Demo我有添加了一个清除接收数据的按钮。
我想这种问题你们都不是事,/////////!!!!!!!!!!!这几个粉红色的字是按钮控件,我把背景设成透明了别误会了。
3代码
好了 然后就是关于这个页面的Code了,
这是我的:
package android.serialport; import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.text.BreakIterator;import java.util.ServiceConfigurationError; import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.view.View;import android.view.View.OnClickListener;import android.view.Window;import android.widget.Button;import android.widget.EditText;import android.widget.Toast; public class MyserialActivity extendsActivity{ EditText sendedit; EditText receiveedit; FileInputStream mInStream; FileOutputStream mOutStream; SerialPort classserialport; ReadThread mReadThread; private class ReadThread extends Thread { public void run() { super.run(); while(!isInterrupted()) { int size; } } } void onDataReceive(final byte[] buffer,finalint size) { runOnUiThread(new Runnable() { @Override publicvoid run() { // TODO Auto-generated method stub if(mReadThread != null) { receiveedit.append(newString(buffer,0,size)); } } }); } @Override protectedvoid onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); this.requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_myserial); sendedit= (EditText)findViewById(R.id.editText1); receiveedit=(EditText)findViewById(R.id.editText2); receiveedit.setFocusable(false);//进制输入 /* * 打开串口 * */ finalButton openserial =(Button)findViewById(R.id.button1); openserial.setOnClickListener(newView.OnClickListener() { @Override publicvoid onClick(View arg0) { //TODO Auto-generated method stub try { classserialport=new SerialPort(new File("/dev/ttyS2"),9600); }catch(SecurityExceptione) { e.printStackTrace(); } catch(IOExceptione) { e.printStackTrace(); } mInStream=(FileInputStream) classserialport.getInputStream(); Toast.makeText(MyserialActivity.this,"串口打开成功",Toast.LENGTH_SHORT).show(); } }); /* * 发送数据 * */ finalButton sendButton =(Button)findViewById(R.id.button2); sendButton.setOnClickListener(newView.OnClickListener() { @Override publicvoid onClick(View arg0) { Stringindata; indata=sendedit.getText().toString(); //TODO Auto-generated method stub try { mOutStream=(FileOutputStream) classserialport.getOutputStream(); mOutStream.write(indata.getBytes()); mOutStream.write('\n'); } catch(IOExceptione) { e.printStackTrace(); } Toast.makeText(MyserialActivity.this,"数据发送成功",Toast.LENGTH_SHORT).show(); sendedit.setText(""); } }); /* * 接收数据 * */ finalButton receButton= (Button)findViewById(R.id.button3); receButton.setOnClickListener(newView.OnClickListener() {//inttag =0; @Override publicvoid onClick(View arg0) { // TODO Auto-generated method stub intsize; try { byte[]buffer = new byte[64]; if(mInStream== null) return; size= mInStream.read(buffer); if(size>0) { receiveedit.setText(""); } if(size>0) { onDataReceive(buffer,size); } inttag =1; receiveedit.setText(newString(buffer, 0, size)); }catch(IOExceptione) { e.printStackTrace(); return; } } privateboolean isInterrupted() { // TODO Auto-generated methodstub returnfalse; } }); /* * 清楚接收区 * */ finalButton ClearButton = (Button)findViewById(R.id.clear); ClearButton.setOnClickListener(newView.OnClickListener() { @Override publicvoid onClick(View arg0) { //TODO Auto-generated method stub receiveedit.setText(""); } }); } @Override publicboolean onCreateOptionsMenu(Menu menu) { //Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.myserial,menu); returntrue; } }
好吧 你做好了。
3需要加载的文件
下面我把所需要添加的代码贴一贴
第一个是Serialport.java
/* * Copyright 2009 Cedric Priscal * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package android.serialport;import java.io.File;import java.io.FileDescriptor;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import android.util.Log;public class SerialPort {private static final String TAG = "SerialPort";/* * Do not remove or rename the field mFd: it is used by native method close(); */private FileDescriptor mFd; //创建一个文件描述符对象 mFdprivate FileInputStream mFileInputStream;private FileOutputStream mFileOutputStream;public SerialPort(File device, int baudrate) throws SecurityException, IOException {/* * 检查访问权限 * *//* Check access permission */if (!device.canRead() || !device.canWrite()) {//如果设备不可读或者设备不可写try {/* Missing read/write permission, trying to chmod the file *///没有读写权限,就尝试去挂载权限Process su; //流程进程 susu = Runtime.getRuntime().exec("/system/bin/su");//通过执行挂载到/system/bin/su 获得执行String cmd = "chmod 777 " + device.getAbsolutePath() + "\n"+ "exit\n";/*String cmd = "chmod 777 /dev/s3c_serial0" + "\n"+ "exit\n";*/su.getOutputStream().write(cmd.getBytes());//进程。获得输出流。写(命令。获得二进制) if ((su.waitFor() != 0) || !device.canRead()|| !device.canWrite()) {//如果 进程等待不是0 或者 设备不能读写就throw new SecurityException();//抛出一个权限异常}} catch (Exception e) {e.printStackTrace();throw new SecurityException();}}/* * * */mFd = open(device.getAbsolutePath(), baudrate);//device.getAbsolutePath()这是要挂载的路径new File("/dev/ttyS2")if (mFd == null) {Log.e(TAG, "native open returns null");throw new IOException();//输入输出异常}//将文件描述符 做输入输出流的参数 传递给创建的输入输出流mFileInputStream = new FileInputStream(mFd);mFileOutputStream = new FileOutputStream(mFd);}// Getters and setterspublic InputStream getInputStream() {return mFileInputStream;}public OutputStream getOutputStream() {return mFileOutputStream;}// JNIprivate native static FileDescriptor open(String path, int baudrate);public native void close();static {System.loadLibrary("serial_port");}}
第二个是SerialPortFinder.java
/* * Copyright 2009 Cedric Priscal * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package android.serialport;import java.io.File;import java.io.FileReader;import java.io.IOException;import java.io.LineNumberReader;import java.util.Iterator;import java.util.Vector;import android.util.Log;public class SerialPortFinder {/* * 创建一个驱动程序类 * */public class Driver {public Driver(String name, String root) {mDriverName = name;//String 类型的mDeviceRoot = root;}private String mDriverName;private String mDeviceRoot;Vector<File> mDevices = null;/* * Vector 类在 java 中可以实现自动增长的对象数组 * 简单的使用方法如下:vector<int> test;//建立一个vectortest.push_back(1);test.push_back(2);//把1和2压入vector这样test[0]就是1,test[1]就是2 * */public Vector<File> getDevices() {if (mDevices == null) {mDevices = new Vector<File>();File dev = new File("/dev");File[] files = dev.listFiles();int i;for (i=0; i<files.length; i++) {if (files[i].getAbsolutePath().startsWith(mDeviceRoot)) {Log.d(TAG, "Found new device: " + files[i]);mDevices.add(files[i]);}}}return mDevices;}public String getName() {return mDriverName;}}/* * * * */private static final String TAG = "SerialPort";private Vector<Driver> mDrivers = null;Vector<Driver> getDrivers() throws IOException {if (mDrivers == null) {mDrivers = new Vector<Driver>();LineNumberReader r = new LineNumberReader(new FileReader("/proc/tty/drivers"));String l;while((l = r.readLine()) != null) {String[] w = l.split(" +");if ((w.length == 5) && (w[4].equals("serial"))) {Log.d(TAG, "Found new driver: " + w[1]);mDrivers.add(new Driver(w[0], w[1]));}}r.close();}return mDrivers;}public String[] getAllDevices() {Vector<String> devices = new Vector<String>();// Parse each driverIterator<Driver> itdriv;try {itdriv = getDrivers().iterator();while(itdriv.hasNext()) {Driver driver = itdriv.next();Iterator<File> itdev = driver.getDevices().iterator();while(itdev.hasNext()) {String device = itdev.next().getName();String value = String.format("%s (%s)", device, driver.getName());devices.add(value);}}} catch (IOException e) {e.printStackTrace();}return devices.toArray(new String[devices.size()]);}public String[] getAllDevicesPath() {Vector<String> devices = new Vector<String>();// Parse each driverIterator<Driver> itdriv;try {itdriv = getDrivers().iterator();while(itdriv.hasNext()) {Driver driver = itdriv.next();Iterator<File> itdev = driver.getDevices().iterator();while(itdev.hasNext()) {String device = itdev.next().getAbsolutePath();devices.add(device);}}} catch (IOException e) {e.printStackTrace();}return devices.toArray(new String[devices.size()]);}}
第三个是Android.mk
## Copyright 2009 Cedric Priscal# # Licensed under the Apache License, Version 2.0 (the "License");# you may not use this file except in compliance with the License.# You may obtain a copy of the License at# # http://www.apache.org/licenses/LICENSE-2.0# # Unless required by applicable law or agreed to in writing, software# distributed under the License is distributed on an "AS IS" BASIS,# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.# See the License for the specific language governing permissions and# limitations under the License. #LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)TARGET_PLATFORM := android-3LOCAL_MODULE := serial_portLOCAL_SRC_FILES := SerialPort.cLOCAL_LDLIBS := -lloginclude $(BUILD_SHARED_LIBRARY)
第四个是SerialPort.c
/* * Copyright 2009 Cedric Priscal * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include <termios.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <string.h>#include <jni.h>#include "android/log.h"static const char *TAG="serial_port";#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args)#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)static speed_t getBaudrate(jint baudrate){switch(baudrate) {case 0: return B0;case 50: return B50;case 75: return B75;case 110: return B110;case 134: return B134;case 150: return B150;case 200: return B200;case 300: return B300;case 600: return B600;case 1200: return B1200;case 1800: return B1800;case 2400: return B2400;case 4800: return B4800;case 9600: return B9600;case 19200: return B19200;case 38400: return B38400;case 57600: return B57600;case 115200: return B115200;case 230400: return B230400;case 460800: return B460800;case 500000: return B500000;case 576000: return B576000;case 921600: return B921600;case 1000000: return B1000000;case 1152000: return B1152000;case 1500000: return B1500000;case 2000000: return B2000000;case 2500000: return B2500000;case 3000000: return B3000000;case 3500000: return B3500000;case 4000000: return B4000000;default: return -1;}}/* * Class: cedric_serial_SerialPort * Method: open * Signature: (Ljava/lang/String;)V */JNIEXPORT jobject JNICALL Java_android_serialport_SerialPort_open (JNIEnv *env, jobject thiz, jstring path, jint baudrate){int fd;speed_t speed;jobject mFileDescriptor;/* Check arguments */{speed = getBaudrate(baudrate);if (speed == -1) {/* TODO: throw an exception */LOGE("Invalid baudrate");return NULL;}}/* Opening device */{jboolean iscopy;const char *path_utf = (*env)->GetStringUTFChars(env, path, &iscopy);LOGD("Opening serial port %s", path_utf);fd = open(path_utf, O_RDWR | O_DIRECT | O_SYNC);LOGD("open() fd = %d", fd);(*env)->ReleaseStringUTFChars(env, path, path_utf);if (fd == -1){/* Throw an exception */LOGE("Cannot open port");/* TODO: throw an exception */return NULL;}}/* Configure device */{struct termios cfg;LOGD("Configuring serial port");if (tcgetattr(fd, &cfg)){LOGE("tcgetattr() failed");close(fd);/* TODO: throw an exception */return NULL;}cfmakeraw(&cfg);cfsetispeed(&cfg, speed);cfsetospeed(&cfg, speed);if (tcsetattr(fd, TCSANOW, &cfg)){LOGE("tcsetattr() failed");close(fd);/* TODO: throw an exception */return NULL;}}/* Create a corresponding file descriptor */{jclass cFileDescriptor = (*env)->FindClass(env, "java/io/FileDescriptor");jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor, "<init>", "()V");jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor, "descriptor", "I");mFileDescriptor = (*env)->NewObject(env, cFileDescriptor, iFileDescriptor);(*env)->SetIntField(env, mFileDescriptor, descriptorID, (jint)fd);}return mFileDescriptor;}/* * Class: cedric_serial_SerialPort * Method: close * Signature: ()V */JNIEXPORT void JNICALL Java_android_serialport_SerialPort_close (JNIEnv *env, jobject thiz){jclass SerialPortClass = (*env)->GetObjectClass(env, thiz);jclass FileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor");jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd", "Ljava/io/FileDescriptor;");jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor", "I");jobject mFd = (*env)->GetObjectField(env, thiz, mFdID);jint descriptor = (*env)->GetIntField(env, mFd, descriptorID);LOGD("close(fd = %d)", descriptor);close(descriptor);}
接下来还要添加库这个需要添加文件(文件一会再传)一会给你们一个例子自己可以裁剪。
4运行
这个串口通讯就完成了。
接下来就需要用在Windows 中的DOS下进行一下操作//这样是为了打开串口Com2 获得串口权限 (如果adb emulator 不是内部外部命令的话就去配置环境变量那就去百度一下怎么配置adb 和 emulator.的环境变量。
运行后把APP装进去
然后下载一个串口调试助手 就可以进行调试了。
你就一台电脑而且没有串口线的时候你就可以下载一个虚拟串口软件 我今天才发现的神器名字是Configure Virtual Serial Port Driver
自己做的 程序源代码 实例在这里 你们可以下载一下http://download.csdn.net/detail/csdnhejingzhou/9181897
然后看结果
本文章借鉴了http://lpcjrflsa.iteye.com/blog/2097280。
更多相关文章
- NPM 和webpack 的基础使用
- 【阿里云镜像】使用阿里巴巴DNS镜像源——DNS配置教程
- Android高手进阶教程(七)之----Android(安卓)中Preferences的使
- AndroidManifest.xml文件剖析 (二)
- Android(安卓)引用外部字体
- 传智播客Android视频教程——第五天
- android之用户定位(一)
- Android中的五大存储
- android国际化操作