Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

android usb转串口数据通信示例

$
0
0

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 原文链接
阅读:14 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>