IOException: पढ़ा गया विफल, सॉकेट बंद हो सकता है - Android 4.3 पर ब्लूटूथ


100

वर्तमान में मैं अपने नेक्सस 7 (2012) पर एक ब्लूटूथसेट को खोलने पर एक अजीब अपवाद से निपटने की कोशिश कर रहा हूं, एंड्रॉइड 4.3 (बिल्ड JWR66Y के साथ, मैं दूसरे 4.3 अपडेट का अनुमान लगाता हूं)। मैंने कुछ संबंधित पोस्टिंग देखी हैं (उदाहरण के लिए) /programming/13648373/blu ), लेकिन कोई भी इस मुद्दे पर समाधान प्रदान नहीं करता है। इसके अलावा, जैसा कि इन थ्रेड्स में सुझाव दिया गया है, फिर से बाँधना मदद नहीं करता है, और लगातार कनेक्ट करने की कोशिश कर रहा है (एक बेवकूफ लूप के माध्यम से) भी कोई प्रभाव नहीं पड़ता है।

मैं एक एम्बेडेड डिवाइस (एक बिना नाम वाली OBD-II कार अडैप्टर, के समान काम कर रहा हूं http://images04.olx.com/ui/15/53/76/1316534072_254254776_2-OBD-II-BLUTOOTH-ADAPTERSCLEAR-CHECK-ENGINE- के LIGHTS-with-YOUR-PHONE-Oceanside.jpg )। मेरे एंड्रॉइड 2.3.7 फोन में कनेक्ट करने के लिए कोई समस्या नहीं है, और एक सहयोगी (एंड्रॉइड 4.1.2) का एक्सपीरिया भी काम करता है। एक अन्य Google Nexus (मुझे नहीं पता कि 'One' या '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/bluaxy/BluisSocket.java#L504 इसे readInt () के माध्यम से कहा जाता है। https : //github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothSocket.java#L319

उपयोग किए गए सॉकेट के कुछ मेटाडेटा डंप के परिणामस्वरूप निम्नलिखित जानकारी प्राप्त हुई। नेक्सस 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 एडेप्टर (अधिक विस्तारक) हैं और वे सभी काम करते हैं। क्या कोई मौका है, कि मैं कुछ याद कर रहा हूं या यह एंड्रॉइड में बग हो सकता है?


मैंने उपरोक्त समाधान की कोशिश की है, क्या कोई इस मुद्दे पर मदद कर सकता है stackoverflow.com/q/52105647/1559331
dileepVikram

जवाबों:


129

मुझे आखिरकार एक वर्कअराउंड मिल गया है। जादू BluetoothDeviceवर्ग के हुड के नीचे छिपा हुआ है (देखें https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluaxy/BluaxyDevice.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()तब कोई भी विफल नहीं होता है। मैंने अभी भी कुछ मुद्दों का अनुभव किया है। असल में, यह कभी-कभी ब्लॉक और विफल हो जाता है। एसपीपी-डिवाइस को रिबूट करना (प्लग / प्लग इन) ऐसे मामलों में मदद करता है। कभी-कभी मुझे 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
@ मुझे पता नहीं कैसे। मैंने सिर्फ परीक्षण किया और पाया कि यह काम कर रहा है।
बोब्स

1
यह सांठगांठ 4 पर काम नहीं करता है। क्या आप कृपया बता सकते हैं कि इस समस्या को कैसे दूर किया जाए। मैंने लगभग हर कोशिश की है। धन्यवाद।
शाह

3
@matthes कहने के लिए क्षमा करें, लेकिन यहां तक ​​कि आपके द्वारा फॉलबैक का उपयोग करने के समाधान ने मेरी समस्या का समाधान नहीं किया है। त्रुटि के नीचे हो रही है। Fallback failed. Cancelling. java.io.IOException: Connection refused कृपया मदद कीजिए।
तुषार बान

2
@matthes "एसपीपी-डिवाइस (प्लग / प्लग इन) ऐसे मामलों में मदद करता है।" ऑन / ऑफ स्टेटमेंट दुनिया में सबसे कमतर है। मैंने सिर्फ 3 घंटे बर्बाद किए और मुझे बस इतना करना था कि इसे चालू और बंद कर दिया जाए -_-
Adz

98

ठीक है, मैं अपने कोड के साथ एक ही समस्या थी, और यह इसलिए है क्योंकि Android 4.2 ब्लूटूथ स्टैक बदल गया है। इसलिए मेरा कोड एंड्रॉइड <4.2 के साथ उपकरणों पर ठीक चल रहा था, अन्य उपकरणों पर मुझे प्रसिद्ध अपवाद मिल रहा था "पढ़ने में विफल रहा, सॉकेट बंद हो सकता है या समय समाप्त हो सकता है, पढ़ें रिट: -1"

समस्या socket.mPortपैरामीटर के साथ है । जब आप अपने सॉकेट का उपयोग करते हुए बनाते हैं socket = device.createRfcommSocketToServiceRecord(SERIAL_UUID);, तो mPortपूर्णांक मान " -1 " हो जाता है , और यह मान Android> = 4.2 के लिए काम नहीं करता है, इसलिए आपको इसे " 1 " पर सेट करने की आवश्यकता है । बुरी खबर यह है कि createRfcommSocketToServiceRecordकेवल यूयूआईडी को पैरामीटर के रूप में स्वीकार किया जाता है और mPortइसलिए हमें अन्य aproach का उपयोग नहीं करना है। @Matthes द्वारा पोस्ट किए गए जवाब ने भी मेरे लिए काम किया, लेकिन मैंने इसे सरल किया socket =(BluetoothSocket) device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(device,1);:। हमें दोनों सॉकेट एट्रिब्यूशन का उपयोग करने की आवश्यकता है, दूसरा एक कमबैक के रूप में।

तो कोड है (एक ELM327 डिवाइस पर SPP से कनेक्ट करने के लिए):

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पैरामीटर पर अंतर्दृष्टि के लिए धन्यवाद जॉर्ज ! imho वर्कफ़्लो वही रहता है, मैं बस कुछ वर्गों को एक इंटरफ़ेस को लागू करने के साथ लपेटता हूं।
Matthes

5
हां, मैंने पहले ही कहा था कि आपका समाधान अच्छा था, लेकिन मैं लोगों को यह समझाना चाहता था कि एंड्रॉइड 4.2 के साथ शुरू होने वाले इस दृष्टिकोण का उपयोग करने की आवश्यकता क्यों है
जॉर्ज

2
एसपीपी = सीरियल पोर्ट प्रोफाइल (जो कि ब्लूटूथ पर सीरियल पोर्ट का अनुकरण करता है) और ELM327 एक ब्लूटूथ <-> obd कार डिवाइस है, इसे Google करें।
जॉर्ज

10
इस कोड को 1 से 2.please देखने के लिए पोर्ट मान बदलने के बाद इसके लिए मेरे लिए काम किया। सॉकेट = (BluetoothSocket) device.getClass ()। getMethod ("createRfcommSocket", नई कक्षा [] {int.class})। इनवोक (डिवाइस, 2); socket.connect ();
दिनेश आईटी

16

सबसे पहले, यदि आपको ब्लूटूथ 2.x डिवाइस से बात करने की आवश्यकता है, तो यह प्रलेखन बताता है कि:

संकेत: यदि आप एक ब्लूटूथ सीरियल बोर्ड से कनेक्ट कर रहे हैं, तो जाने-माने SPP UUID 00001101-0000-1000-8000-00805F9B34FB का उपयोग करने का प्रयास करें । हालाँकि, यदि आप एक एंड्रॉइड पीयर से जुड़ रहे हैं, तो कृपया अपना विशिष्ट यूयूआईडी बनाएं।

मैंने नहीं सोचा था कि यह काम करेगा, लेकिन केवल यूयूआईडी की जगह इसके साथ 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 अल्फ़ान्यूमेरिक है और मैं HC-5 को जोड़ने की कोशिश कर रहा हूं और मेरा ब्लूटूथ कनेक्शन कनेक्शन विफल हो रहा है लेकिन जब मैंने इस समाधान का उपयोग किया तो मेरी समस्या हल हो गई। फिर से शुक्रिया
निखिल शेंडे

8

मेरे पास यहां वर्णित के समान लक्षण थे। मैं एक बार एक ब्लूटूथ प्रिंटर से कनेक्ट कर सकता था लेकिन बाद में कनेक्ट "सॉकेट बंद" के साथ विफल हो गया, इससे कोई फर्क नहीं पड़ता कि मैंने क्या किया।

मुझे यह थोड़ा अजीब लगा कि यहाँ वर्णित वर्कअराउंड आवश्यक होगा। अपने कोड के माध्यम से जाने के बाद मैंने पाया कि मैं सॉकेट के InputStream और OutputSteram को बंद करना भूल गया था और कनेक्टेडट्रेड्स को ठीक से समाप्त नहीं किया था।

कनेक्टेडह्रेड I का उपयोग यहां के उदाहरण के समान है:

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

ध्यान दें कि ConnectThread और ConnectedThread दो अलग-अलग वर्ग हैं।

जो भी क्लास कनेक्टेडथ्रेड शुरू करता है उसे थ्रेड पर इंटरप्ट () और कैंसिल () को कॉल करना होगा। मैंने ConnectedTread.cancel () विधि में mmInStream.close () और mmOutStream.close () जोड़ा।

थ्रेड / स्ट्रीम / सॉकेट को ठीक से बंद करने के बाद मैं बिना किसी समस्या के नए सॉकेट बना सकता था।


धन्यवाद, एक ही मुद्दा रहा था, अभी-अभी मुझे लगा कि मैंने स्ट्रीम और कनेक्शन को बंद नहीं किया है ...
राफेल

उपरोक्त सभी परिदृश्यों की कोशिश की, (अन्य युग्मित उपकरणों को हटाने के अलावा अच्छी तरह से कारण बनता है कि वास्तव में एक समाधान नहीं मिला है कि हाँ ... यह आमतौर पर केवल तब होता है जब इनपुट स्ट्रीम और सॉकेट ठीक से बंद नहीं होते हैं ..... !!
अमन सतीजा

7

खैर, मुझे वास्तव में समस्या मिल गई है।

अधिकांश लोग जो socket.Connect();एक अपवाद का उपयोग करके संबंध बनाने की कोशिश करते हैं उन्हें बुलाया जाता है Java.IO.IOException: read failed, socket might closed, read ret: -1

कुछ मामलों में यह आपके ब्लूटूथ डिवाइस पर भी निर्भर करता है, क्योंकि दो अलग-अलग प्रकार के ब्लूटूथ होते हैं, जिनका नाम है BLE (कम ऊर्जा) और क्लासिक।

यदि आप अपने ब्लूटूथ डिवाइस के प्रकार की जांच करना चाहते हैं, तो यहां कोड है:

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

मैं समस्या को हल करने के लिए कई दिनों से कोशिश कर रहा हूं, लेकिन आज से मुझे समस्या का पता चल गया है। @ काम से समाधान अभी भी कुछ मुद्दों के रूप में वह पहले से ही कहा है, लेकिन यहाँ मेरा समाधान है।

फिलहाल मैं ज़ामरीन एंड्रॉइड में काम करता हूं, लेकिन यह अन्य प्लेटफार्मों के लिए भी काम करना चाहिए।

उपाय

यदि एक से अधिक युग्मित उपकरण हैं, तो आपको अन्य युग्मित उपकरणों को हटा देना चाहिए। इसलिए केवल वही रखें जिसे आप कनेक्ट करना चाहते हैं (सही छवि देखें)।

यहां छवि विवरण दर्ज करें यहां छवि विवरण दर्ज करें

बाईं छवि में आप देखते हैं कि मेरे पास दो युग्मित उपकरण हैं, जैसे "MOCUTE-032_B52-CA7E" और "ब्लू इज़ी"। यह मुद्दा है, लेकिन मुझे नहीं पता कि यह समस्या क्यों होती है। हो सकता है कि ब्लूटूथ प्रोटोकॉल किसी अन्य ब्लूटूथ डिवाइस से कुछ जानकारी प्राप्त करने की कोशिश कर रहा हो।

हालाँकि, socket.Connect();अभी बहुत अच्छा काम करता है, बिना किसी समस्या के। इसलिए मैं इसे साझा करना चाहता था, क्योंकि वह त्रुटि वास्तव में कष्टप्रद है।

सौभाग्य!


यह एक डिवाइस पर काम करता है जहां मैं इस समस्या का सामना करता हूं, जो केवल मेरे लिए 5.0 फोन पर होता है, और तब भी जब मैं पहली बार बीटी को सक्षम कर रहा हूं, फिर एक कनेक्शन खोल रहा हूं। यदि बीटी पहले से ही थे, तो कोई कनेक्शन समस्या नहीं! यह एंड्रॉइड के बाद के संस्करण के साथ उपकरणों पर नहीं होता है, यह सुझाव देते हुए कि देवताओं ने बग को देखा और इसे ठीक किया, लेकिन एंड्रॉइड बीटी पृष्ठ में इसके बारे में एक शब्द भी नहीं है। लेकिन आपका समाधान काम करता है, धन्यवाद!
जॉन पेरी

7

एंड्रॉइड के नए संस्करणों पर, मुझे यह त्रुटि मिल रही थी क्योंकि एडॉप्टर अभी भी खोज रहा था जब मैंने सॉकेट से कनेक्ट करने का प्रयास किया था। भले ही मैंने ब्लूटूथ एडॉप्टर पर कैंसिलडिस्कवरी विधि को कॉल किया था, लेकिन मुझे ब्रॉडकास्टसीवर के ऑनरिविव () पद्धति के कॉलबैक तक इंतजार करना पड़ा, जिसमें एक्शन ब्लूटूथ एडेप्टर.ACTION_DISCOVERY -FINISHED लिखा था।

एक बार जब मैंने एडॉप्टर की खोज बंद करने का इंतजार किया, तो सॉकेट पर कनेक्ट कॉल सफल हो गया।


6

आपने registerReceiver(receiver, new IntentFilter("android.bleutooth.device.action.UUID")); "ब्लूटूथ" के साथ "ब्लुटूथ" लिखा है।


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

ब्लूटूथ डिवाइस एक ही समय में क्लासिक और ले मोड दोनों में काम कर सकते हैं। कभी-कभी वे एक अलग मैक पते का उपयोग करते हैं, जिसके आधार पर आप कनेक्ट कर रहे हैं। कॉलिंगsocket.connect() ब्लूटूथ क्लासिक का उपयोग कर रही है, इसलिए आपको यह सुनिश्चित करना होगा कि जब आपको स्कैन किया गया डिवाइस वास्तव में एक क्लासिक डिवाइस था।

हालाँकि, केवल क्लासिक उपकरणों के लिए फ़िल्टर करना आसान है:

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

इस जांच के बिना, यह एक दौड़ की स्थिति है जैसे कि हाइब्रिड स्कैन आपको क्लासिक डिवाइस या बीएलई डिवाइस पहले देगा। यह कनेक्ट करने के लिए आंतरायिक अक्षमता के रूप में प्रकट हो सकता है, या कुछ उपकरणों को मज़बूती से कनेक्ट करने में सक्षम होने के रूप में, जबकि अन्य कभी नहीं लग सकते हैं।


1

मुझे भी इस समस्या का सामना करना पड़ा, आप इसे 2 तरीकों से हल कर सकते हैं, जैसा कि पहले बताया गया था कि सॉकेट बनाने के लिए प्रतिबिंब का उपयोग करें दूसरा एक है, ग्राहक दिए गए UUID के साथ एक सर्वर की तलाश कर रहा है और यदि आपका सर्वर क्लाइंट के समानांतर नहीं चल रहा है तो यह हो जाता। दिए गए क्लाइंट UUID के साथ एक सर्वर बनाएं और फिर सर्वर साइड से क्लाइंट को सुनें और स्वीकार करें। यह काम करेगा।


1

मैं इस समस्या में भाग गया और सॉकेट बंद करने से पहले इनपुट और आउटपुट स्ट्रीम को बंद करके इसे ठीक कर दिया। अब मैं डिस्कनेक्ट कर सकता हूं और फिर से बिना किसी मुद्दे के जुड़ सकता हूं।

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

कोटलिन में:

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

1

यदि आपके कोड के दूसरे भाग ने पहले से ही सॉकेट और UUID के साथ एक कनेक्शन बना लिया है, तो आपको यह त्रुटि मिलती है।


0

यहां तक ​​कि मुझे भी यही समस्या थी, आखिरकार मेरे मुद्दे को समझें, मैं ब्लूटूथ कवरेज रेंज से (रेंज के बाहर) कनेक्ट करने की कोशिश कर रहा था।


0

मेरे पास यह समस्या है और समाधान विशेष जादू GUID का उपयोग करना था।

            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.

मुझे संदेह है कि ये यूयूआईडी हैं जो काम करते हैं:

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

हालांकि, मैंने उन सभी की कोशिश नहीं की है।


यहां तक ​​कि मैं उसी UUID का उपयोग कर रहा हूं। लेकिन मेरी मदद नहीं की। क्या यह केवल क्लासिक ब्लूटूथ डिवाइस (BLE नहीं) से कनेक्ट करने के लिए समर्थन करता है? मुझे Xamarin.Forms का उपयोग करके BLE डिवाइस से कनेक्ट करने के लिए क्या करना है। यहाँ प्रकाशित किया गया था [ stackoverflow.com/questions/62371859/…
शैलेश भट्ट

मैं क्लासिक ब्लूटूथ का उपयोग कर रहा हूं; 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, लेकिन मुझे एंड्रॉइड सिस्टम डेमो मिला: "ब्लूटूथचैट" प्रोजेक्ट पर काम किया गया। मैंने निर्धारित किया कि समस्या यूयूआईडी है।

तो मैं अपने को बदलने UUID.fromString("00001001-0000-1000-8000-00805F9B34FB")के लिए UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66")और यह सबसे अधिक दृश्य काम किया, केवल कभी कभी ब्लूटूथ डिवाइस को पुनः आरंभ करने की जरूरत है;

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.