2010-07-07 4 views
3

Мне нужно подключить мой Android к устройству Bluetooth. Я использую образец BluetoothChat от Google.Как отключить соединение Bluetooth (HTC Desire)

У меня возникли проблемы с этим с помощью Google Nexus, поскольку Nexus установил соединение, но сразу отключился. Мне нужно дважды инициировать соединение в качестве обходного пути (см. ConnectionLost()).

Теперь он хорошо работает на Nexus One и на HTC Desire.

Моя проблема заключается в отключении при выходе приложения. Он отлично работает на Nexus, соединение закрыто, но не на HTC Desire. Я добавляю функцию закрытия входного/выходного потока в дополнение к закрытию сокета. Посмотрите на функцию «stop()».

package xxx.yyy.zzz; 

import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.lang.reflect.Method; 
import java.util.UUID; 

import activities.Act_Main; 

import android.bluetooth.BluetoothAdapter; 
import android.bluetooth.BluetoothDevice; 
import android.bluetooth.BluetoothSocket; 
import android.content.Context; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.util.Log; 

/** 
* This class does all the work for setting up and managing Bluetooth 
* connections with other devices. It has a thread that listens for 
* incoming connections, a thread for connecting with a device, and a 
* thread for performing data transmissions when connected. 
*/ 
public class BluetoothService { 
    // Debugging 
    private static final String TAG = "BluetoothService"; 
    private static final boolean D = true; 

    // Member fields 
    //private final BluetoothAdapter mAdapter; 
    private final Handler mHandler; 
    private ConnectThread mConnectThread; 
    private ConnectedThread mConnectedThread; 
    private int mState; 
    private String mBTAddress; 
    private boolean isStop = false; 

    // Constants that indicate the current connection state 
    public static final int STATE_NONE = 0;  // we're doing nothing 
    public static final int STATE_LISTEN = 1;  // now listening for incoming connections 
    public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection 
    public static final int STATE_CONNECTED = 3; // now connected to a remote device 

    /** 
    * Constructor. Prepares a new Act_Main session. 
    * @param context The UI Activity Context 
    * @param handler A Handler to send messages back to the UI Activity 
    */ 
    public BluetoothService(Context context, Handler handler) 
    { 
     //mAdapter = BluetoothAdapter.getDefaultAdapter(); 
     mState = STATE_NONE; 
     mHandler = handler; 
    } 

    /** 
    * Set the current state of the connection 
    * @param state An integer defining the current connection state 
    */ 
    private synchronized void setState(int state) 
    { 
     if (D) Log.d(TAG, "setState() " + mState + " -> " + state); 
     mState = state; 

     // Give the new state to the Handler so the UI Activity can update 
     mHandler.obtainMessage(Act_Main.MESSAGE_STATE_CHANGE, state, -1).sendToTarget(); 
    } 

    /** 
    * Return the current connection state. */ 
    public synchronized int getState() 
    { 
     return mState; 
    } 

    /** 
    * Start the ConnectThread to initiate a connection to a remote device. 
    * @param device The BluetoothDevice to connect 
    */ 
    public synchronized void connect(String BTAddress) 
    { 
     mBTAddress = BTAddress ; 

     // Get the BLuetoothDevice object 
     BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(BTAddress); 

     if (D) Log.d(TAG, "connect to: " + device); 

     // Cancel any thread attempting to make a connection 
     if (mState == STATE_CONNECTING) 
      if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} 

