IOException: Lesen fehlgeschlagen, Socket möglicherweise geschlossen - Bluetooth unter Android 4.3

Zur Zeit versuche ich zu umgehen mit einer seltsamen Ausnahme, wenn die Eröffnung eines BluetoothSocket auf meinem Nexus 7 (2012) mit Android 4.3 (Build JWR66Y, ich denke, das zweite 4.3-update). Ich habe gesehen, einige Verwandte postings (z.B. https://stackoverflow.com/questions/13648373/bluetoothsocket-connect-throwing-exception-read-failed), aber keiner scheint sich um eine Problemumgehung für dieses Problem. Auch, wie vorgeschlagen, in diesen threads, re-pairing nicht helfen, und ständig versuchen zu verbinden (durch eine blöde Schleife) hat auch keine Wirkung.

Bin ich den Umgang mit einem embedded-Gerät (noname OBD-II Fahrzeug-adapter, ähnlich http://images04.olx.com/ui/15/53/76/1316534072_254254776_2-OBD-II-BLUTOOTH-ADAPTERSCLEAR-CHECK-ENGINE-LIGHTS-WITH-YOUR-PHONE-Oceanside.jpg). Mein Android 2.3.7 Telefon hat keine Probleme mit der Verbindung, und das Xperia von einem Kollegen (Android 4.1.2) funktioniert auch. Eine weitere Google-Nexus (ich weiß nicht, ob 'Man' oder 'S', aber nicht '4') auch nicht mit Android 4.3.

Hier ist das Snippet, den Verbindungsaufbau. Es läuft in einem eigenen Thread, erstellt innerhalb eines Service.

private class ConnectThread extends Thread {

    private static final UUID EMBEDDED_BOARD_SPP = UUID
        .fromString("00001101-0000-1000-8000-00805F9B34FB");

    private BluetoothAdapter adapter;
    private boolean secure;
    private BluetoothDevice device;
    private List<UUID> uuidCandidates;
    private int candidate;
    protected boolean started;

    public ConnectThread(BluetoothDevice device, boolean secure) {
        logger.info("initiliasing connection to device "+device.getName() +" /"+ device.getAddress());
        adapter = BluetoothAdapter.getDefaultAdapter();
        this.secure = secure;
        this.device = device;

        setName("BluetoothConnectThread");

        if (!startQueryingForUUIDs()) {
            this.uuidCandidates = Collections.singletonList(EMBEDDED_BOARD_SPP);
            this.start();
        } else{
            logger.info("Using UUID discovery mechanism.");
        }
        /*
         * it will start upon the broadcast receive otherwise
         */
    }

    private boolean startQueryingForUUIDs() {
        Class<?> cl = BluetoothDevice.class;

        Class<?>[] par = {};
        Method fetchUuidsWithSdpMethod;
        try {
            fetchUuidsWithSdpMethod = cl.getMethod("fetchUuidsWithSdp", par);
        } catch (NoSuchMethodException e) {
            logger.warn(e.getMessage());
            return false;
        }

        Object[] args = {};
        try {
            BroadcastReceiver receiver = new BroadcastReceiver() {
                @Override
                public void onReceive(Context context, Intent intent) {
                    BluetoothDevice deviceExtra = intent.getParcelableExtra("android.bluetooth.device.extra.DEVICE");
                    Parcelable[] uuidExtra = intent.getParcelableArrayExtra("android.bluetooth.device.extra.UUID");

                    uuidCandidates = new ArrayList<UUID>();
                    for (Parcelable uuid : uuidExtra) {
                        uuidCandidates.add(UUID.fromString(uuid.toString()));
                    }

                    synchronized (ConnectThread.this) {
                        if (!ConnectThread.this.started) {
                            ConnectThread.this.start();
                            ConnectThread.this.started = true;
                            unregisterReceiver(this);
                        }

                    }
                }

            };
            registerReceiver(receiver, new IntentFilter("android.bleutooth.device.action.UUID"));
            registerReceiver(receiver, new IntentFilter("android.bluetooth.device.action.UUID"));

            fetchUuidsWithSdpMethod.invoke(device, args);
        } catch (IllegalArgumentException e) {
            logger.warn(e.getMessage());
            return false;
        } catch (IllegalAccessException e) {
            logger.warn(e.getMessage());
            return false;
        } catch (InvocationTargetException e) {
            logger.warn(e.getMessage());
            return false;
        }           

        return true;
    }

    public void run() {
        boolean success = false;
        while (selectSocket()) {

            if (bluetoothSocket == null) {
                logger.warn("Socket is null! Cancelling!");
                deviceDisconnected();
                openTroubleshootingActivity(TroubleshootingActivity.BLUETOOTH_EXCEPTION);
            }

            //Always cancel discovery because it will slow down a connection
            adapter.cancelDiscovery();

            //Make a connection to the BluetoothSocket
            try {
                //This is a blocking call and will only return on a
                //successful connection or an exception
                bluetoothSocket.connect();
                success = true;
                break;

            } catch (IOException e) {
                //Close the socket
                try {
                    shutdownSocket();
                } catch (IOException e2) {
                    logger.warn(e2.getMessage(), e2);
                }
            }
        }

        if (success) {
            deviceConnected();
        } else {
            deviceDisconnected();
            openTroubleshootingActivity(TroubleshootingActivity.BLUETOOTH_EXCEPTION);
        }
    }

    private boolean selectSocket() {
        if (candidate >= uuidCandidates.size()) {
            return false;
        }

        BluetoothSocket tmp;
        UUID uuid = uuidCandidates.get(candidate++);
        logger.info("Attempting to connect to SDP "+ uuid);
        try {
            if (secure) {
                tmp = device.createRfcommSocketToServiceRecord(
                        uuid);
            } else {
                tmp = device.createInsecureRfcommSocketToServiceRecord(
                        uuid);
            }
            bluetoothSocket = tmp;
            return true;
        } catch (IOException e) {
            logger.warn(e.getMessage() ,e);
        }

        return false;
    }

}

Den code in Ermangelung an bluetoothSocket.connect(). Ich bin immer ein java.io.IOException: read failed, socket might closed, read ret: -1. Dies ist der korrespondierende Quelltext auf GitHub: https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothSocket.java#L504
Die genannte durch readInt(), aufgerufen https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothSocket.java#L319

Einige Metadaten-Speicherabbild der verwendeten socket-führte in den folgenden Informationen. Diese sind genau das gleiche auf dem Nexus 7 und meinem 2.3.7 Telefon.

Bluetooth Device 'OBDII'
Address: 11:22:33:DD:EE:FF
Bond state: 12 (bonded)
Type: 1
Class major version: 7936
Class minor version: 7936
Class Contents: 0
Contents: 0

Habe ich einige andere OBD-II-Adapter (mehr expansives) und Sie funktionieren alle. Gibt es irgendeine chance, dass mir etwas fehlt oder könnte das ein bug in Android?

InformationsquelleAutor der Frage matthes | 2013-09-06

Schreibe einen Kommentar