usb转串口数据通信示例。物联网开发中也会经常用到usb转串口,对android手机进行通信。一般都会用otc线进行转换。我在GitHub下来一份代码,亲测可用。并进行了修改封装。
GitHub网址:https://github.com/mik3y/usb-serial-for-android
这篇博客代码的地址:http://download.csdn.net/download/qq_16064871/9978818
1、实现效果
第一次使用的时候,需要选择app调试
扫描界面,当有接口有连接的话,还有直接反应,跳转到这个界面。并有1秒扫描一次。
接受数据的界面,原始demo界面
代码封装后,重新写的接受数据的界面
2、代码示例
设备扫描
/* Copyright 2011-2013 Google Inc. * Copyright 2013 mike wakerly <opensource@hoho.com> * * 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 (opensource@hoho.com) */ 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<UsbSerialPort> mEntries = new ArrayList<UsbSerialPort>(); private ArrayAdapter<UsbSerialPort> 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<UsbSerialPort>(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<Void, Void, List<UsbSerialPort>>() { @Override protected List<UsbSerialPort> doInBackground(Void... params) { Log.d(TAG, "Refreshing device list ..."); SystemClock.sleep(1000); final List<UsbSerialDriver> drivers = UsbSerialProber.getDefaultProber().findAllDrivers(mUsbManager); final List<UsbSerialPort> result = new ArrayList<UsbSerialPort>(); for (final UsbSerialDriver driver : drivers) { final List<UsbSerialPort> 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<UsbSerialPort> 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); } }
3、接收数据
进行了简单的封装类
封装时候遇到最大问题就是,连接失败。连接失败,记得释放资源,调用这个方法 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(); } }
3、怎么调用
针对上面代码封装后,可以进行简单方便的调用
public class CustomSerialConsoleActivity extends Activity { /** * Driver instance, passed in statically via * * <p/> * 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()); } }
4、权限
<uses-feature android:name="android.hardware.usb.host" />
activity 扫描界面权限
<activity android:name="com.hoho.android.usbserial.examples.DeviceListActivity" android:label="@string/app_name" android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" /> </intent-filter> <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" android:resource="@xml/device_filter" /> </activity>
GitHub代码里面有一个usbSerialForAndroid是源码。我在自已的demo有打包成jar包。进行调用。
暂时发现这份代码比较通用,网上有人说不同的芯片,代码不一样。
我测试机器是系统5.0以上的。
测试了一个4.2的系统,测试不通过。
建议:1、出现失败情况下,记得换一下android 机器进行测试。
2、一直失败情况下,记得卸载所有与串口调试的应用。因为串口授权(就是图一:为USB设备选择一个应用程序)。只授权一个。所以卸载所有授权的,或者清除授权。重新测试。
作者:qq_16064871 发表于2017/9/15 9:45:47 原文链接
阅读:198 评论:0 查看评论