     // Cancel any thread currently running a connection 
     if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} 

     // Start the thread to connect with the given device 
     mConnectThread = new ConnectThread(device); 
     mConnectThread.start(); 
     setState(STATE_CONNECTING); 
     isStop = false ; 
    } 

    /** 
    * Start the ConnectedThread to begin managing a Bluetooth connection 
    * @param socket The BluetoothSocket on which the connection was made 
    * @param device The BluetoothDevice that has been connected 
    */ 
    public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) 
    { 
     if (D) Log.d(TAG, "connected"); 

     // Cancel the thread that completed the connection 
     if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;} 

     // Cancel any thread currently running a connection 
     if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;} 

     // Start the thread to manage the connection and perform transmissions 
     mConnectedThread = new ConnectedThread(socket); 
     mConnectedThread.start(); 

     // Send the name of the connected device back to the UI Activity 
     Message msg = mHandler.obtainMessage(Act_Main.MESSAGE_DEVICE_NAME); 
     Bundle bundle = new Bundle(); 
     bundle.putString(Act_Main.DEVICE_NAME, device.getName()); 
     msg.setData(bundle); 
     mHandler.sendMessage(msg); 

     setState(STATE_CONNECTED); 
    } 

    /** 
    * Stop all threads 
    */ 
    public synchronized void stop() 
    { 
     isStop = true ; 

     if (D) 
      Log.d(TAG, "stop"); 

     if(mConnectThread != null) 
     { 
      mConnectThread.cancel(); 
      Thread moribund = mConnectThread; 
      mConnectThread = null; 
      moribund.interrupt(); 
     } 

     if(mConnectedThread != null) 
     { 
      mConnectedThread.cancel(); 
      Thread moribund = mConnectedThread; 
      mConnectedThread = null; 
      moribund.interrupt(); 
     } 

     setState(STATE_NONE); 
    } 

    /** 
    * Write to the ConnectedThread in an unsynchronized manner 
    * @param out The bytes to write 
    * @see ConnectedThread#write(byte[]) 
    */ 
    public void write(byte[] out) 
    { 
     // Create temporary object 
     ConnectedThread r; 

     // Synchronize a copy of the ConnectedThread 
     synchronized (this) 
     { 
      Log.d(TAG, "BT_SEND_MESSAGE"); 

      if (mState != STATE_CONNECTED) 
       return; 

      r = mConnectedThread; 
     } 

     // Perform the write unsynchronized 
     r.write(out); 
    } 

    /** 
    * Indicate that the connection attempt failed and notify the UI Activity. 
    */ 
    private void connectionFailed() 
    { 
     try 
     { 
      synchronized (this) 
      { 
       this.wait(3000); 
      } 
      connect(mBTAddress); 
     } 
     catch(InterruptedException ex) 
     { 
      Log.e(TAG, "WAIT_EXCEPTION:"+ ex.getMessage()); 
     } 
    } 

    /** 
    * Indicate that the connection was lost and notify the UI Activity. 
    */ 
    private void connectionLost() 
    { 
     if (!isStop) 
      connect(mBTAddress); 
    } 

    /** 
    * This thread runs while attempting to make an outgoing connection 
    * with a device. It runs straight through; the connection either 
    * succeeds or fails. 
    */ 
    private class ConnectThread extends Thread 
    { 
     private final BluetoothSocket mmSocket; 
     private final BluetoothDevice mmDevice; 

     public ConnectThread(BluetoothDevice device) 
     { 
      mmDevice = device; 
      BluetoothSocket tmp = null; 

      // Get a BluetoothSocket for a connection with the 
      // given BluetoothDevice 
      try 
      { 
       tmp = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")); 
      } 
      catch (Exception e) 
      { 
       Log.e(TAG, "create() failed", e); 
      } 
      mmSocket = tmp; 
     } 

     public void run() 
     { 
      Log.i(TAG, "BEGIN mConnectThread"); 
      setName("ConnectThread"); 

      // Always cancel discovery because it will slow down a connection 
      //mAdapter.cancelDiscovery(); 

      // Make a connection to the BluetoothSocket 
      try 
      { 
       // This is a blocking call and will only return on a successful connection or an exception 
       mmSocket.connect(); 
      } 
      catch (IOException e) 
      { 
       connectionFailed(); 

       // Close the socket 
       try 
       { 
        mmSocket.close(); 
       } 
       catch (IOException e2) 
       { 
        Log.e(TAG, "unable to close() socket during connection failure", e2); 
       } 
       return; 
      } 

      // Reset the ConnectThread because we're done 
      synchronized (BluetoothService.this) 
      { 
       mConnectThread = null; 
      } 

      // Start the connected thread 
      connected(mmSocket, mmDevice); 
     } 

     public void cancel() 
     { 
      try 
      { 
       mmSocket.close(); 
      } 
      catch (IOException e) 
      { 
       Log.e(TAG, "close() of connect socket failed", e); 
      } 
     } 
    } 

    /** 
    * This thread runs during a connection with a remote device. 
    * It handles all incoming and outgoing transmissions. 
    */ 
    private class ConnectedThread extends Thread { 
     private BluetoothSocket mmSocket; 
     private InputStream mmInStream; 
     private OutputStream mmOutStream; 

     public ConnectedThread(BluetoothSocket socket) { 
      Log.d(TAG, "create ConnectedThread"); 
      mmSocket = socket; 
      InputStream tmpIn = null; 
      OutputStream tmpOut = null; 

      // Get the BluetoothSocket input and output streams 
      try { 
       tmpIn = socket.getInputStream(); 
       tmpOut = socket.getOutputStream(); 
      } catch (IOException e) { 
       Log.e(TAG, "temp sockets not created", e); 
      } 

      mmInStream = tmpIn; 
      mmOutStream = tmpOut; 
     } 

     public void run() 
     { 
      Log.i(TAG, "BEGIN mConnectedThread"); 
      byte[] buffer; 
      int bytes = 0; 

      // Keep listening to the InputStream while connected 
      while (true) 
      { 
       try 
       { 
        //Clear buffer 
        buffer = new byte[1024]; 

        // Read from the InputStream 
        bytes = mmInStream.read(buffer); 

        // Send the obtained bytes to the UI Activity 
        mHandler.obtainMessage(Act_Main.MESSAGE_READ, bytes, -1, buffer).sendToTarget(); 
       } 
       catch (IOException e) 
       { 
        //String bufferStr = new String(buffer, 0, buffer.length); 
        Log.e(TAG, "disconnected", e); 
        connectionLost(); 
        break; 
       } 
      } 
     } 

     /** 
     * Write to the connected OutStream. 
     * @param buffer The bytes to write 
     */ 
     public void write(byte[] buffer) 
     { 
      try 
      { 
       mmOutStream.write(buffer); 
      } 
      catch (IOException e) 
      { 
       Log.e(TAG, "Exception during write", e); 
      } 
     } 

     public void cancel() 
     { 
      if (mmOutStream != null) 
      { 
       try {mmOutStream.close();} catch (Exception e) { Log.e(TAG, "close() of outputstream failed", e); } 
       mmOutStream = null; 
      } 

      if (mmInStream != null) 
      { 
       try {mmInStream.close();} catch (Exception e) { Log.e(TAG, "close() of inputstream failed", e); } 
       mmInStream = null; 
      } 

      if (mmSocket != null) 
      { 
       try {mmSocket.close();} catch (Exception e) { Log.e(TAG, "close() of connect socket failed", e); } 
       mmSocket = null; 
      } 
     } 
    } 
} 

