IOException: đọc không thành công, ổ cắm có thể bị đóng - Bluetooth trên Android 4.3


100

Hiện tại, tôi đang cố gắng đối phó với một Ngoại lệ lạ khi mở BluetoothSocket trên Nexus 7 (2012) của tôi, với Android 4.3 (Bản dựng JWR66Y, tôi đoán là bản cập nhật 4.3 thứ hai). Tôi đã thấy một số bài đăng có liên quan (ví dụ: /programming/13648373/bl Bluetoothsocket-connect-throwing-exception-read-failed ), nhưng dường như không có giải pháp nào cung cấp giải pháp cho vấn đề này. Ngoài ra, như được đề xuất trong các chuỗi này, việc ghép nối lại không giúp ích gì và việc liên tục cố gắng kết nối (thông qua một vòng lặp ngu ngốc) cũng không có tác dụng.

Tôi đang xử lý một thiết bị nhúng (bộ điều hợp ô tô noname OBD-II, tương tự như http://images04.olx.com/ui/15/53/76/1316534072_254254776_2-OBD-II-BLUTOOTH-ADAPTORSCLEAR-CHECK-ENGINE- LIGHTS-VỚI-ĐIỆN THOẠI CỦA BẠN-Oceanside.jpg ). Điện thoại Android 2.3.7 của tôi không có bất kỳ sự cố kết nối nào và Xperia của một đồng nghiệp (Android 4.1.2) cũng hoạt động. Một chiếc Nexus khác của Google (tôi không biết liệu 'One' hay 'S', nhưng không phải '4') cũng không thành công với Android 4.3.

Đây là Đoạn mã của thiết lập kết nối. Nó đang chạy trong Thread của chính nó, được tạo trong một Dịch vụ.

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;
    }

}

Mã không thành công tại bluetoothSocket.connect(). Tôi đang nhận được một java.io.IOException: read failed, socket might closed, read ret: -1. Đây là nguồn tương ứng tại GitHub: https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bl Bluetooth/Bl BluetoothSocket.java#L504 Nó được gọi thông qua readInt (), được gọi từ https : //github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bl Bluetooth/BluetoothSocket.java#L319

Một số kết xuất siêu dữ liệu của ổ cắm đã sử dụng dẫn đến thông tin sau. Chúng hoàn toàn giống nhau trên Nexus 7 và điện thoại 2.3.7 của tôi.

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

Tôi có một số bộ điều hợp OBD-II khác (mở rộng hơn) và chúng đều hoạt động. Có bất kỳ cơ hội nào mà tôi đang thiếu thứ gì đó hoặc đây có thể là một lỗi trong Android không?


Tôi đã thử các giải pháp trên, có thể sombody giúp đỡ về vấn đề này stackoverflow.com/q/52105647/1559331
dileepVikram

Câu trả lời:


129

