IOException:読み取り失敗、ソケットが閉じている可能性-Android 4.3のBluetooth


100

現在、Nexus 7(2012)でBluetooth 4.3をAndroid 4.3(ビルドJWR66Y、2番目の4.3更新プログラム)で開くと、奇妙な例外に対処しようとしています。関連する投稿をいくつか見ました(例:https : //stackoverflow.com/questions/13648373/bluetoothsocket-connect-throwing-exception-read-failed)が、この問題の回避策を提供しているようには見えません。また、これらのスレッドで提案されているように、再ペアリングは役に立たず、常に(愚かなループを通じて)接続しようとしても効果がありません。

私は組み込みデバイス(noname 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)。私のAndroid 2.3.7電話は接続に問題がなく、同僚のXperia(Android 4.1.2)も動作します。別のGoogle Nexus(「1」か「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 https から呼び出され、readInt()から呼び出されます://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
うわー!素晴らしい解決策!
Bobs

2
@MDわからない。私はテストしたところ、機能していることがわかりました。
Bobs

1
ネクサス4では動作しません。この問題の解決方法を教えてください。私はほとんどすべてを試しました。ありがとう。
シャー

3
@matthes申し訳ありませんが、フォールバックを使用するソリューションでさえ、私の問題は解決していません。エラーを下回っています。Fallback failed. Cancelling. java.io.IOException: Connection refused 助けてください。
Tushar Banne 2016

2
@matthes "SPP-Device(プラグオフ/プラグイン)は、このような場合に役立ちます。" on / offステートメントは、世界で最も過小評価されています。3時間も無駄にしただけで、電源を入れたり切ったりするだけ
でし

98

よく、私は私のコードで同じ問題を抱えていました、そしてそれはアンドロイド4.2のbluetoothスタックが変更されたからです。だから私のコードはAndroid <4.2のデバイスでうまく実行されていました、他のデバイスでは私は有名な例外を得ていました「読み取り失敗、ソケットが閉じているかタイムアウトしている可能性があります。retを読み取ります:-1」

問題はsocket.mPortパラメータにあります。を使用してソケットを作成する場合socket = device.createRfcommSocketToServiceRecord(SERIAL_UUID);mPort整数値「-1」を取得します。この値はandroid> = 4.2では機能しないようなので、「1」に設定する必要があります。悪いニュースは、createRfcommSocketToServiceRecordUUIDをパラメーターとしてのみ受け入れるmPortため、他のアプローチを使用する必要があることです。@matthesによって投稿された回答も私には役立ちましたが、私はそれを簡略化しました:socket =(BluetoothSocket) device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(device,1);。両方のソケット属性を使用する必要があります。2番目はフォールバックとして使用します。

したがって、コードは(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パラメータに関する洞察を提供してくれたGeorgeに感謝します!ワークフローは同じままですが、インターフェイスを実装するいくつかのクラスでラップしました。
マシューズ2014

5
はい、私はすでにあなたのソリューションは優れていると言っていましたが、Android 4.2からこのアプローチを使用する必要がある理由を人々に理解させたいと思いました
George Dima

2
SPP =シリアルポートプロファイル(Bluetooth経由でシリアルポートをエミュレート)およびELM327はBluetooth <-> obdカーデバイスです。
ジョージディマ2015

10
ポート値を1から2に変更した後、それは私のために働きました。このコードを見てください。socket =(BluetoothSocket)device.getClass()。getMethod( "createRfcommSocket"、new Class [] {int.class})。invoke(device、2); socket.connect();
Dinesh 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がないと、ソケットはすぐに閉じて、それ以上の説明なしに失敗します。
David Sinclair

私のUUIDは英数字です。HC-5を接続しようとしていますが、Bluetoothが接続失敗を示していますが、このソリューションを使用すると問題が解決します。ありがとうございました
Nikhil Shende

8

ここで説明したのと同じ症状がありました。Bluetoothプリンターに1回接続することはできましたが、その後の接続は、何をしても「ソケットが閉じた」状態で失敗しました。

ここで説明する回避策が必要になるのは少し奇妙だと思いました。コードを調べたところ、ソケットのInputStreamとOutputSteramを閉じるのを忘れており、ConnectedThreadsを適切に終了していないことがわかりました。

私が使用するConnectedThreadは、次の例と同じです。

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

ConnectThreadとConnectedThreadは2つの異なるクラスであることに注意してください。

ConnectedThreadを開始するクラスは、スレッドでinterrupt()およびcancel()を呼び出す必要があります。ConnectedTread.cancel()メソッドにmmInStream.close()とmmOutStream.close()を追加しました。

スレッド/ストリーム/ソケットを適切に閉じた後、問題なく新しいソケットを作成できました。


おかげで、同じ問題が発生していましたが、たった今、私はストリームと接続を閉じていなかったと思いました...
Rafael

上記のシナリオをすべて試しました(他のペアリングされたデバイスを削除することを除いて、それは本当に解決策ではありません)はい...これは通常、入力ストリームとソケットが適切に閉じられない場合にのみ発生します... !!
アマンサティヤ

7

まあ、私は実際に問題を発見しました。

を使用して接続しようとするほとんどの人socket.Connect();は、という例外を受け取りますJava.IO.IOException: read failed, socket might closed, read ret: -1

Bluetoothには、BLE(低エネルギー)とクラシックの2つの異なるタイプがあるため、Bluetoothデバイスによって異なる場合もあります。

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の解決策には、残念ながらまだいくつかの問題がありますが、これが私の解決策です。

現時点ではXamarin Androidで作業していますが、これは他のプラットフォームでも機能するはずです。

解決

ペアリングされたデバイスが複数ある場合は、ペアリングされた他のデバイスを削除する必要があります。したがって、接続したいものだけを保持してください(右の画像を参照)。

ここに画像の説明を入力してください ここに画像の説明を入力してください

左の画像を見ると、「MOCUTE-032_B52-CA7E」と「Blue Easy」という2つのペアデバイスがあることがわかります。それが問題ですが、なぜその問題が発生するのかはわかりません。Bluetoothプロトコルが別のBluetoothデバイスから情報を取得しようとしている可能性があります。

しかし socket.Connect();今のところ問題なく動作しています。このエラーは本当に煩わしいので、私はこれを共有したかっただけです。

幸運を!


これは、この問題が発生した1つのデバイスで機能しました。この問題は5.0電話でのみ発生し、BTを最初に有効にして接続を開いたときにも発生します。BTがすでにオンになっている場合、接続の問題はありません。それ以降のバージョンのAndroidを搭載したデバイスでは発生せず、開発者がバグに気付いて修正したことを示唆していますが、Android BTページはそれについて一言も述べていません。しかし、あなたの解決策はうまくいきます!
ジョンペリー

7

新しいバージョンのAndroidでは、ソケットに接続しようとしたときにアダプターがまだ検出していたため、このエラーを受け取りました。BluetoothアダプターでcancelDiscoveryメソッドを呼び出しましたが、BroadcastReceiverのonReceive()メソッドへのコールバックがアクションBluetoothAdapter.ACTION_DISCOVERY_FINISHEDで呼び出されるまで待機する必要がありました。

アダプターがディスカバリーを停止するのを待つと、ソケットの接続呼び出しは成功しました。


6

あなたは置く registerReceiver(receiver, new IntentFilter("android.bleutooth.device.action.UUID")); 「ブルートゥース」綴ら「bleutooth」と。


4

誰かがKotlinで問題を抱えている場合、私はいくつかのバリエーションで受け入れられた答えに従う必要がありました:

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クラシックを使用しているため、スキャンしたときに取得したデバイスが本当にクラシックデバイスであることを確認する必要があります。

ただし、クラシックデバイスのみをフィルタリングするのは簡単です。

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

このチェックがないと、ハイブリッドスキャンでクラシックデバイスとBLEデバイスのどちらが先に表示されるかが競合状態になります。接続が断続的にできない、または特定のデバイスが確実に接続できるように見えても、他のデバイスでは接続できないように見える場合があります。


1

私はこの問題にも直面しました。2つの方法で解決できます。前述のように、リフレクションを使用してソケットを作成します。2番目の方法は、クライアントが指定されたUUIDのサーバーを探し、サーバーがクライアントと並行して実行されていない場合、これです。起こります。指定されたクライアントUUIDでサーバーを作成し、サーバー側からクライアントをリッスンして受け入れます。それは機能します。


1

私はこの問題に遭遇し、ソケットを閉じる前に入力ストリームと出力ストリームを閉じることで修正しました。今、私は問題なく切断して再接続することができます。

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

コトリンでは:

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

1

コードの別の部分がすでに同じソケットとUUIDで接続している場合、このエラーが発生します。


0

同じ問題が発生しましたが、最終的に私の問題を理解しました。Bluetoothの範囲外(範囲外)から接続しようとしていました。


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.

これらが機能するUUIDであると思います:

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

しかし、私はそれらすべてを試したことはありません。


同じUUIDを使用しています。しかし、私を助けませんでした。これはクラシックBluetoothデバイス(BLEではない)への接続のみをサポートしていますか?Xamarin.Formsを使用してBLEデバイスに接続するために私がしなければならないこと。[ここに投稿stackoverflow.com/questions/62371859/...
Shailesh Bhatさん

クラシックBluetoothを使用しています。BLEはゴミです。
Richard Barraclough

-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デバイスを再起動する必要があるだけです;

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.