Android USB通讯(完整版)

Android USB通讯(完整版)_第1张图片

1.Host端代码:

package com.tcl.navigator.hostchart.activity;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.tcl.navigator.hostchart.R;
import com.tcl.navigator.hostchart.base.MyApplication;
import com.tcl.navigator.hostchart.receiver.OpenDevicesReceiver;
import com.tcl.navigator.hostchart.receiver.UsbDetachedReceiver;

import java.util.Collection;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 
 */

public class MainActivity extends AppCompatActivity implements UsbDetachedReceiver.UsbDetachedListener, OpenDevicesReceiver.OpenDevicesListener, View.OnClickListener {

    private static final int    CONNECTED_SUCCESS        = 0;
    private static final int    RECEIVER_MESSAGE_SUCCESS = 1;
    private static final int    SEND_MESSAGE_SUCCESS     = 2;
    private static final String USB_ACTION               = "com.tcl.navigator.hostchart";
    private TextView            mLog;
    private EditText            mMessage;
    private UsbDetachedReceiver mUsbDetachedReceiver;
    private ExecutorService     mThreadPool;
    private UsbManager          mUsbManager;
    private OpenDevicesReceiver mOpenDevicesReceiver;
    private TextView            mError;
    private UsbDeviceConnection mUsbDeviceConnection;
    private UsbEndpoint         mUsbEndpointOut;
    private UsbEndpoint         mUsbEndpointIn;
    private boolean mToggle = true;
    private Button mSendMessage;
    private boolean isDetached        = false;
    private byte[]  mBytes            = new byte[1024];
    private boolean isReceiverMessage = true;
    private UsbInterface mUsbInterface;
    private StringBuffer mStringBuffer = new StringBuffer();
    private Context mContext;

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case CONNECTED_SUCCESS://车机和手机连接成功
                    mError.setText("");
                    mSendMessage.setEnabled(true);
                    loopReceiverMessage();
                    break;

                case RECEIVER_MESSAGE_SUCCESS://成功接受到数据
                    mLog.setText(mStringBuffer.toString());
                    break;