Cuối cùng tôi đã tìm thấy một giải pháp. Điều kỳ diệu được ẩn giấu dưới lớp vỏ bọc của BluetoothDevicelớp học (xem https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bl Bluetooth/BluetoothDevice.java#L1037 ).

Bây giờ, khi tôi nhận được ngoại lệ đó, tôi khởi tạo một dự phòng BluetoothSocket, tương tự như mã nguồn bên dưới. Như bạn có thể thấy, gọi phương thức ẩn createRfcommSocketthông qua phản xạ. Tôi không có manh mối tại sao phương pháp này bị ẩn. Mã nguồn định nghĩa nó như publicthể ...

Class<?> clazz = tmp.getRemoteDevice().getClass();
Class<?>[] paramTypes = new Class<?>[] {Integer.TYPE};

Method m = clazz.getMethod("createRfcommSocket", paramTypes);
Object[] params = new Object[] {Integer.valueOf(1)};

fallbackSocket = (BluetoothSocket) m.invoke(tmp.getRemoteDevice(), params);
fallbackSocket.connect();

connect()sau đó không thất bại nữa. Tôi vẫn gặp một số vấn đề. Về cơ bản, điều này đôi khi chặn và không thành công. Khởi động lại SPP-Device (cắm tắt / cắm vào) sẽ hữu ích trong những trường hợp như vậy. Đôi khi tôi cũng nhận được một yêu cầu Ghép nối khác connect()ngay cả khi thiết bị đã được kết nối.

CẬP NHẬT:

đây là một lớp hoàn chỉnh, chứa một số lớp lồng nhau. để triển khai thực tế, chúng có thể được tổ chức dưới dạng các lớp riêng biệt.

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.util.List;
import java.util.UUID;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.util.Log;

public class BluetoothConnector {

    private BluetoothSocketWrapper bluetoothSocket;
    private BluetoothDevice device;
    private boolean secure;
    private BluetoothAdapter adapter;
    private List<UUID> uuidCandidates;
    private int candidate;


    /**
     * @param device the device
     * @param secure if connection should be done via a secure socket
     * @param adapter the Android BT adapter
     * @param uuidCandidates a list of UUIDs. if null or empty, the Serial PP id is used
     */
    public BluetoothConnector(BluetoothDevice device, boolean secure, BluetoothAdapter adapter,
            List<UUID> uuidCandidates) {
        this.device = device;
        this.secure = secure;
        this.adapter = adapter;
        this.uuidCandidates = uuidCandidates;

        if (this.uuidCandidates == null || this.uuidCandidates.isEmpty()) {
            this.uuidCandidates = new ArrayList<UUID>();
            this.uuidCandidates.add(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
        }
    }

    public BluetoothSocketWrapper connect() throws IOException {
        boolean success = false;
        while (selectSocket()) {
            adapter.cancelDiscovery();

            try {
                bluetoothSocket.connect();
                success = true;
                break;
            } catch (IOException e) {
                //try the fallback
                try {
                    bluetoothSocket = new FallbackBluetoothSocket(bluetoothSocket.getUnderlyingSocket());
                    Thread.sleep(500);                  
                    bluetoothSocket.connect();
                    success = true;
                    break;  
                } catch (FallbackException e1) {
                    Log.w("BT", "Could not initialize FallbackBluetoothSocket classes.", e);
                } catch (InterruptedException e1) {
                    Log.w("BT", e1.getMessage(), e1);
                } catch (IOException e1) {
                    Log.w("BT", "Fallback failed. Cancelling.", e1);
                }
            }
        }

        if (!success) {
            throw new IOException("Could not connect to device: "+ device.getAddress());
        }

        return bluetoothSocket;
    }

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

        BluetoothSocket tmp;
        UUID uuid = uuidCandidates.get(candidate++);

        Log.i("BT", "Attempting to connect to Protocol: "+ uuid);
        if (secure) {
            tmp = device.createRfcommSocketToServiceRecord(uuid);
        } else {
            tmp = device.createInsecureRfcommSocketToServiceRecord(uuid);
        }
        bluetoothSocket = new NativeBluetoothSocket(tmp);

        return true;
    }

    public static interface BluetoothSocketWrapper {

        InputStream getInputStream() throws IOException;

        OutputStream getOutputStream() throws IOException;

        String getRemoteDeviceName();

        void connect() throws IOException;

        String getRemoteDeviceAddress();

        void close() throws IOException;

        BluetoothSocket getUnderlyingSocket();

    }


    public static class NativeBluetoothSocket implements BluetoothSocketWrapper {

        private BluetoothSocket socket;

        public NativeBluetoothSocket(BluetoothSocket tmp) {
            this.socket = tmp;
        }

        @Override
        public InputStream getInputStream() throws IOException {
            return socket.getInputStream();
        }

        @Override
        public OutputStream getOutputStream() throws IOException {
            return socket.getOutputStream();
        }

        @Override
        public String getRemoteDeviceName() {
            return socket.getRemoteDevice().getName();
        }

        @Override
        public void connect() throws IOException {
            socket.connect();
        }

        @Override
        public String getRemoteDeviceAddress() {
            return socket.getRemoteDevice().getAddress();
        }

        @Override
        public void close() throws IOException {
            socket.close();
        }

        @Override
        public BluetoothSocket getUnderlyingSocket() {
            return socket;
        }

    }

    public class FallbackBluetoothSocket extends NativeBluetoothSocket {

        private BluetoothSocket fallbackSocket;

        public FallbackBluetoothSocket(BluetoothSocket tmp) throws FallbackException {
            super(tmp);
            try
            {
              Class<?> clazz = tmp.getRemoteDevice().getClass();
              Class<?>[] paramTypes = new Class<?>[] {Integer.TYPE};
              Method m = clazz.getMethod("createRfcommSocket", paramTypes);
              Object[] params = new Object[] {Integer.valueOf(1)};
              fallbackSocket = (BluetoothSocket) m.invoke(tmp.getRemoteDevice(), params);
            }
            catch (Exception e)
            {
                throw new FallbackException(e);
            }
        }

        @Override
        public InputStream getInputStream() throws IOException {
            return fallbackSocket.getInputStream();
        }

        @Override
        public OutputStream getOutputStream() throws IOException {
            return fallbackSocket.getOutputStream();
        }


        @Override
        public void connect() throws IOException {
            fallbackSocket.connect();
        }


        @Override
        public void close() throws IOException {
            fallbackSocket.close();
        }

    }

    public static class FallbackException extends Exception {

        /**
         * 
         */
        private static final long serialVersionUID = 1L;

        public FallbackException(Exception e) {
            super(e);
        }

    }
}

3
Chà! giải pháp tuyệt vời!
Bobs

2
@MD Tôi không biết làm thế nào. Tôi vừa thử nghiệm và thấy nó đang hoạt động.
Bobs

1
Nó không hoạt động trên nexus 4. bạn có thể vui lòng cho biết cách khắc phục sự cố này không. Tôi gần như đã thử mọi thứ. Cảm ơn.
Shah

3
@matthes Rất tiếc phải nói nhưng ngay cả giải pháp sử dụng dự phòng của bạn vẫn chưa giải quyết được vấn đề của tôi. Nhận lỗi bên dưới. Fallback failed. Cancelling. java.io.IOException: Connection refused Xin vui lòng giúp đỡ.
Tushar Banne

2
@matthes "SPP-Device (cắm tắt / cắm vào) sẽ giúp ích trong những trường hợp như vậy.". Câu lệnh bật / tắt được đánh giá thấp nhất trên thế giới. Tôi chỉ lãng phí 3 giờ và tất cả những gì tôi phải làm là bật và tắt nó -_-
Adz

98

tốt, tôi đã gặp vấn đề tương tự với mã của mình và đó là vì ngăn xếp bluetooth android 4.2 đã thay đổi. vì vậy mã của tôi chạy tốt trên các thiết bị có android <4.2, trên các thiết bị khác, tôi nhận được ngoại lệ nổi tiếng "đọc không thành công, ổ cắm có thể bị đóng hoặc hết thời gian, đọc ret: -1"

Vấn đề là với socket.mPorttham số. Khi bạn tạo ổ cắm của mình bằng cách sử dụng socket = device.createRfcommSocketToServiceRecord(SERIAL_UUID);, mPortgiá trị nhận được là số nguyên " -1 " và giá trị này dường như không hoạt động đối với android> = 4.2, vì vậy bạn cần đặt nó thành " 1 ". Tin xấu là createRfcommSocketToServiceRecordchỉ chấp nhận UUID làm tham số và không phải mPortvì vậy chúng ta phải sử dụng aproach khác. Câu trả lời đăng bởi @matthes cũng làm việc cho tôi, nhưng tôi đơn giản hóa nó: socket =(BluetoothSocket) device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(device,1);. Chúng ta cần sử dụng cả hai bộ tiêu hao ổ cắm, cái thứ hai làm dự phòng.

Vì vậy, mã là (để kết nối với SPP trên thiết bị ELM327):

BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();

    if (btAdapter.isEnabled()) {
        SharedPreferences prefs_btdev = getSharedPreferences("btdev", 0);
        String btdevaddr=prefs_btdev.getString("btdevaddr","?");

        if (btdevaddr != "?")
        {
            BluetoothDevice device = btAdapter.getRemoteDevice(btdevaddr);

            UUID SERIAL_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); // bluetooth serial port service
            //UUID SERIAL_UUID = device.getUuids()[0].getUuid(); //if you don't know the UUID of the bluetooth device service, you can get it like this from android cache

            BluetoothSocket socket = null;

            try {
                socket = device.createRfcommSocketToServiceRecord(SERIAL_UUID);
            } catch (Exception e) {Log.e("","Error creating socket");}

            try {
                socket.connect();
                Log.e("","Connected");
            } catch (IOException e) {
                Log.e("",e.getMessage());
                try {
                    Log.e("","trying fallback...");

                    socket =(BluetoothSocket) device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(device,1);
                    socket.connect();

                    Log.e("","Connected");
                }
             catch (Exception e2) {
                 Log.e("", "Couldn't establish Bluetooth connection!");
              }
            }
        }
        else
        {
            Log.e("","BT device not selected");
        }
    }

