用于USB附件的FileDescriptor将关闭

时间:2015-11-12 13:53:50

标签: android service usb

我使用服务打开与USB附件的连接。我使用绑定到我从UsbManager的openAccessory()方法获得的FileDescriptor的输入流。只要我不开始新的活动,一切都很好。出于某种原因,当我开始一个新活动时,我得到IOException(文件描述符已关闭)。任何想法为什么会这样?我不想这样做,以便输入流在各个活动之间保持连接。

2 个答案:

答案 0 :(得分:1)

您必须将USB连接置于服务(不是绑定服务,而是前台或后台)中,并与广播接收器通信接收到的数据。

答案 1 :(得分:0)

让我以完善的服务为您提供更多帮助,以附件模式读取USB。 读取的数据放在缓冲区中。

public final class UsbService extends Service {

    //Member attributes
    // USB
    private static final String ACTION_USB_PERMISSION = "com.examples.accessory.controller.action.USB_PERMISSION";

    private Context mMainContext;
    LocalBroadcastManager mBroadcastManager = null;

    private UsbManager mUsbManager;
    private PendingIntent mPermissionIntent;
    private UsbAccessory mAccessory;
    private ParcelFileDescriptor mFileDescriptor;
    private FileInputStream mInputStream;
    private FileOutputStream mOutputStream;

    private boolean mPermissionRequestPendding = false;

    private Thread mAccessMonitor;
    private Thread mUsbListenner;

    private ConcurrentLinkedQueue<String> usbDataBuffer;

    /* ************************************* */
    /*         BROADCAST RECEIVERS           */
    /* ************************************* */

    private final BroadcastReceiver mUsbPermissionReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            usbPermissionMonitor(intent);    
        }
    };

    /* ************************************* */
    /*              RUNNABLES                */
    /* ************************************* */

    // Running thread listenning to USB port for received messages
    private Runnable UsbListenner = new Runnable() {
        public void run() {
            while(1)
                readUsbAccessory();
        }
    };

    // Running thread listenning to USB accessories
    private Runnable AccessoryMonitor = new Runnable() {
        public void run() {
            android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND);
            while(mIsServiceRunning){
                try {
                    getAccessory();
                    sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    };

    /* ************************************* */
    /*           SERVICE FUNCTIONS           */
    /* ************************************* */
    public UsbService(){}

    @Override
    public void onCreate() {
        mMainContext = getApplicationContext();
        mBroadcastManager = LocalBroadcastManager.getInstance(mMainContext);
        mBroadcastManager.registerReceiver(usbServiceReceiver, usbServiceFilter);
        initUsb();
    }

    public IBinder onBind(Intent intent){
        return null;
    }

    @Override
    public void onRebind(Intent intent) {
        super.onRebind(intent);
    }

    @Override
    public boolean onUnbind(Intent intent) {
        super.onUnbind(intent);
        return true;
    }

    // Destroy
    @Override
    public void onDestroy() {

        closeAccessory();
        mBroadcastManager.unregisterReceiver(mUsbPermissionReceiver);
        mBroadcastManager.unregisterReceiver(usbServiceReceiver);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId){

        return START_NOT_STICKY;
    }

    /* ************************************* */
    /*         USB CONTROL FUNCTIONS         */
    /* ************************************* */

    private void initUsb()
    {
        usbDataBuffer = new ConcurrentLinkedQueue<>();
        mAccessMonitor= new Thread(AccessoryMonitor);
        mUsbListenner = new Thread(UsbListenner);

        mUsbManager = (UsbManager)getSystemService(Context.USB_SERVICE);
        mPermissionIntent = PendingIntent.getBroadcast(this, 0, new Intent(ACTION_USB_PERMISSION), 0);
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        filter.addAction(UsbManager.ACTION_USB_ACCESSORY_DETACHED);
        filter.addAction(UsbManager.EXTRA_ACCESSORY);
        mBroadcastManager.registerReceiver(mUsbPermissionReceiver, filter);
        mAccessMonitor.start();
    }

    private void getAccessory()
    {
        if (mFileDescriptor != null) {
            return;
        }

        UsbAccessory[] accessories = mUsbManager.getAccessoryList();
        UsbAccessory accessory = (accessories == null ? null : accessories[0]);
        if (accessory != null)
        {
            if (mUsbManager.hasPermission(accessory))
            {
                //"has permission";
                if(!mPermissionRequestPendding) {
                    openAccessory(accessory);
                }
            }
            else
            {
                //"no permission";
                synchronized (mUsbPermissionReceiver)
                {
                    if(!mPermissionRequestPendding) {
                        mUsbManager.requestPermission(accessory, mPermissionIntent);
                        mPermissionRequestPendding = true;
                    }
                }
            }
        }
    }

    private void openAccessory(UsbAccessory accessory)
    {
        if(accessory != null) {
            mFileDescriptor = mUsbManager.openAccessory(accessory);
            if (mFileDescriptor != null) {
                mAccessory = accessory;
                FileDescriptor fd = mFileDescriptor.getFileDescriptor();
                mInputStream = new FileInputStream(fd);
                mOutputStream = new FileOutputStream(fd);
                mUsbListenner.start();
                mPermissionRequestPendding = false;
            }
        }
    }

    private void closeAccessory() {
        try {
            if (mFileDescriptor != null) {
                mFileDescriptor.close();
            }
        }
        catch (IOException e) {

        }
        finally {
            mAccessory = null;
            mFileDescriptor = null;
        }
    }

    public void sendDataUsb(String msg)
    {
        if (mFileDescriptor != null) {
            byte[] bytes = msg.getBytes();
            try {
                mOutputStream.write(bytes);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /*
     * Runnable block that will poll the accessory data stream
     * for regular updates, adds each message to a buffer.
     */
    private void readUsbAccessory() {
        if (mFileDescriptor != null) {
            int ret = 0;
            byte[] buffer = new byte[16384];

            while (mFileDescriptor != null) {
                try {
                    ret = mInputStream.read(buffer);
                    if (ret > 0) {
                        usbDataBuffer.add(new String(buffer, 0, ret));
                    }
                } catch (IOException e) {
                    break;
                }
            }
        }
    }

    /*
     * This receiver monitors for the event of a user granting permission to use
     * the attached accessory.  If the user has checked to always allow, this will
     * be generated following attachment without further user interaction.
     */
    private void usbPermissionMonitor(Intent intent)
    {
        String action = intent.getAction();
        if (ACTION_USB_PERMISSION.equals(action)) {
            synchronized (this) {
                final UsbAccessory accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    openAccessory(accessory);
                    mPermissionRequestPendding = false;
                } else {
                    //permission refused
                    mUsbManager.requestPermission(accessory, mPermissionIntent);
                }
            }
        } else if (UsbManager.ACTION_USB_ACCESSORY_DETACHED.equals(action)) {
            UsbAccessory accessory = intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);
            if (accessory != null && accessory.equals(mAccessory)) {
                Toast.makeText(this, "Cable detach !", Toast.LENGTH_LONG).show();
                closeAccessory();
                mUsbActive = false;
            }
        }
    }
}