Подтвердить что ты не робот

Отключите разъем Bluetooth в Android

Я разрабатываю программу, в которой с Android Phone я должен подключиться как клиент к медицинскому датчику Bluetooth. Я использую официальный Bluetooth API и никаких проблем при подключении (профиль SPP), но когда я заканчиваю сокет, датчик все еще подключен к моему телефону (хотя я закрыл соединение).

Есть ли способ отключить Bluetooth? Я думаю, что есть намерение, называемое ACTION_ACL_CONNECTED, которое делает это. Может ли кто-нибудь объяснить мне, как это использовать?

Спасибо заранее.

EDITED: Вот код, если кому-то нужна дополнительная информация, это медицинский датчик 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();
                    }
                }
            }
        }
}
4b9b3361

Ответ 1

Не забудьте сначала закрыть потоки ввода/вывода, затем закройте сокет.

Закрывая потоки, вы начинаете процесс отключения. После того, как вы закроете розетку, соединение должно быть полностью разрушено.

Если вы закрываете сокет перед потоками, вы можете обходить некоторые этапы выключения, такие как (правильное) закрытие соединения физического уровня.

Здесь метод, который я использую, когда его время разбивает соединение.

/**
 * 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: добавление кода для 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;
}

Ответ 2

Я обнаружил, что если я вызову socket.close() слишком скоро после недавней связи через OutputStream, то замыкание завершится неудачно, и я не могу повторно подключиться. Я добавил Thread.sleep(1000) непосредственно перед вызовом close(), и это, похоже, решит его.

Ответ 3

HI,

Я видел ту же самую проблему (HTC Desire). Несмотря на закрытие сокета книгой (как предлагает Брэд), следующий connect() блокирует навсегда - до тех пор, пока не завершится close() другим потоком.

Я обошел эту проблему, всегда вызывая BluetoothAdapter.disable()/. enable() перед подключением. Ужасный, недружелюбный хак, я знаю...

Я подозреваю, что некоторые из настоящих проблем с BT являются специфическими для производителя, поскольку некоторые разработчики приложений, похоже, счастливо живут с createRfcommSocketToServiceRecord(), которые, безусловно, терпят неудачу в моем HTC Desire (обновление Android 2.1).

Я видел показания (извините, не имеют ссылок), что стек HTC Desire BT отличается от Nexus One, хотя они, похоже, очень похожи на устройства...

BR Per

(дополнение) Здесь очень простая деятельность по воспроизведению проблемы (без моего отключения/включения "лечения" ):

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

Если кто-то может заметить, если я делаю это неправильно, не стесняйтесь комментировать:)

(дополнение 2) Я думаю, что теперь у меня это получилось:

  • Официальный способ подключения RFCOMM (через SDP) теперь, похоже, работает (HTC Desire, 2.1 update 1), НО Мне пришлось удалить и снова спарить устройство BT. Go figure..
  • Повторное соединение может по-прежнему терпеть неудачу (отказ службы обнаружения), если я снова подключусь слишком быстро (закройте приложение, а затем немедленно перезапустите). Угадайте, что соединение еще не полностью опущено.
  • Если я всегда заканчиваю (последнее) действие не только с помощью finish(), но также с Runtime.getRuntime(). exit (0);, он работает намного лучше. Идите еще раз...

Если кто-нибудь сможет это объяснить, я с радостью узнаю. /Per

(дополнение 3) Наконец, получил обновление Froyo (2.2) для моего желания, и, насколько я вижу, SPP теперь работает:) /Per

Ответ 4

Я разрабатывал приложение, которое связано с устройством BT. Ваш код отлично работает в моем HTC Wildfire, но с Samsung Galaxy I5700 doen't не работает. Оба os имеют обновление 2.1, но.....

Исключением было "InvocationTargetException"

Единственное, что мне пришлось изменить, это отключить().

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

Ответ 5

Эй, поэтому я использовал приложение Bluetooth Chat с сайта Android Development, и они предоставляют метод stop() в классе BluetoothChatService. Поэтому я просто создал экземпляр этого в моем основном классе и вызвал функцию остановки из моей кнопки разъединения.

Вот как я называю это в своем основном классе

//Объект-член для служб чата

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

Метод stop() в 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;
    }
}

Ответ 6

У меня такая же проблема. Это проблема с модулем Bluetooth CSR BC417, который присутствует во многих устройствах как последовательный адаптер Bluetooth с профилем SPP. С другим устройством Android-устройства Bluetooth работает хорошо, и bluetooth освобождает коннектор после закрытия гнезда, но с устройствами с этим ядром CSR нет. Протестировано на SPP Bluetooth на последовательный адаптер на базе CSR BC417 и модуль Bluetooth от Actisys. Оба устройства Android 4.0. Я не знаю, почему, но проблема совместимости между harwares, попробуйте изменить последовательный адаптер для другого с другим Core. Я пытаюсь программно найти решение, даже отключив bluetooth, но это невозможно, проблема возникла из модуля CSR.