57
cho người kiểm duyệt: vì bạn đã xóa câu trả lời trước đây của tôi mà không có lý do gì, tôi đăng lại.
George Dima

2
cảm ơn George vì những hiểu biết sâu sắc về mPortthông số! imho luồng công việc vẫn như cũ, tôi chỉ gói mọi thứ với một số lớp triển khai một giao diện.
matthes

5
vâng, tôi đã nói giải pháp của bạn là tốt, nhưng tôi muốn làm cho mọi người hiểu tại sao nó cần phải sử dụng phương pháp này bắt đầu với Android 4.2
George Dima

2
SPP = Cấu hình cổng nối tiếp (mô phỏng cổng nối tiếp qua bluetooth) và ELM327 là thiết bị bluetooth <-> obd trên ô tô, hãy google nó.
George Dima

10
Nó đã làm việc cho tôi sau khi thay đổi giá trị cổng từ 1 thành 2. xin vui lòng xem mã này. socket = (BluetoothSocket) device.getClass (). getMethod ("createRfcommSocket", new Class [] {int.class}). invoke (device, 2); socket.connect ();
Dinesh IT

16

Trước tiên, nếu bạn cần nói chuyện với thiết bị bluetooth 2.x, tài liệu này nói rằng:

Gợi ý: Nếu bạn đang kết nối với bảng nối tiếp Bluetooth thì hãy thử sử dụng SPP UUID 00001101-0000-1000-8000-00805F9B34FB nổi tiếng . Tuy nhiên, nếu bạn đang kết nối với một ứng dụng ngang hàng Android thì vui lòng tạo UUID duy nhất của riêng bạn.