                case SEND_MESSAGE_SUCCESS://成功发送数据
                    mMessage.setText("");
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        init();
    }

    private void init() {
        initView();
        initListener();
        initData();
    }

    private void initView() {
        mLog = (TextView) findViewById(R.id.log);
        mError = (TextView) findViewById(R.id.error);
        mMessage = (EditText) findViewById(R.id.message);
        mSendMessage = (Button) findViewById(R.id.sendmessage);
    }

    private void initListener() {
        mSendMessage.setOnClickListener(this);
    }

    private void initData() {
        mContext = getApplicationContext();
        mSendMessage.setEnabled(false);
        mUsbDetachedReceiver = new UsbDetachedReceiver(this);
        IntentFilter intentFilter = new IntentFilter(UsbManager.ACTION_USB_DEVICE_DETACHED);
        registerReceiver(mUsbDetachedReceiver, intentFilter);

        mThreadPool = Executors.newFixedThreadPool(5);

        mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);

        openDevices();
    }

    /**
     * 打开设备 , 让车机和手机端连起来
     */
    private void openDevices() {
        PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(USB_ACTION), 0);
        IntentFilter intentFilter = new IntentFilter(USB_ACTION);
        mOpenDevicesReceiver = new OpenDevicesReceiver(this);
        registerReceiver(mOpenDevicesReceiver, intentFilter);

        //列举设备(手机)
        HashMap deviceList = mUsbManager.getDeviceList();
        if (deviceList != null) {
            for (UsbDevice usbDevice : deviceList.values()) {
                int productId = usbDevice.getProductId();
                if (productId != 377 && productId != 7205) {
                //这里说明下,这里的377 , 7205是我这台机子上独有,因为我这上面有多台设备,所以我在这里
                //判断了下.只有一台设备的无需这一步.
                    if (mUsbManager.hasPermission(usbDevice)) {
                        initAccessory(usbDevice);
                    } else {
                        mUsbManager.requestPermission(usbDevice, pendingIntent);
                    }
                }
            }
        } else {
            mError.setText("请连接USB");
        }
    }

    /**
     * 发送命令 , 让手机进入Accessory模式
     *
     * @param usbDevice
     */
    private void initAccessory(UsbDevice usbDevice) {
        UsbDeviceConnection usbDeviceConnection = mUsbManager.openDevice(usbDevice);
        if (usbDeviceConnection == null) {
            mError.setText("请连接USB");
            return;
        }

        //根据AOA协议打开Accessory模式
        initStringControlTransfer(usbDeviceConnection, 0, "Google, Inc."); // MANUFACTURER
        initStringControlTransfer(usbDeviceConnection, 1, "AccessoryChat"); // MODEL
        initStringControlTransfer(usbDeviceConnection, 2, "Accessory Chat"); // DESCRIPTION
        initStringControlTransfer(usbDeviceConnection, 3, "1.0"); // VERSION
        initStringControlTransfer(usbDeviceConnection, 4, "http://www.android.com"); // URI
        initStringControlTransfer(usbDeviceConnection, 5, "0123456789"); // SERIAL
        usbDeviceConnection.controlTransfer(0x40, 53, 0, 0, new byte[]{}, 0, 100);
        usbDeviceConnection.close();
        MyApplication.printLogDebug("initAccessory success");
        initDevice();
    }

    private void initStringControlTransfer(UsbDeviceConnection deviceConnection, int index, String string) {
        deviceConnection.controlTransfer(0x40, 52, 0, index, string.getBytes(), string.length(), 100);
    }

    /**
     * 初始化设备(手机) , 当手机进入Accessory模式后 , 手机的PID会变为Google定义的2个常量值其中的一个 ,
     */
    private void initDevice() {
        mThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                while (mToggle) {
                    SystemClock.sleep(1000);
                    HashMap deviceList = mUsbManager.getDeviceList();
                    Collection values = deviceList.values();
                    if (!values.isEmpty()) {
                        for (UsbDevice usbDevice : values) {
                            int productId = usbDevice.getProductId();
                            if (productId == 0x2D00 || productId == 0x2D01) {
                                if (mUsbManager.hasPermission(usbDevice)) {
                                    mUsbDeviceConnection = mUsbManager.openDevice(usbDevice);
                                    if (mUsbDeviceConnection != null) {
                                        mUsbInterface = usbDevice.getInterface(0);
                                        int endpointCount = mUsbInterface.getEndpointCount();
                                        for (int i = 0; i < endpointCount; i++) {
                                            UsbEndpoint usbEndpoint = mUsbInterface.getEndpoint(i);
                                            if (usbEndpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                                                if (usbEndpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
                                                    mUsbEndpointOut = usbEndpoint;
                                                } else if (usbEndpoint.getDirection() == UsbConstants.USB_DIR_IN) {
                                                    mUsbEndpointIn = usbEndpoint;
                                                }
                                            }
                                        }
                                        if (mUsbEndpointOut != null && mUsbEndpointIn != null) {
                                            MyApplication.printLogDebug("connected success");
                                            mHandler.sendEmptyMessage(CONNECTED_SUCCESS);
                                            mToggle = false;
                                            isDetached = true;
                                        }
                                    }
                                } else {
                                    mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(""), 0));
                                }
                            }
                        }
                    } else {
                        finish();
                    }
                }
            }
        });
    }

    /**
     * 接受消息线程 , 此线程在设备(手机)初始化完成后 , 就一直循环接受消息
     */
    private void loopReceiverMessage() {
        mThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                SystemClock.sleep(1000);
                while (isReceiverMessage) {
                    /**
                     * 循环接受数据的地方 , 只接受byte数据类型的数据
                     */
                    if (mUsbDeviceConnection != null && mUsbEndpointIn != null) {
                        int i = mUsbDeviceConnection.bulkTransfer(mUsbEndpointIn, mBytes, mBytes.length, 3000);
                        MyApplication.printLogDebug(i + "");
                        if (i > 0) {
                            mStringBuffer.append(new String(mBytes, 0, i) + "\n");
                            mHandler.sendEmptyMessage(RECEIVER_MESSAGE_SUCCESS);
                        }
                    }
                }
            }
        });
    }

    @Override
    public void usbDetached() {
        if (isDetached) {
            finish();
        }
    }

    @Override
    public void openAccessoryModel(UsbDevice usbDevice) {
        initAccessory(usbDevice);
    }

    @Override
    public void openDevicesError() {
        mError.setText("USB连接错误");
    }

    @Override
    public void onClick(View v) {
        final String messageContent = mMessage.getText().toString();
        if (!TextUtils.isEmpty(messageContent)) {
            mThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    /**
                     * 发送数据的地方 , 只接受byte数据类型的数据
                     */
                    int i = mUsbDeviceConnection.bulkTransfer(mUsbEndpointOut, messageContent.getBytes(), messageContent.getBytes().length, 3000);
                    if (i > 0) {
                        mHandler.sendEmptyMessage(SEND_MESSAGE_SUCCESS);
                    }
                }
            });
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        if (mUsbDeviceConnection != null) {
            mUsbDeviceConnection.releaseInterface(mUsbInterface);
            mUsbDeviceConnection.close();
            mUsbDeviceConnection = null;
        }
        mUsbEndpointIn = null;
        mUsbEndpointOut = null;
        mToggle = false;
        isReceiverMessage = false;
        mThreadPool.shutdownNow();
        unregisterReceiver(mUsbDetachedReceiver);
        unregisterReceiver(mOpenDevicesReceiver);
    }
}