Заранее за вашу помощь.

JJ

+0

Человек этот пример я ненавижу от Google его все, что вы не должны делать при подключении читать Потоки. Использование while (true) - это то, что я ненавижу. Я всегда использую while (! Thread.interrupted()) – JPM

ответ

1

Быстрый комментарий о синхронизации в коде:

Оставьте synchronized ключевое слово в вашем методе connect(), но когда приходит время для подключения, обратитесь к connect() из потока, а не создавать поток из вашего connect() , В настоящее время ваш код отключает поток подключений от connect() и побеждает цель синхронизации. (Цель состоит в том, чтобы синхронизировать запросы с connect(), чтобы несколько потоков не перепутались, поскольку они одновременно пытаются использовать connect). Это может вызвать некоторые проблемы с подключением.

относительно HTC:

Я думаю, что вы и я столкнулся с такой же вопрос: Why can't HTC Droid running OTA 2.1 communicate with RFCOMM?

Примечание об отключении соединения Bluetooth:

Убедитесь отключиться грациозно каждый раз используя ваш метод cancel().

+0

Спасибо за объяснение синхронизации. Исходный код предоставляется от Google ... Это удивительно. И ошибка Bluetooth на HTC тоже сумасшедшая ... Держите меня в курсе, если у вас есть новости о HTC. – Hrk

0

Я только что прочитал этот пост в настоящее время: Bluetooth on 2.0+

Кто-нибудь решение плохой реализации HTC Desire?

ОБНОВЛЕНИЕ: Например, я сделал очень плохое обходное решение. Я убиваю процесс, когда я выхожу из приложения:

ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); 
am.restartPackage("com.example.package"); 

Я все еще жду от чистого решения.

0

UPDATE: Похоже, HTC зафиксировал его через обновление Froyo (Android 2.2)

Смежные вопросы