Tôi không nghĩ rằng nó sẽ hoạt động, nhưng chỉ bằng cách thay thế UUID bằng 00001101-0000-1000-8000-00805F9B34FBnó hoạt động. Tuy nhiên, mã này dường như xử lý sự cố của phiên bản SDK và bạn chỉ có thể thay thế hàm device.createRfcommSocketToServiceRecord(mMyUuid);bằng tmp = createBluetoothSocket(mmDevice);sau khi xác định phương pháp sau:

private BluetoothSocket createBluetoothSocket(BluetoothDevice device)
    throws IOException {
    if(Build.VERSION.SDK_INT >= 10){
        try {
            final Method m = device.getClass().getMethod("createInsecureRfcommSocketToServiceRecord", new Class[] { UUID.class });
            return (BluetoothSocket) m.invoke(device, mMyUuid);
        } catch (Exception e) {
            Log.e(TAG, "Could not create Insecure RFComm Connection",e);
        }
    }
    return  device.createRfcommSocketToServiceRecord(mMyUuid);
}

Mã nguồn không phải của tôi mà đến từ trang web này .


1
Điều đó giải quyết được gần 2 ngày làm việc ... cảm ơn thở dài ... Nếu không có UUID này, ổ cắm sẽ đóng ngay lập tức và hỏng mà không cần giải thích thêm.
David Sinclair

