IOException: читання не вдалося, розетка може закритися - Bluetooth на Android 4.3


100

В даний час я намагаюся зіткнутися з дивним винятком під час відкриття BluetoothSocket на моєму Nexus 7 (2012), з Android 4.3 (Build JWR66Y, я думаю, друге оновлення 4.3). Я бачив деякі пов’язані публікації (наприклад, /programming/13648373/bluetoothsocket-connect-throwing-exception-read-failed ), але жодна проблема не може забезпечити вирішення цього питання. Також, як це пропонується в цих потоках, повторне сполучення не допомагає, і постійно намагаються підключитися (через тупу петлю) також не дає ефекту.

Я маю справу з вбудованим пристроєм (автомобільний адаптер a noname OBD-II, подібний до http://images04.olx.com/ui/15/53/76/1316534072_254254776_2-OBD-II-BLUTOOTH-ADAPTERSCLEAR-CHECK-ENGINE- СВІТЛІ-З ВАШИМ ТЕЛЕФОН-Oceanside.jpg ). Мій телефон Android 2.3.7 не має жодних проблем із підключенням, також працює і колега Xperia (Android 4.1.2). Інший Google Nexus (я не знаю, чи "Один" або "S", але не "4") також не працює з Android 4.3.

Ось фрагмент закладу зв'язку. Він працює у власному потоці, створеному в межах Служби.

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

}

Код не вдається bluetoothSocket.connect(). Я отримую java.io.IOException: read failed, socket might closed, read ret: -1. Це відповідне джерело в GitHub: https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothSocket.java#L504 Його викликано через readInt (), викликане з https : //github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothSocket.java#L319

Деякі скидання метаданих використовуваного сокета призвели до наступної інформації. Це точно так само на Nexus 7 і на моєму телефоні 2.3.7.

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

У мене є деякі інші адаптери OBD-II (більш розширені), і всі вони працюють. Чи є якийсь шанс, що я щось пропускаю або це може бути помилка в Android?


Я спробував вище рішенням, може Sombody допомоги з цього питання stackoverflow.com/q/52105647/1559331
dileepVikram

Відповіді:


129

