usb转串口数据通信示例。物联网开发中也会经常用到usb转串口,对android手机进行通信。一般都会用otc线进行转换。我在GitHub下来一份代码,亲测可用。并进行了修改封装。
GitHub网址:https://github.com/mik3y/usb-serial-for-android
这篇博客代码的地址:http://download.csdn.net/download/qq_16064871/9978818
第一次使用的时候,需要选择app调试
扫描界面,当有接口有连接的话,还有直接反应,跳转到这个界面。并有1秒扫描一次。
接受数据的界面,原始demo界面
代码封装后,重新写的接受数据的界面
设备扫描
/* Copyright 2011-2013 Google Inc.
* Copyright 2013 mike wakerly
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* Project home page: https://github.com/mik3y/usb-serial-for-android
*/
package com.hoho.android.usbserial.examples;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.TwoLineListItem;
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.hoho.android.usbserial.util.HexDump;
import java.util.ArrayList;
import java.util.List;
import src.com.hoho.android.usbserial.examples.UsbSerialPortTopIO;
/**
* Shows a {@link ListView} of available USB devices.
*
* @author mike wakerly ([email protected])
*/
public class DeviceListActivity extends Activity {
private final String TAG = DeviceListActivity.class.getSimpleName();
private UsbManager mUsbManager;
private ListView mListView;
private TextView mProgressBarTitle;
private ProgressBar mProgressBar;
private static final int MESSAGE_REFRESH = 101;
private static final long REFRESH_TIMEOUT_MILLIS = 5000;
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_REFRESH:
refreshDeviceList();
mHandler.sendEmptyMessageDelayed(MESSAGE_REFRESH, REFRESH_TIMEOUT_MILLIS);
break;
default:
super.handleMessage(msg);
break;
}
}
};
private List mEntries = new ArrayList();
private ArrayAdapter mAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
mListView = (ListView) findViewById(R.id.deviceList);
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mProgressBarTitle = (TextView) findViewById(R.id.progressBarTitle);
mAdapter = new ArrayAdapter(this,
android.R.layout.simple_expandable_list_item_2, mEntries) {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final TwoLineListItem row;
if (convertView == null){
final LayoutInflater inflater =
(LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = (TwoLineListItem) inflater.inflate(android.R.layout.simple_list_item_2, null);
} else {
row = (TwoLineListItem) convertView;
}
final UsbSerialPort port = mEntries.get(position);
final UsbSerialDriver driver = port.getDriver();
final UsbDevice device = driver.getDevice();
final String title = String.format("Vendor %s Product %s",
HexDump.toHexString((short) device.getVendorId()),
HexDump.toHexString((short) device.getProductId()));
row.getText1().setText(title);
final String subtitle = driver.getClass().getSimpleName();
row.getText2().setText(subtitle);
return row;
}
};
mListView.setAdapter(mAdapter);
mListView.setOnItemClickListener(new ListView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view, int position, long id) {
Log.d(TAG, "Pressed item " + position);
if (position >= mEntries.size()) {
Log.w(TAG, "Illegal position.");
return;
}
final UsbSerialPort port = mEntries.get(position);
showConsoleActivity(port);
}
});
}
@Override
protected void onResume() {
super.onResume();
mHandler.sendEmptyMessage(MESSAGE_REFRESH);
}
@Override
protected void onPause() {
super.onPause();
mHandler.removeMessages(MESSAGE_REFRESH);
}
private void refreshDeviceList() {
showProgressBar();
new AsyncTask>() {
@Override
protected List doInBackground(Void... params) {
Log.d(TAG, "Refreshing device list ...");
SystemClock.sleep(1000);
final List drivers =
UsbSerialProber.getDefaultProber().findAllDrivers(mUsbManager);
final List result = new ArrayList();
for (final UsbSerialDriver driver : drivers) {
final List ports = driver.getPorts();
Log.d(TAG, String.format("+ %s: %s port%s",
driver, Integer.valueOf(ports.size()), ports.size() == 1 ? "" : "s"));
result.addAll(ports);
}
return result;
}
@Override
protected void onPostExecute(List result) {
mEntries.clear();
mEntries.addAll(result);
mAdapter.notifyDataSetChanged();
mProgressBarTitle.setText(
String.format("%s device(s) found",Integer.valueOf(mEntries.size())));
hideProgressBar();
Log.d(TAG, "Done refreshing, " + mEntries.size() + " entries found.");
}
}.execute((Void) null);
}
private void showProgressBar() {
mProgressBar.setVisibility(View.VISIBLE);
mProgressBarTitle.setText(R.string.refreshing);
}
private void hideProgressBar() {
mProgressBar.setVisibility(View.INVISIBLE);
}
private void showConsoleActivity(UsbSerialPort port) {
UsbSerialPortTopIO.GetInstance().SetUsbSerialPort(this,port);
final Intent intent = new Intent(this, com.hoho.android.usbserial.examples.CustomSerialConsoleActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
// com.hoho.android.usbserial.examples.SerialConsoleActivity.show(this,port);
}
}
进行了简单的封装类
封装时候遇到最大问题就是,连接失败。连接失败,记得释放资源,调用这个方法 onDeviceStateChange();
package src.com.hoho.android.usbserial.examples;
import android.content.Context;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbManager;
import android.location.LocationManager;
import android.util.Log;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.util.SerialInputOutputManager;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class UsbSerialPortTopIO {
private volatile static UsbSerialPortTopIO usbSerialPortTopIO = null;
private static UsbSerialPort sPort = null;
private final String TAG = "Show";
private static Context mContext = null;
public static UsbSerialPortTopIO GetInstance() {
if (usbSerialPortTopIO == null ) {
synchronized (UsbSerialPortTopIO.class){
if (usbSerialPortTopIO == null){
usbSerialPortTopIO = new UsbSerialPortTopIO();
}
}
}
return usbSerialPortTopIO;
}
ConnectListener mConnectListener = null;
public void RegConnectListener(ConnectListener arg0) {
mConnectListener = arg0;
}
TopDataIOListener mIOListener = null;
public void RegIOListener(TopDataIOListener arg0) {
mIOListener = arg0;
}
public void UnRegIOListener() {
mIOListener = null;
}
public boolean SendData(int nLength, byte[] data) {
if (mSerialIoManager != null) {
mSerialIoManager.writeAsync(data);
}
return false;
}
public void Connect() {
onDeviceStateChange();
Log.d(TAG, "Resumed, port=" + sPort);
if (sPort == null) {
if (null != mConnectListener)
mConnectListener.OnConnectStatusCallBack(false);
} else {
final UsbManager usbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);
UsbDeviceConnection connection = usbManager.openDevice(sPort.getDriver().getDevice());
if (connection == null) {
if (null != mConnectListener)
mConnectListener.OnConnectStatusCallBack(false);
return;
}
try {
sPort.open(connection);
sPort.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
} catch (IOException e) {
if (null != mConnectListener)
mConnectListener.OnConnectStatusCallBack(false);
try {
sPort.close();
} catch (IOException e2) {
if (null != mConnectListener)
mConnectListener.OnConnectStatusCallBack(false);
}
sPort = null;
return;
}
if (null != mConnectListener)
mConnectListener.OnConnectStatusCallBack(true);
}
}
public void DisConnect() {
stopIoManager();
if (sPort != null) {
try {
sPort.close();
} catch (IOException e) {
// Ignore.
}
sPort = null;
}
}
public boolean SetUsbSerialPort(Context context, UsbSerialPort port) {
sPort = port;
mContext = context.getApplicationContext();
return true;
}
public UsbSerialPortTopIO() {
}
private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
private SerialInputOutputManager mSerialIoManager;
private final SerialInputOutputManager.Listener mListener =
new SerialInputOutputManager.Listener() {
@Override
public void onRunError(Exception e) {
Log.d("Show", "Runner stopped.");
if (mIOListener != null)
mIOListener.OnIOCallBack(e.toString().getBytes().length, e.toString().getBytes());
onDeviceStateChange();
}
@Override
public void onNewData(final byte[] data) {
if (mIOListener != null)
mIOListener.OnIOCallBack(data.length, data);
}
};
private void stopIoManager() {
if (mSerialIoManager != null) {
Log.i(TAG, "Stopping io manager ..");
mSerialIoManager.stop();
mSerialIoManager = null;
}
}
private void startIoManager() {
if (sPort != null) {
Log.i(TAG, "Starting io manager ..");
mSerialIoManager = new SerialInputOutputManager(sPort, mListener);
mExecutor.submit(mSerialIoManager);
}
}
private void onDeviceStateChange() {
stopIoManager();
startIoManager();
}
}
针对上面代码封装后,可以进行简单方便的调用
public class CustomSerialConsoleActivity extends Activity {
/**
* Driver instance, passed in statically via
*
*
* This is a devious hack; it'd be cleaner to re-create the driver using
* arguments passed in with the {@link #startActivity(Intent)} intent. We
* can get away with it because both activities will run in the same
* process, and this is a simple demo.
*/
private TextView mDumpTextView;
private ScrollView mScrollView;
private TextView mTitleTextView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.serial_console2);
mDumpTextView = (TextView) findViewById(R.id.consoleText);
mScrollView = (ScrollView) findViewById(R.id.demoScroller);
mTitleTextView = (TextView) findViewById(R.id.demoTitle);
UsbSerialPortTopIO.GetInstance().RegConnectListener(mConnectListener);
UsbSerialPortTopIO.GetInstance().RegIOListener(topDataIOListener);
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
UsbSerialPortTopIO.GetInstance().Connect();
}
});
}
//接收数据IO
private TopDataIOListener topDataIOListener = new TopDataIOListener() {
@Override
public void OnIOCallBack(int nLength,final byte[] data) {
CustomSerialConsoleActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
CustomSerialConsoleActivity.this.updateReceivedData(data);
}
});
}
};
private ConnectListener mConnectListener = new ConnectListener() {
@Override
public void OnConnectStatusCallBack(boolean bSucceed) {
if (bSucceed){
mTitleTextView.setText("succeed");
}else {
mTitleTextView.setText("faile");
}
}
@Override
public void OnDisConnectCallBack() {
}
};
@Override
protected void onPause() {
super.onPause();
}
@Override
public void finish() {
UsbSerialPortTopIO.GetInstance().DisConnect();
super.finish();
}
@Override
protected void onResume() {
super.onResume();
}
private void updateReceivedData(byte[] Data) {
final String message = "Read " + Data.length + " bytes: \n"
+ HexDump.dumpHexString(Data) + "\n\n";
mDumpTextView.append(message);
mScrollView.smoothScrollTo(0, mDumpTextView.getBottom());
}
}
暂时发现这份代码比较通用,网上有人说不同的芯片,代码不一样。
我测试机器是系统5.0以上的。
测试了一个4.2的系统,测试不通过。
建议:1、出现失败情况下,记得换一下android 机器进行测试。
2、一直失败情况下,记得卸载所有与串口调试的应用。因为串口授权(就是图一:为USB设备选择一个应用程序)。只授权一个。所以卸载所有授权的,或者清除授权。重新测试。