Cảm ơn bạn rất nhiều vì đã giúp UUID của tôi là chữ và số và tôi đang cố gắng kết nối HC-5 và kết nối bluetooth của tôi không hiển thị nhưng khi tôi sử dụng giải pháp này, vấn đề của tôi không giải quyết được. cảm ơn bạn một lần nữa
Nikhil Shende

8

Tôi đã có các triệu chứng giống như mô tả ở đây. Tôi có thể kết nối một lần với máy in bluetooth nhưng kết nối sau đó không thành công với "ổ cắm đã đóng" bất kể tôi đã làm gì.

Tôi thấy hơi lạ khi các cách giải quyết được mô tả ở đây là cần thiết. Sau khi xem qua mã của mình, tôi thấy rằng tôi đã quên đóng InputStream và OutputSteram của ổ cắm và không kết thúc ConnectedThreads đúng cách.

ConnectedThread mà tôi sử dụng giống như trong ví dụ ở đây:

http://developer.android.com/guide/topics/connectivity/bl Bluetooth.html

Lưu ý rằng ConnectThread và ConnectedThread là hai lớp khác nhau.

Bất kỳ lớp nào bắt đầu ConnectedThread đều phải gọi ngắt () và hủy () trên luồng. Tôi đã thêm mmInStream.close () và mmOutStream.close () trong phương thức ConnectedTread.cancel ().

Sau khi đóng các luồng / luồng / ổ cắm đúng cách, tôi có thể tạo các ổ cắm mới mà không gặp vấn đề gì.


Cảm ơn, đã gặp vấn đề tương tự, vừa rồi tôi đã phát hiện ra rằng mình chưa đóng luồng và kết nối ...
Rafael