Я нарешті знайшов рішення. Магія прихована під кришкою BluetoothDeviceкласу (див. Https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothDevice.java#L1037 ).

Тепер, коли я отримую цей виняток, я створюю резервну копію BluetoothSocket, подібну до вихідного коду нижче. Як бачите, виклик прихованого методу createRfcommSocketза допомогою роздумів. У мене немає поняття, чому цей метод прихований. Вихідний код визначає його як publicби ...

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()то більше не провалюється. Я випробував ще кілька питань. В основному, це іноді блокує і виходить з ладу. Перезавантаження SPP-пристрою (вимкнути / підключити) допомагає в таких випадках. Іноді я отримую ще один запит на пару після connect()того, як пристрій вже пов'язаний.

ОНОВЛЕННЯ:

ось повний клас, що містить деякі вкладені класи. для реальної реалізації вони можуть проводитись як окремі заняття.

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
Оце Так! чудове рішення!
Бобс

2
@MD Я не знаю як. Я щойно перевірив і виявив, що це працює.
Бобс

1
Він не працює на Nexus 4. Чи можете ви скажіть, як подолати цю проблему. Я майже все пробував. Дякую.
Шах

3
@matthes Вибачте, але навіть ваше рішення щодо використання резервного рішення не вирішило мою проблему. Помилка нижче Помилка. Fallback failed. Cancelling. java.io.IOException: Connection refused Будь ласка, допоможіть.
Тушар Бен

2
@matthes "SPP-пристрій (вимкнути / підключити) допомагає в таких випадках." Заява про ввімкнення / вимкнення є найбільш заниженою у світі. Я просто витратив 3 години, і все, що я повинен був зробити, це ввімкнути і вимкнути -_-
Adz

98

ну, у мене була така ж проблема з моїм кодом, і це тому, що з Android стек Bluetooth Bluetooth змінився. тому мій код працював нормально на пристроях з Android <4.2, на інших пристроях я отримував відомий виняток: "читання не вдалося, сокет може закритися або час очікування, прочитати ret: -1"

Проблема з socket.mPortпараметром. Коли ви створюєте сокет за допомогою socket = device.createRfcommSocketToServiceRecord(SERIAL_UUID);, mPortотримує ціле значення " -1 ", і це значення, здається, не працює для android> = 4.2, тому вам потрібно встановити його на " 1 ". Погана новина полягає в тому, що createRfcommSocketToServiceRecordтільки параметр UUID приймає як параметр, а не mPortтак, що ми мусимо використовувати інші підходи. Відповідь відправлений @matthes також працював для мене, але я спростив: socket =(BluetoothSocket) device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(device,1);. Нам потрібно використовувати обидві атрибути сокетів, другий як резервний.

Отже код (для підключення до SPP на пристрої 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
для модераторів: оскільки ви видалили мою попередню відповідь без причини, я опублікую її ще раз.
Джордж Діма

2
дякую Джорджу за розуміння mPortпараметра! Якщо робочий процес залишається таким же, я просто загортав речі з деякими класами, що реалізують інтерфейс.
Математика

5
так, я вже сказав, що ваше рішення було гарним, але я хотів, щоб люди зрозуміли, для чого йому потрібно використовувати цей підхід, починаючи з андроїда 4.2
Джордж Діма

2
SPP = профіль послідовного порту (який імітує послідовний порт через bluetooth), а ELM327 - автомобільний пристрій bluetooth <->, гугл його.
Джордж Діма

10
Він працював для мене після того, як змінив значення порту з 1 на 2.можливо переглянути цей код. socket = (BluetoothSocket) device.getClass (). getMethod ("createRfcommSocket", новий клас [] {int.class}). call (пристрій, 2); socket.connect ();
Дінеш IT

16

По-перше, якщо вам потрібно поговорити з пристроєм Bluetooth 2.x, у цій документації зазначено, що:

Підказка: Якщо ви підключаєтесь до послідовної плати Bluetooth, то спробуйте використовувати відомий SPP UUID 00001101-0000-1000-8000-00805F9B34FB . Однак якщо ви підключаєтесь до Android-однолітків, то створіть власний унікальний UUID.

Я не думав, що це буде працювати, але лише заміни UUID 00001101-0000-1000-8000-00805F9B34FBним працює. Тим НЕ менше, цей код здається , щоб впоратися з проблемою SDK версії, і ви можете просто замінити функцію device.createRfcommSocketToServiceRecord(mMyUuid);з tmp = createBluetoothSocket(mmDevice);після визначення наступного методу:

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

Вихідний код не мій, але надходить з цього веб-сайту .


1
Це вирішило майже 2 дні роботи ... вдячний зітхання ... Без цього UUID розетка негайно закриється і вийде з ладу без додаткових пояснень.
Девід Сінклер

велике спасибі за допомогу. МОЙ UUID буквено-цифровий, і я намагаюся підключити HC-5 і мій Bluetooth, що показує з'єднання, не вдалося, але коли я використав це рішення, свою проблему вирішити. ще раз дякую
Nikhil Shende

8

У мене були ті ж симптоми, що описані тут. Я міг один раз підключитися до Bluetooth-принтера, але наступні з’єднання не вдалося із "розеткою закритою", незалежно від того, що я робив.

Мені здалося трохи дивним, що описані тут обхідні шляхи знадобляться. Переглянувши код, я виявив, що забув закрити InputStream і OutputSteram сокета і не припинив належним чином ConnectedThreads.

Я використовую ConnectedThread такий же, як у прикладі тут:

http://developer.android.com/guide/topics/connectivity/bluetooth.html

Зауважте, що ConnectThread та ConnectedThread - це два різні класи.

Незалежно від класу, який запускає ConnectedThread, слід викликати interrupt () та cancel () у потоці. Я додав mmInStream.close () та mmOutStream.close () у методі ConnectedTread.cancel ().

Після належного закриття ниток / потоків / сокет я міг створити нові розетки без проблем.


Дякую, виникли ті самі проблеми, просто зараз я зрозумів, що не закрив потік і з'єднання ...
Рафаель,

спробував усі вищевказані сценарії (за винятком видалення інших парних пристроїв, добре, що насправді не знайдено рішення, що так ... це зазвичай відбувається лише тоді, коли вхідні потоки та сокети не закриваються належним чином ..... !!
Аман Сатья

7

Ну, я фактично знайшов проблему.

Більшість людей, які намагаються встановити з'єднання за допомогою, socket.Connect();отримують назву винятку Java.IO.IOException: read failed, socket might closed, read ret: -1.

У деяких випадках це також залежить від вашого пристрою Bluetooth, оскільки є два різних типи Bluetooth, а саме BLE (низька енергія) та Classic.

Якщо ви хочете перевірити тип вашого пристрою Bluetooth, ось код:

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

Я цілими днями намагався вирішити проблему, але з сьогоднішнього дня я знайшов проблему. На жаль, рішення від @matthes, як і раніше, має ще кілька питань, але ось моє рішення.

На даний момент я працюю в Android Xamarin, але це має працювати і для інших платформ.

РІШЕННЯ

Якщо є декілька парних пристроїв, тоді слід видалити інші парні пристрої. Тому зберігайте лише той, який ви хочете підключити (див. Правильне зображення).

введіть тут опис зображення введіть тут опис зображення

На зображенні зліва ви бачите, що у мене є два парні пристрої, а саме "MOCUTE-032_B52-CA7E" та "Blue Easy". Це питання, але я поняття не маю, чому така проблема виникає. Можливо, протокол Bluetooth намагається отримати деяку інформацію з іншого пристрою Bluetooth.

Однак, socket.Connect();чудово працює зараз, без проблем. Тому я просто хотів поділитися цим, бо ця помилка насправді дратує.

Удачі!


Це працювало на одному пристрої, де я стикаюся з цією проблемою, яка виникає у мене лише на телефоні 5.0, і навіть тоді, коли я вперше вмикаю BT, а потім відкриваю з'єднання. Якщо БТ вже ввімкнено, жодних проблем із підключенням немає! Це не трапляється на пристроях із пізнішою версією Android, припускаючи, що розробники помітили помилку та виправили її, але сторінка Android BT про це не говорить. Але ваше рішення працює, дякую!
Джон Перрі

7

У нових версіях Android я отримував цю помилку, оскільки адаптер все ще виявляв, коли я намагався підключитися до сокета. Незважаючи на те, що я закликав метод cancelDiscovery на адаптері Bluetooth, мені довелося чекати, поки буде викликано зворотний виклик методу onReceive () BroadcastReceiver () з дією BluetoothAdapter.ACTION_DISCOVERY_FINISHED.

Як тільки я чекав, коли адаптер припинить виявлення, тоді виклик з'єднання на розетці вдався.


6

Ви ставите registerReceiver(receiver, new IntentFilter("android.bleutooth.device.action.UUID")); з "bluetooth" написано "bleutooth".


4

Якщо у когось є проблеми з Котліном, я повинен був дотримуватися прийнятої відповіді з деякими варіаціями:

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()
            }
        }
    }
}

