IOException: okuma başarısız oldu, yuva kapalı olabilir - Android 4.3'te Bluetooth


100

Şu anda Android 4.3 ile Nexus 7 (2012) cihazımda bir BluetoothSocket açarken garip bir İstisna ile başa çıkmaya çalışıyorum (Derleme JWR66Y, sanırım ikinci 4.3 güncellemesi). Bazı ilgili gönderiler gördüm (ör. Https://stackoverflow.com/questions/13648373/bluetoothsocket-connect-throwing-exception-read-failed ), ancak hiçbiri bu sorun için bir çözüm sağlamıyor gibi görünüyor. Ayrıca, bu konu başlıklarında önerildiği gibi, yeniden eşleştirme yardımcı olmuyor ve sürekli bağlanmaya çalışmanın (aptal bir döngü aracılığıyla) da hiçbir etkisi yok.

Gömülü bir cihazla uğraşıyorum ( http://images04.olx.com/ui/15/53/76/1316534072_254254776_2-OBD-II-BLUTOOTH-ADAPTERSCLEAR-CHECK-ENGINE- benzeri, isimsiz bir OBD-II araç adaptörü TELEFONUNUZLA-IŞIKLARI-Oceanside.jpg ). Android 2.3.7 telefonumun bağlantı sorunu yok ve bir iş arkadaşımın Xperia'sı (Android 4.1.2) da çalışıyor. Başka bir Google Nexus ("Bir" mi yoksa "S" mi bilmiyorum ama "4" değil) Android 4.3 ile başarısız oluyor.

İşte bağlantı kuruluşunun Parçacığı. Bir Hizmet içinde oluşturulan kendi İş Parçacığı içinde çalışır.

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

}

Kod başarısız oluyor bluetoothSocket.connect(). Bir alıyorum java.io.IOException: read failed, socket might closed, read ret: -1. Bu, GitHub'daki ilgili kaynaktır: https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothSocket.java#L504 Onun çağrılabilir readInt () aracılığıyla denilen https : //github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothSocket.java#L319

Kullanılan soketin bazı meta veri dökümü aşağıdaki bilgilerle sonuçlandı. Bunlar Nexus 7 ve 2.3.7 telefonumda tamamen aynı.

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

Başka OBD-II adaptörüm var (daha geniş kapsamlı) ve hepsi çalışıyor. Bir şeyi kaçırma şansım var mı yoksa bu Android'de bir hata olabilir mi?


Yukarıdaki çözümü denedim, bu konuda yardımcı olabilirim stackoverflow.com/q/52105647/1559331
dileepVikram

Yanıtlar:


129

Sonunda bir geçici çözüm buldum. Sihir, BluetoothDevicesınıfın altında gizlidir (bkz. Https://github.com/android/platform_frameworks_base/blob/android-4.3_r2/core/java/android/bluetooth/BluetoothDevice.java#L1037 ).

Şimdi, bu istisnayı aldığımda BluetoothSocket, aşağıdaki kaynak koduna benzer bir geri dönüş başlatıyorum . Gördüğünüz gibi gizli yöntemi createRfcommSocketyansımalar aracılığıyla çağırmak . Bu yöntemin neden gizlendiğine dair hiçbir fikrim yok. Kaynak kodu onu publicsanki ...

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()daha sonra artık başarısız olmaz. Hala birkaç sorun yaşadım. Temel olarak, bu bazen engeller ve başarısız olur. SPP-Cihazını yeniden başlatmak (fişi kapatın / takın) bu gibi durumlarda yardımcı olur. Bazen connect()cihaz zaten bağlandığında bile başka bir Eşleştirme isteği alıyorum .

GÜNCELLEME:

burada bazı iç içe sınıfları içeren eksiksiz bir sınıf var. gerçek bir uygulama için bunlar ayrı sınıflar olarak tutulabilir.

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
Vaov! harika çözüm!
Bobs

2
@MD Nasıl olduğunu bilmiyorum. Sadece test ettim ve çalıştığını buldum.
Bobs

1
Nexus 4'te çalışmıyor. Lütfen bu sorunun nasıl üstesinden gelineceğini söyler misiniz? Neredeyse her şeyi denedim. Teşekkürler.
Shah

3
@matthes Söylediğim için üzgünüm ama geri dönüşü kullanma çözümünüz bile sorunumu çözmedi. Aşağıya Alınıyor Hata. Fallback failed. Cancelling. java.io.IOException: Connection refused Lütfen yardım et.
Tushar Banne

2
@matthes "SPP-Device (fişten çıkarın / takın) bu gibi durumlarda yardımcı olur." Açma / kapama ifadesi dünyadaki en küçümsenen ifadedir. Az önce 3 saatimi boşa harcadım ve tek yapmam gereken onu açıp kapatmaktı -_-
Adz

98

Eh, kodumla aynı sorunu yaşadım ve bunun nedeni android 4.2 bluetooth yığını değiştiğinden beri. bu yüzden kodum Android <4.2 olan cihazlarda sorunsuz çalışıyordu, diğer cihazlarda "okuma başarısız oldu, soket kapanabilir veya zaman aşımına uğradı, ret: -1'i oku" istisnasını alıyordum

Sorun socket.mPortparametrede. Eğer kullanarak soket oluşturduğunuzda socket = device.createRfcommSocketToServiceRecord(SERIAL_UUID);, mPortdeğer tamsayı "alır -1 " ve "olarak ayarlayın gerekir böylece bu değer, 4,2> = android için iş yapmaz görünüyor 1 ". Kötü haber şu ki, createRfcommSocketToServiceRecordsadece UUID'yi parametre olarak kabul ediyor ve bu mPortyüzden başka bir yaklaşım kullanmamız gerekiyor. Cevap tarafından gönderildi @matthes de benim için çalıştı, ama onu basitleştirilmiş: socket =(BluetoothSocket) device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(device,1);. Her iki soket özelliğini de kullanmalıyız, ikincisi yedek olarak.

Yani kod (bir ELM327 cihazında bir SPP'ye bağlanmak için):

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
moderatörler için: Önceki cevabımı sebepsiz yere sildiğiniz için tekrar gönderiyorum.
George Dima

2
mPortParametre hakkındaki görüşler için teşekkürler George ! imho iş akışı aynı kalıyor, sadece bir arayüz uygulayan bazı sınıflarla işleri tamamladım.
matthes

5
evet, zaten çözümünüzün iyi olduğunu söyledim, ancak insanların neden bu yaklaşımı kullanmaları gerektiğini anlamalarını sağlamak istedim. Android 4.2
George Dima

2
SPP = Seri Port Profili (bluetooth üzerinden bir seri portu taklit eder) ve ELM327 bir bluetooth <-> obd araç cihazıdır, google it.
George Dima

10
Bağlantı noktası değerini 1'den 2'ye değiştirdikten sonra benim için çalıştı. Lütfen bu koda bakın. soket = (BluetoothSocket) device.getClass (). getMethod ("createRfcommSocket", yeni Sınıf [] {int.class}). invoke (device, 2); socket.connect ();
Dinesh BT

16

Öncelikle, bir bluetooth 2.x cihazıyla konuşmanız gerekirse, bu belge şunları belirtir:

İpucu: Bir Bluetooth seri kartına bağlanıyorsanız, iyi bilinen SPP UUID 00001101-0000-1000-8000-00805F9B34FB'yi kullanmayı deneyin . Ancak bir Android eşdüzeyine bağlanıyorsanız, lütfen kendi benzersiz UUID'nizi oluşturun.

Bunun işe yarayacağını düşünmedim, ancak yalnızca UUID'yi onunla değiştirerek 00001101-0000-1000-8000-00805F9B34FBişe yarıyor. Bununla birlikte, bu kod SDK sürümünün sorununu ele alıyor gibi görünüyor ve işlevi aşağıdaki yöntemi tanımladıktan sonra device.createRfcommSocketToServiceRecord(mMyUuid);ile değiştirebilirsiniz 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);
}

Kaynak kodu benim değil ama bu web sitesinden geliyor .


1
Bu neredeyse 2 günlük çalışma çözüldü ... minnettar iç çekiş ... Bu UUID olmadan yuva hemen kapanır ve daha fazla açıklama yapılmadan başarısız olur.
David Sinclair

Yardım için çok teşekkür ederim UUID'm alfasayısaldır ve HC-5'i bağlamaya çalışıyorum ve bağlantımın başarısız olduğunu gösteren bluetooth'um ancak bu çözümü kullandığımda sorunum çözüldü. tekrar teşekkür ederim
Nikhil Shende

8

Burada anlatılanla aynı semptomlara sahiptim. Bir bluetooth yazıcısına bir kez bağlayabildim, ancak ne yaparsam yapayım "soket kapalı" ile sonraki bağlantılar başarısız oldu.

Burada açıklanan geçici çözümlerin gerekli olacağını biraz garip buldum. Kodumun üzerinden geçtikten sonra, soketin InputStream ve OutputSteram'ını kapatmayı unuttuğumu ve ConnectedThreads'i düzgün şekilde sonlandırmadığımı fark ettim.

Kullandığım ConnectedThread buradaki örnekteki ile aynı:

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

ConnectThread ve ConnectedThread'in iki farklı sınıf olduğunu unutmayın.

ConnectedThread'i başlatan sınıf ne olursa olsun iş parçacığı üzerinde interrupt () ve cancel () çağırmalıdır. ConnectedTread.cancel () yöntemine mmInStream.close () ve mmOutStream.close () ekledim.

Konuları / akışları / soketleri düzgün bir şekilde kapattıktan sonra herhangi bir sorun yaşamadan yeni soketler oluşturabilirim.


Teşekkürler, aynı sorunu yaşıyordum, şimdi akışı ve bağlantıyı kapatmadığımı anladım ...
Rafael

Yukarıdaki senaryoların tümünü denedim (diğer eşleştirilmiş cihazların kaldırılması dışında, gerçekten bir çözüm bulunmayan evet, bu normalde yalnızca giriş akışları ve soketler düzgün kapanmadığında gerçekleşir ..... !!
Aman Satija

7

Aslında sorunu buldum.

Kullanarak bağlantı kurmaya çalışan çoğu kişi, socket.Connect();adı verilen bir istisna alır Java.IO.IOException: read failed, socket might closed, read ret: -1.

Bazı durumlarda, Bluetooth cihazınıza da bağlıdır, çünkü iki farklı Bluetooth türü vardır, yani BLE (düşük enerji) ve Klasik.

Bluetooth cihazınızın türünü kontrol etmek istiyorsanız, kod şu şekildedir:

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

Günlerdir sorunu çözmeye çalışıyorum ama bugünden beri sorunu buldum. @Matthes'in çözümünün maalesef daha önce söylediği gibi hala birkaç sorunu var, ama işte benim çözümüm.

Şu anda Xamarin Android'de çalışıyorum, ancak bu diğer platformlar için de çalışmalı.

ÇÖZÜM

Birden fazla eşleştirilmiş cihaz varsa, diğer eşleştirilmiş cihazları kaldırmanız gerekir. Bu nedenle, yalnızca bağlamak istediğinizi saklayın (doğru resme bakın).

görüntü açıklamasını buraya girin görüntü açıklamasını buraya girin

Soldaki resimde "MOCUTE-032_B52-CA7E" ve "Blue Easy" olmak üzere iki eşleştirilmiş cihazım olduğunu görüyorsunuz. Sorun bu, ancak bu sorunun neden oluştuğuna dair hiçbir fikrim yok. Belki de Bluetooth protokolü başka bir Bluetooth cihazından bazı bilgiler almaya çalışıyor.

Ancak socket.Connect(); şu anda sorunsuz bir işler harika. Ben de bunu paylaşmak istedim çünkü bu hata gerçekten can sıkıcı.

İyi şanslar!


Bu, bu sorunla karşılaştığım tek cihazda çalıştı, bu sadece benim için bir 5.0 telefonda ve o zaman bile yalnızca BT'yi ilk etkinleştirip ardından bir bağlantı açtığımda ortaya çıktı. BT zaten açıksa, bağlantı sorunu yok! Android'in daha sonraki bir sürümüne sahip cihazlarda ortaya çıkmaz, bu da geliştiricilerin hatayı fark edip düzelttiklerini, ancak Android BT sayfasının bu konuda tek kelime etmediğini gösteriyor. Ama çözümünüz işe yarıyor, teşekkürler!
John Perry

7

Android'in daha yeni sürümlerinde, bu hatayı alıyordum çünkü sokete bağlanmaya çalıştığımda adaptör hala keşfediyordu. Bluetooth bağdaştırıcısında cancelDiscovery yöntemini çağırmama rağmen, BluetoothAdapter.ACTION_DISCOVERY_FINISHED eylemiyle BroadcastReceiver'ın onReceive () yöntemine yapılan geri arama çağrılana kadar beklemek zorunda kaldım.

Adaptörün keşfi durdurmasını bekledikten sonra soketteki bağlantı çağrısı başarılı oldu.


6

Sen koymak registerReceiver(receiver, new IntentFilter("android.bleutooth.device.action.UUID")); "bluetooth" yazıldığından "bleutooth" ile.


4

Birinin Kotlin ile sorunları olması durumunda, kabul edilen yanıtı bazı varyasyonlarla takip etmek zorunda kaldım:

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

Umarım yardımcı olur


3

Bluetooth cihazları aynı anda hem klasik hem de LE modunda çalışabilir. Bazen hangi yolla bağlandığınıza bağlı olarak farklı bir MAC adresi kullanırlar. Arama socket.connect()Bluetooth Classic kullanıyor, bu nedenle taradığınız zaman aldığınız cihazın gerçekten klasik bir cihaz olduğundan emin olmalısınız.

Yalnızca Klasik cihazlar için filtrelemek kolaydır, ancak:

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

Bu kontrol olmadan, hibrit taramanın size önce Klasik cihazı mı yoksa BLE cihazını mı vereceğine dair bir yarış koşulu. Ara sıra bağlanamama gibi görünebilir veya bazı cihazlar güvenilir bir şekilde bağlanırken diğerleri hiçbir zaman yapamaz gibi görünebilir.


1

Ben de bu problemle karşılaştım, daha önce de belirtildiği gibi 2 şekilde çözebilirsiniz, daha önce de belirtildiği gibi, soketi oluşturmak için yansıma kullanın İkincisi, müşteri belirli bir UUID'ye sahip bir sunucu arıyor ve sunucunuz istemciye paralel çalışmıyorsa, o zaman bu olur. Verilen istemci UUID'sine sahip bir sunucu oluşturun ve ardından istemciyi sunucu tarafından dinleyin ve kabul edin.


1

Bu problemle karşılaştım ve soketi kapatmadan önce giriş ve çıkış akışlarını kapatarak sorunu çözdüm. Artık hiçbir sorun olmadan bağlantıyı kesip tekrar bağlanabiliyorum.

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

Kotlin'de:

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

1

Kodunuzun başka bir bölümü aynı soket ve UUID ile zaten bağlantı kurduysa, bu hatayı alırsınız.


0

Aynı sorunu yaşadım bile, sonunda sorunumu anladım, (kapsama alanı dışında) Bluetooth kapsama alanından bağlanmaya çalışıyordum.


0

Bu sorunu yaşadım ve çözüm özel sihirli GUID kullanmaktı.

            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.

Bunların çalışan UUID'ler olduğundan şüpheleniyorum:

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

Ancak hepsini denemedim.


Ben bile aynı UUID kullanıyorum. Ama bana yardım etmedi. Bu, yalnızca Klasik bluetooth cihazlarına (BLE değil) bağlanmayı destekliyor mu? Xamarin.Forms kullanarak BLE cihazlarına bağlanmak için ne yapmam gerekiyor. Burada yayınlandı [ stackoverflow.com/questions/62371859/…
Shailesh Bhat

Klasik Bluetooth kullanıyorum; BLE çöptür.
Richard Barraclough

-1

Filtre eylemi ekleyerek sorunum çözüldü

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

Ben de aynısını IOExceptionaldım, ancak Android sistem demosunu buldum: "BluetoothChat" projesi çalıştı. Sorunun UUID olduğunu belirledim.

Bu yüzden değiştiriyorum UUID.fromString("00001001-0000-1000-8000-00805F9B34FB") etmek UUID.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66")ve çoğu sahneyi çalıştı, sadece bazen Bluetooth cihazını yeniden başlatmanız gerekir;

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.