đã thử tất cả các trường hợp trên, (ngoại trừ việc loại bỏ các thiết bị được ghép nối khác, nguyên nhân thực sự không phải là giải pháp được tìm thấy là có ... điều này thường chỉ xảy ra khi các luồng đầu vào và ổ cắm không được đóng đúng cách ..... !!
Aman Satija

7

Chà, tôi thực sự đã tìm ra vấn đề.

Hầu hết những người cố gắng tạo kết nối bằng cách sử dụng socket.Connect();một ngoại lệ được gọi Java.IO.IOException: read failed, socket might closed, read ret: -1.

Trong một số trường hợp, nó cũng phụ thuộc vào thiết bị Bluetooth của bạn, vì có hai loại Bluetooth khác nhau, đó là BLE (năng lượng thấp) và Cổ điển.

Nếu bạn muốn kiểm tra loại thiết bị Bluetooth của mình, đây là mã:

        String checkType;
        var listDevices = BluetoothAdapter.BondedDevices;
        if (listDevices.Count > 0)
        {
            foreach (var btDevice in listDevices)
            {
                if(btDevice.Name == "MOCUTE-032_B52-CA7E")
                {
                    checkType = btDevice.Type.ToString();
                    Console.WriteLine(checkType);
                }
            }
        }

Tôi đã cố gắng giải quyết vấn đề trong nhiều ngày, nhưng kể từ hôm nay tôi đã tìm ra vấn đề. Rất tiếc, giải pháp từ @matthes vẫn còn một số vấn đề như anh ấy đã nói, nhưng đây là giải pháp của tôi.

Hiện tại tôi đang làm việc trên Xamarin Android, nhưng điều này cũng sẽ hoạt động cho các nền tảng khác.

GIẢI PHÁP

Nếu có nhiều thiết bị được ghép nối thì bạn nên xóa các thiết bị được ghép nối khác. Vì vậy, chỉ giữ lại cái mà bạn muốn kết nối (xem hình bên phải).

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Trong hình ảnh bên trái, bạn thấy rằng tôi có hai thiết bị được ghép nối, đó là "MOCUTE-032_B52-CA7E" và "Blue Easy". Đó là vấn đề, nhưng tôi không biết tại sao vấn đề đó lại xảy ra. Có thể giao thức Bluetooth đang cố lấy một số thông tin từ một thiết bị Bluetooth khác.

Tuy nhiên, hiện tại socket.Connect();hoạt động tuyệt vời, không có bất kỳ vấn đề gì. Vì vậy, tôi chỉ muốn chia sẻ điều này, vì lỗi đó thực sự khó chịu.

Chúc may mắn!


Điều này đã hoạt động trên một thiết bị mà tôi gặp phải sự cố này, điều này chỉ xảy ra với tôi trên điện thoại 5.0 và thậm chí chỉ xảy ra khi tôi bật BT lần đầu tiên, sau đó mở kết nối. Nếu BT đã được bật, không có vấn đề kết nối! Nó không xảy ra trên các thiết bị có phiên bản Android mới hơn, cho thấy các nhà phát triển đã nhận thấy lỗi và sửa nó, nhưng trang Android BT không đưa ra lời nào về nó. Nhưng giải pháp của bạn hoạt động, cảm ơn!
John Perry

7

Trên các phiên bản Android mới hơn, tôi gặp lỗi này do bộ điều hợp vẫn phát hiện ra khi tôi cố gắng kết nối với ổ cắm. Mặc dù tôi đã gọi phương thức hủy bỏ phát hiện trên bộ điều hợp Bluetooth, nhưng tôi phải đợi cho đến khi gọi lại phương thức onReceive () của BroadcastReceiver được gọi với hành động BluetoothAdapter.ACTION_DISCOVERY_FINISHED.

Sau khi tôi đợi bộ điều hợp ngừng phát hiện, thì cuộc gọi kết nối trên ổ cắm đã thành công.


6

Bạn đặt registerReceiver(receiver, new IntentFilter("android.bleutooth.device.action.UUID")); với "bluetooth" đánh vần là "bleutooth".


4

Trong trường hợp ai đó gặp vấn đề với Kotlin, tôi phải làm theo câu trả lời được chấp nhận với một số biến thể:

fun print(view: View, text: String) {
    var adapter = BluetoothAdapter.getDefaultAdapter();
    var pairedDevices = adapter.getBondedDevices()
    var uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
    if (pairedDevices.size > 0) {
        for (device in pairedDevices) {
            var s = device.name
            if (device.getName().equals(printerName, ignoreCase = true)) {
                Thread {
                    var socket = device.createInsecureRfcommSocketToServiceRecord(uuid)
                    var clazz = socket.remoteDevice.javaClass
                    var paramTypes = arrayOf<Class<*>>(Integer.TYPE)
                    var m = clazz.getMethod("createRfcommSocket", *paramTypes)
                    var fallbackSocket = m.invoke(socket.remoteDevice, Integer.valueOf(1)) as BluetoothSocket
                    try {
                        fallbackSocket.connect()
                        var stream = fallbackSocket.outputStream
                        stream.write(text.toByteArray(Charset.forName("UTF-8")))
                    } catch (e: Exception) {
                        e.printStackTrace()
                        Snackbar.make(view, "An error occurred", Snackbar.LENGTH_SHORT).show()
                    }
                }.start()
            }
        }
    }
}

Hy vọng nó giúp


3

Thiết bị Bluetooth có thể hoạt động ở cả chế độ cổ điển và chế độ LE cùng một lúc. Đôi khi họ sử dụng một địa chỉ MAC khác tùy thuộc vào cách bạn đang kết nối. Tính năng gọi socket.connect()đang sử dụng Bluetooth Classic, vì vậy bạn phải đảm bảo thiết bị bạn nhận được khi quét thực sự là thiết bị cổ điển.

Tuy nhiên, thật dễ dàng để lọc chỉ các thiết bị Cổ điển:

if(BluetoothDevice.DEVICE_TYPE_LE == device.getType()){ //socket.connect() }

Nếu không có kiểm tra này, đó là một điều kiện chạy đua xem liệu quét kết hợp sẽ cung cấp cho bạn thiết bị Cổ điển hay thiết bị BLE trước. Nó có thể xuất hiện như không thể kết nối không liên tục hoặc như một số thiết bị có thể kết nối đáng tin cậy trong khi những thiết bị khác dường như không bao giờ có thể.


1

Tôi cũng gặp phải vấn đề này, bạn có thể giải quyết nó theo 2 cách, như đã đề cập trước đó, sử dụng phản chiếu để tạo socket Thứ hai là, máy khách đang tìm kiếm một máy chủ có UUID đã cho và nếu máy chủ của bạn không chạy song song với máy khách thì điều này xảy ra. Tạo một máy chủ với UUID máy khách nhất định, sau đó lắng nghe và chấp nhận máy khách từ phía máy chủ. Nó sẽ hoạt động.


1

Tôi đã gặp sự cố này và khắc phục nó bằng cách đóng các luồng đầu vào và đầu ra trước khi đóng ổ cắm. Bây giờ tôi có thể ngắt kết nối và kết nối lại mà không gặp vấn đề gì.

https://stackoverflow.com/a/3039807/5688612

Trong Kotlin:

fun disconnect() {
    bluetoothSocket.inputStream.close()
    bluetoothSocket.outputStream.close()
    bluetoothSocket.close()
}

1

Nếu một phần khác của mã của bạn đã tạo kết nối với cùng một ổ cắm và UUID, bạn sẽ gặp lỗi này.


0

Ngay cả khi tôi đã gặp vấn đề tương tự, cuối cùng cũng hiểu được vấn đề của mình, tôi đang cố gắng kết nối từ (ngoài phạm vi) phạm vi phủ sóng của Bluetooth.


0

Tôi đã gặp vấn đề này và giải pháp là sử dụng GUID ma thuật đặc biệt.

            val id: UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB") // Any other GUID doesn't work.
            val device: BluetoothDevice = bta!!.bondedDevices.first { z -> z.name == deviceName }

            bts = device.createRfcommSocketToServiceRecord(id) // mPort is -1
            bts?.connect()
            // Start processing thread.

Tôi nghi ngờ rằng đây là những UUID hoạt động:

var did: Array<ParcelUuid?> = device.uuids

Tuy nhiên, tôi đã không thử tất cả chúng.


Ngay cả khi tôi đang sử dụng cùng một UUID. Nhưng đã không giúp tôi. Điều này có chỉ hỗ trợ kết nối với các thiết bị bluetooth cổ điển (không phải BLE) không? Tôi phải làm gì để kết nối với thiết bị BLE bằng Xamarin.Forms. Đã đăng ở đây [ stackoverflow.com/questions/62371859/…
Shailesh Bhat

Tôi đang sử dụng Bluetooth cổ điển; BLE là rác rưởi.
Richard Barraclough

-1

Bằng cách thêm hành động lọc, vấn đề của tôi đã được giải quyết

 // Register for broadcasts when a device is discovered
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
    intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
    intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
    registerReceiver(mReceiver, intentFilter);

-3

Tôi cũng nhận được điều tương tự IOException, nhưng tôi thấy bản demo hệ thống Android: Dự án "BluetoothChat" đã hoạt động. Tôi đã xác định vấn đề là UUID.

Vì vậy, tôi thay thế của tôi UUID.fromString("00001001-0000-1000-8000-00805F9B34FB")thành UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66")và nó hoạt động hầu hết các cảnh, đôi khi chỉ cần khởi động lại thiết bị Bluetooth;

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.