Сподіваюся, це допомагає


3

Пристрої Bluetooth можуть одночасно працювати як у класичному, так і в LE режимі. Іноді вони використовують іншу MAC-адресу залежно від способу підключення. Дзвінокsocket.connect() використовується Bluetooth Classic, тому ви повинні переконатися, що пристрій, який ви отримали під час сканування, був справді класичним пристроєм.

Однак легко фільтрувати лише класичні пристрої:

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

Без цієї перевірки, умова перегонів щодо того, чи спочатку гібридна розгортка дасть вам класичний пристрій чи пристрій BLE. Це може виявлятися як переривчаста неможливість підключення, або як певні пристрої здатні надійно підключитися, тоді як інші, здавалося б, ніколи не можуть.


1

Я також зіткнувся з цією проблемою, ви могли вирішити її двома способами, як згадувалося раніше, використовуйте відображення для створення сокета. Другий - клієнт шукає сервер із заданим UUID, і якщо ваш сервер не працює паралельно клієнту, це буває. Створіть сервер із заданим клієнтським UUID, а потім слухайте та приймайте клієнта з боку сервера. Він буде працювати.


1

Я зіткнувся з цією проблемою і вирішив її, закривши вхідні та вихідні потоки перед тим, як закрити сокет. Тепер я можу відключитися та знову підключитися без проблем.

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

У Котліні:

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

1

Якщо інша частина вашого коду вже зробила з'єднання з тим же сокетом та UUID, ви отримаєте цю помилку.


0

Навіть у мене була та сама проблема, нарешті зрозумів свою проблему, я намагався підключитись із (поза діапазоном) діапазону покриття Bluetooth.


0

У мене була ця проблема, і рішенням було скористатися спеціальним магічним посібником.

            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.

Я підозрюю, що це UUID, які працюють:

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

Однак я не пробував їх усіх.


Навіть я використовую той же UUID. Але мені це не допомогло. Чи підтримується це лише для підключення до класичних пристроїв Bluetooth (не BLE)? Що мені потрібно зробити, щоб підключитися до пристроїв BLE за допомогою Xamarin.Forms. Опубліковано тут [ stackoverflow.com/questions/62371859/…
Шайлеш Бхат

Я використовую класичний Bluetooth; BLE - сміття.
Річард Барраклу

-1

Додавши дію фільтра, моя проблема вирішена

 // 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

Я теж отримав те саме IOException, але я вважаю демонстрацію системи Android: проект "BluetoothChat" працює. Я визначив, що проблема - UUID.

Тому я замінити UUID.fromString("00001001-0000-1000-8000-00805F9B34FB")на UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66")і працював велику сцену, тільки іноді необхідно перезавантажити пристрій Bluetooth;

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.