OpenDevicesReceiver广播代码:

package com.tcl.navigator.hostchart.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;

/**
 * Created by yaohui on 2017/3/3.
 */

public class OpenDevicesReceiver extends BroadcastReceiver {

    private OpenDevicesListener mOpenDevicesListener;

    public OpenDevicesReceiver(OpenDevicesListener openDevicesListener) {
        mOpenDevicesListener = openDevicesListener;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
        if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
            if (usbDevice != null) {
                mOpenDevicesListener.openAccessoryModel(usbDevice);
            } else {
                mOpenDevicesListener.openDevicesError();
            }
        } else {
            mOpenDevicesListener.openDevicesError();
        }
    }

    public interface OpenDevicesListener {
        /**
         * 打开Accessory模式
         *
         * @param usbDevice
         */
        void openAccessoryModel(UsbDevice usbDevice);

        /**
         * 打开设备(手机)失败
         */
        void openDevicesError();
    }
}

UsbDetachedReceiver广播代码:

package com.tcl.navigator.hostchart.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class UsbDetachedReceiver extends BroadcastReceiver {

    private UsbDetachedListener mUsbDetachedListener;

    public UsbDetachedReceiver(UsbDetachedListener usbDetachedListener) {
        mUsbDetachedListener = usbDetachedListener;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        mUsbDetachedListener.usbDetached();
    }

    public interface UsbDetachedListener {
        /**
         * usb断开连接
         */
        void usbDetached();
    }
}

以上就是Host端代码了.

2.Accessory端代码:

package com.tcl.navigator.accessorychart.activity;

import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import com.tcl.navigator.accessorychart.R;
import com.tcl.navigator.accessorychart.receiver.OpenAccessoryReceiver;
import com.tcl.navigator.accessorychart.receiver.UsbDetachedReceiver;

