Odłącz Gniazdo bluetooth w Androidzie

Opracowuję program, w którym z telefonu z Androidem muszę połączyć się jako klient z czujnikiem medycznym Bluetooth. Używam oficjalnego API Bluetooth i nie ma problemu podczas połączenia (profil SPP), ale po zakończeniu gniazda czujnik jest nadal podłączony do mojego telefonu(chociaż mam bliskie połączenie).

Czy Jest jakiś sposób na rozłączenie Bluetooth? Myślę, że istnieje intencja zwana ACTION_ACL_CONNECTED, która to robi. Czy ktoś może mi wyjaśnić jak używać to?

Z góry dzięki.

EDITED: oto Kod, jeśli ktoś potrzebuje dodatkowych informacji, to czujnik Medyczny Nonin 4100.

Set<BluetoothDevice> pairedDevices = Activa.myBluetoothAdapter.getBondedDevices();
        // If there are paired devices
        if (pairedDevices.size() > 0) {
            // Loop through paired devices
            for (BluetoothDevice device : pairedDevices) {
                // Add the name and address to an array adapter to show in a ListView
                String name = device.getName();
                if (name.contains("Nonin")) {
                    try {
                        found = true;
//                      socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
//                      handler.sendEmptyMessage(5);
//                      Activa.myBluetoothAdapter.cancelDiscovery();
//                      socket.connect();
                        BluetoothDevice hxm = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(device.getAddress());
                        Method m;
                        try {
                            m = hxm.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
                            socket = (BluetoothSocket)m.invoke(hxm, Integer.valueOf(1));
                            handler.sendEmptyMessage(5);
                            socket.connect();
                        } catch (Exception e) {
                            handler.sendEmptyMessage(7);
                            e.printStackTrace();
                            break;
                        }
                        handler.sendEmptyMessage(6);
                        InputStream in = socket.getInputStream();
                        OutputStream out = socket.getOutputStream();
                        byte[] retrieve = { 0x44, 0x31};
                        out.write(retrieve);
                        byte [] ack = new byte [1];
                        in.read(ack);
                        if (ack[0] == 0x15) {
                            cancelMeasurement();
                            return;
                        }
                        byte [] data = new byte [3];
                        long timeStart = System.currentTimeMillis();
                        this.timePassed = System.currentTimeMillis() - timeStart;
                        while ((this.timePassed < (this.time))&&(this.finished)) {
                            try {
                                in.read(data);
                                processData(data);
                                Thread.sleep(1000);
                                this.timePassed = System.currentTimeMillis() - timeStart;
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                        in.close();
                        out.close();
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
}
Author: user365610, 2010-06-13

6 answers

Pamiętaj, aby najpierw zamknąć strumienie wejściowe/wyjściowe, a następnie zamknąć Gniazdo.

Zamykając strumienie, rozpoczynasz proces rozłączania. Po zamknięciu Gniazda Połączenie powinno zostać całkowicie przerwane.

Jeśli zamkniesz gniazdo przed strumieniami, możesz ominąć pewne kroki zamykania, takie jak (właściwe) zamknięcie połączenia warstwy fizycznej.

Oto metoda, której używam, gdy jej czas na zerwanie połączenia.

/**
 * Reset input and output streams and make sure socket is closed. 
 * This method will be used during shutdown() to ensure that the connection is properly closed during a shutdown.  
 * @return
 */
private void resetConnection() {
        if (mBTInputStream != null) {
                try {mBTInputStream.close();} catch (Exception e) {}
                mBTInputStream = null;
        }

        if (mBTOutputStream != null) {
                try {mBTOutputStream.close();} catch (Exception e) {}
                mBTOutputStream = null;
        }

        if (mBTSocket != null) {
                try {mBTSocket.close();} catch (Exception e) {}
                mBTSocket = null;
        }

}

EDIT: dodanie kodu dla connect ():

// bluetooth adapter which provides access to bluetooth functionality. 
BluetoothAdapter        mBTAdapter      = null;
// socket represents the open connection.
BluetoothSocket         mBTSocket   = null;
// device represents the peer
BluetoothDevice         mBTDevice       = null; 

// streams
InputStream           mBTInputStream  = null;
OutputStream          mBTOutputStream = null;

static final UUID UUID_RFCOMM_GENERIC = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

/**
 * Try to establish a connection with the peer. 
 * This method runs synchronously and blocks for one or more seconds while it does its thing 
 * SO CALL IT FROM A NON-UI THREAD!
 * @return - returns true if the connection has been established and is ready for use. False otherwise. 
 */
private  boolean connect() {

        // Reset all streams and socket.
        resetConnection();

        // make sure peer is defined as a valid device based on their MAC. If not then do it. 
        if (mBTDevice == null) 
                mBTDevice = mBTAdapter.getRemoteDevice(mPeerMAC);

        // Make an RFCOMM binding. 
        try {mBTSocket = mBTDevice.createRfcommSocketToServiceRecord(UUID_RFCOMM_GENERIC);
        } catch (Exception e1) {
                msg ("connect(): Failed to bind to RFCOMM by UUID. msg=" + e1.getMessage());
                return false;
        }

        msg ("connect(): Trying to connect.");

        try {
                mBTSocket.connect();
        } catch (Exception e) {
                msg ("connect(): Exception thrown during connect: " + e.getMessage());
                return false;
        }

        msg ("connect(): CONNECTED!");

        try {
                mBTOutputStream = mBTSocket.getOutputStream();
                mBTInputStream  = mBTSocket.getInputStream();
        } catch (Exception e) {
                msg ("connect(): Error attaching i/o streams to socket. msg=" + e.getMessage());
                return false;
        }

        return true;
}
 58
Author: Brad Hein,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-16 12:46:56

Znalazłem, że jeśli zadzwonię do socket.close() zbyt szybko po ostatniej komunikacji za pośrednictwem OutputStream, wtedy close zawiedzie i nie mogę ponownie się połączyć. Dodałem wątek.uśpienia (1000) tuż przed wywołaniem zamknięcia () i to zdaje się go rozwiązać.

 12
Author: djilk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-31 18:23:02

Cześć,

Widziałem dokładnie ten sam problem (HTC Desire). Pomimo zamknięcia gniazda przez książkę (jak sugeruje Brad), następne connect() blokuje się na zawsze - do zakończenia przez close () przez inny wątek.

Obejrzałem problem, zawsze dzwoniąc do BluetoothAdapter.disable()/.enable () przed połączeniem. Okropne, nieprzyjazne włamanie, wiem...

Podejrzewam, że niektóre z obecnych problemów BT są specyficzne dla producenta, ponieważ niektórzy implementatorzy aplikacji wydają się żyć szczęśliwie z createRfcommSocketToServiceRecord (), który zdecydowanie zawodzi na moim HTC Desire (Android 2.1 update 1).

Widziałem sygnały (przepraszam, nie mam referencji), że stos HTC Desire BT różni się od Nexus One, choć wydają się być bardzo podobne urządzenia...

BR Na

(dodatek) Oto bardzo prosta czynność, aby odtworzyć problem (bez mojego wyłączania/włączania "wyleczenia"):

package com.care2wear.BtTest;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;

public class BtTestActivity extends Activity {
    private static final String TAG="BtTest";

    BluetoothAdapter mBtAdapter = null;
    BluetoothDevice mBtDev = null;
    BluetoothSocket mBtSocket = null;
    InputStream isBt;
    OutputStream osBt;  
    String mAddress = "00:18:E4:1C:A4:66";

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);


        init();

        connect();  // ok
        disconnect(); // ok
        connect(); // this invariably fails - blocked until BT is switched off by someone else, or the peer device turns off/goes out of range
        disconnect();
    }

    private void init() {
        Log.d(TAG, "initializing");
        mBtAdapter = BluetoothAdapter.getDefaultAdapter();
        mBtDev = mBtAdapter.getRemoteDevice(mAddress);
        Log.d(TAG, "initialized");
    }

    private void connect() {
        try {
            Log.d(TAG, "connecting");
            Method m = mBtDev.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
            mBtSocket = (BluetoothSocket) m.invoke(mBtDev, 1);
            mBtSocket.connect();
            Log.d(TAG, "connected");
        } catch (SecurityException e) {
            Log.e(TAG, "SecEx", e);
        } catch (NoSuchMethodException e) {
            Log.e(TAG, "NsmEx", e);
        } catch (IllegalArgumentException e) {
            Log.e(TAG, "IArgEx", e);
        } catch (IllegalAccessException e) {
            Log.e(TAG, "IAccEx", e);
        } catch (InvocationTargetException e) {
            Log.e(TAG, "ItEx", e);
        } catch (IOException e) {
            Log.e(TAG, "IOEx", e);
        }

    }

    private void disconnect() {
        Log.d(TAG, "closing");

        if (isBt != null) {
            try {
                isBt.close();
            } catch (IOException e) {
                Log.e(TAG, "isBt IOE", e);              
            }
            isBt = null;
        }
        if (osBt != null) {
            try {
                osBt.close();
            } catch (IOException e) {
                Log.e(TAG, "osBt IOE", e);              
            }
            osBt = null;
        }
        if (mBtSocket != null) {
            try {
                mBtSocket.close();
            } catch (IOException e) {
                Log.e(TAG, "socket IOE", e);                
            }
            mBtSocket = null;
        }
        Log.d(TAG, "closed");       
    }
}

Jeśli ktoś może zauważyć, czy robię to źle, zapraszam do komentowania :)

(dodatek 2) Chyba mi się udało:

  1. oficjalna metoda łączenia RFCOMM (przez SDP) teraz wydaje się działać (HTC Desire, 2.1 update 1), ale musiałem usunąć i ponownie sparować urządzenie BT. Pomyśl..
  2. ponowne połączenie może się nie udać (błąd wykrywania usługi), Jeśli ponownie połączę się "zbyt szybko" (zamknij aplikację, a następnie natychmiast uruchom ponownie). Domyślam się, że połączenie nie jest jeszcze całkowicie wyłączone..
  3. Jeśli zawsze zakończę (ostatnią) aktywność nie tylko z finish (), ale także z Runtime.getRuntime ().exit (0);, działa o wiele lepiej. Pomyśl jeszcze raz...
Jeśli ktoś może to wyjaśnić, chętnie się nauczę. / Per

(dodatek 3) W końcu dostałem Update Froyo (2.2) na moje życzenie i z tego co widzę, SPP teraz działa :) / Per

 9
Author: Per Laursen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-13 16:20:31

Tworzyłem aplikację, która łączy się z urządzeniem BT. Twój kod działa dobrze w moim HTC Wildfire, ale z Samsung Galaxy i5700 nie działa. Oba os są aktualizacją 2.1, ale.....

Wyjątkiem było 'InvocationTargetException'

Jedyną rzeczą, którą musiałem zmodyfikować, jest disconnect ().

private void disconnect() {
         if(Conectado){ 
            try {
                ***mBtSocket.close();***
                 texto.setText(texto.getText()+"\nDesconectado");
                 Conectado = false;
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                texto.setText(texto.getText()+"\n"+e1.getMessage());
            } 
            catch (Exception e2) {
                // TODO Auto-generated catch block
                texto.setText(texto.getText()+"\n"+e2.getMessage());
            }    
         }
 2
Author: user343464,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-29 16:27:25

Hej więc używam aplikacji Bluetooth Chat z Android Development site i zapewniają metodę stop() w klasie BluetoothChatService. Więc po prostu utworzyłem jego instancję w mojej głównej klasie i wywołałem funkcję stop z mojego przycisku rozłączenia.

Oto Jak to nazywam w mojej klasie głównej

/ / Member object for the chat services

private BluetoothManager mChatService = null;
case R.id.disconnect:
        mChatService.stop();
break;

Metoda stop() w BluetoothChatService

private AcceptThread mAcceptThread;
private ConnectThread mConnectThread;
public synchronized void stop() 
{
    if (mConnectThread != null)
    {
        mConnectThread.cancel(); mConnectThread = null;
    }
    if (mConnectedThread != null) 
    {
        mConnectedThread.cancel(); mConnectedThread = null;
    }
    if (mAcceptThread != null) 
    {
        mAcceptThread.cancel(); mAcceptThread = null;
    }
}
 1
Author: Rafael Mancilla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-25 12:04:02

Mam ten sam problem. Jest to problem z modułem Bluetooth CSR BC417, obecnym w wielu urządzeniach jako adapter szeregowy do bluetooth z profilem SPP. Z innym modułem Bluetooth urządzenie z Androidem działa dobrze, a bluetooth zwalnia połączenie po zamknięciu gniazda, ale z urządzeniami z tym rdzeniem CSR nie. Testowany na adapterze SPP Bluetooth na złącze szeregowe opartym na CSR BC417 oraz module Bluetooth firmy Actisys. Oba z urządzeniami z systemem Android 4.0. Nie wiem dlaczego, ale jest problem z kompatybilnością pomiędzy urządzeniami harware spróbuj zmienić adapter szeregowy na inny z innym rdzeniem. Staram się programowo znaleźć rozwiązanie, nawet wyłączając bluetooth, ale jest to niemożliwe, problem pochodzi z modułu CSR.

 0
Author: Cacho Paraguay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-24 20:38:49