import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MainActivity extends AppCompatActivity implements OpenAccessoryReceiver.OpenAccessoryListener, View.OnClickListener, UsbDetachedReceiver.UsbDetachedListener {

    private static final int    SEND_MESSAGE_SUCCESS     = 0;
    private static final int    RECEIVER_MESSAGE_SUCCESS = 1;
    private static final String USB_ACTION               = "com.tcl.navigator.accessorychart";
    private TextView              mLog;
    private EditText              mMessage;
    private Button                mSend;
    private UsbManager            mUsbManager;
    private OpenAccessoryReceiver mOpenAccessoryReceiver;
    private ParcelFileDescriptor  mParcelFileDescriptor;
    private FileInputStream       mFileInputStream;
    private FileOutputStream      mFileOutputStream;
    private ExecutorService       mThreadPool;
    private byte[]       mBytes        = new byte[1024];
    private StringBuffer mStringBuffer = new StringBuffer();
    private UsbDetachedReceiver mUsbDetachedReceiver;

    Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case SEND_MESSAGE_SUCCESS:
                    mMessage.setText("");
                    mMessage.clearComposingText();
                    break;

                case RECEIVER_MESSAGE_SUCCESS:
                    mLog.setText(mStringBuffer.toString());
                    break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        init();
    }

    private void init() {
        initView();
        initListener();
        initData();
    }

    private void initView() {
        mLog = (TextView) findViewById(R.id.log);
        mMessage = (EditText) findViewById(R.id.message);
        mSend = (Button) findViewById(R.id.send);
    }

    private void initListener() {
        mSend.setOnClickListener(this);
    }

    private void initData() {
        mSend.setEnabled(false);
        mUsbManager = (UsbManager) getSystemService(Context.USB_SERVICE);
        mThreadPool = Executors.newFixedThreadPool(3);

        mUsbDetachedReceiver = new UsbDetachedReceiver(this);
        IntentFilter filter = new IntentFilter(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
        registerReceiver(mUsbDetachedReceiver, filter);

        mOpenAccessoryReceiver = new OpenAccessoryReceiver(this);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent(USB_ACTION), 0);
        IntentFilter intentFilter = new IntentFilter(USB_ACTION);
        registerReceiver(mOpenAccessoryReceiver, intentFilter);

        UsbAccessory[] accessories = mUsbManager.getAccessoryList();
        UsbAccessory usbAccessory = (accessories == null ? null : accessories[0]);
        if (usbAccessory != null) {
            if (mUsbManager.hasPermission(usbAccessory)) {
                openAccessory(usbAccessory);
            } else {
                mUsbManager.requestPermission(usbAccessory, pendingIntent);
            }
        }
    }

    /**
     * 打开Accessory模式
     *
     * @param usbAccessory
     */
    private void openAccessory(UsbAccessory usbAccessory) {
        mParcelFileDescriptor = mUsbManager.openAccessory(usbAccessory);
        if (mParcelFileDescriptor != null) {
            FileDescriptor fileDescriptor = mParcelFileDescriptor.getFileDescriptor();
            mFileInputStream = new FileInputStream(fileDescriptor);
            mFileOutputStream = new FileOutputStream(fileDescriptor);
            mSend.setEnabled(true);

            mThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    int i = 0;
                    while (i >= 0) {
                        try {
                            i = mFileInputStream.read(mBytes);
                        } catch (IOException e) {
                            e.printStackTrace();
                            break;
                        }
                        if (i > 0) {
                            mStringBuffer.append(new String(mBytes, 0, i) + "\n");
                            mHandler.sendEmptyMessage(RECEIVER_MESSAGE_SUCCESS);
                        }
                    }
                }
            });
        }
    }

    @Override
    public void openAccessoryModel(UsbAccessory usbAccessory) {
        openAccessory(usbAccessory);
    }

    @Override
    public void openAccessoryError() {

    }

    @Override
    public void onClick(View v) {
        final String mMessageContent = mMessage.getText().toString();
        if (!TextUtils.isEmpty(mMessageContent)) {
            mThreadPool.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        mFileOutputStream.write(mMessageContent.getBytes());
                        mHandler.sendEmptyMessage(SEND_MESSAGE_SUCCESS);
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    @Override
    public void usbDetached() {

        finish();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();

        unregisterReceiver(mOpenAccessoryReceiver);
        unregisterReceiver(mUsbDetachedReceiver);
        if (mParcelFileDescriptor != null) {
            try {
                mParcelFileDescriptor.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (mFileInputStream != null) {
            try {
                mFileInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (mFileOutputStream != null) {
            try {
                mFileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

OpenAccessoryReceiver广播代码:

package com.tcl.navigator.accessorychart.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.hardware.usb.UsbAccessory;
import android.hardware.usb.UsbManager;

public class OpenAccessoryReceiver extends BroadcastReceiver {

    private OpenAccessoryListener mOpenAccessoryListener;

    public OpenAccessoryReceiver(OpenAccessoryListener openAccessoryListener) {
        mOpenAccessoryListener = openAccessoryListener;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        UsbAccessory usbAccessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
        if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
            if (usbAccessory != null) {
                mOpenAccessoryListener.openAccessoryModel(usbAccessory);
            } else {
                mOpenAccessoryListener.openAccessoryError();
            }
        } else {
            mOpenAccessoryListener.openAccessoryError();
        }
    }

    public interface OpenAccessoryListener {
        /**
         * 打开Accessory模式
         *
         * @param usbAccessory
         */
        void openAccessoryModel(UsbAccessory usbAccessory);

        /**
         * 打开设备(手机)失败
         */
        void openAccessoryError();
    }
}

UsbDetachedReceiver广播代码:

package com.tcl.navigator.accessorychart.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class UsbDetachedReceiver extends BroadcastReceiver {

    private UsbDetachedListener mUsbDetachedListener;

    public UsbDetachedReceiver(UsbDetachedListener usbDetachedListener) {
        mUsbDetachedListener = usbDetachedListener;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        mUsbDetachedListener.usbDetached();
    }

    public interface UsbDetachedListener {
        /**
         * usb断开连接
         */
        void usbDetached();
    }
}

最后在AndroidManifest里面有些小改动:

<activity android:name=".activity.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <action android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            intent-filter>

            <meta-data
                android:name="android.hardware.usb.action.USB_ACCESSORY_ATTACHED"
                android:resource="@xml/accessory_filter"/>
        activity>

其中USB通讯是需要用户手动赋予权限的,所以2个手机都会有提示的.
到此基本上就完了,我写的这2个app运行在2个安卓手机上,通过数据线是可以进行聊天的.
不懂的请给我留言,我看到了都会回复的,再见啦! ! !
源码下载地址:HostChart,AccessoryChart

你可能感兴趣的:(android,通讯,usb)