2015-01-15 120 views
0

我试图让两个Android手机通过蓝牙连接。我遵循Android在线howto的说明,并且我非常密切关注。以编程方式安卓蓝牙重复连接

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

我可以得到蓝牙连接一次,但我必须重新启动Android设备或应用程序本身,为了得到它连接第二次。这在开发过程中不是问题,因为每次编辑代码时,android studio程序都会重新加载应用程序。它启动它并重新启动它,这样在测试期间我可以反复连接。在实际使用过程中,我必须重新启动android手机或转到设置下的应用程序管理器选项,并实际停止该应用程序。

从下面的代码,如果我把这些线我可以连接:

generateDefaultAdapter(); 
startDiscovery(); 
startThreadAccept(); 
startThreadConnect(); 

我如何得到它,这样的蓝牙连接可以一遍又一遍的启动?我看到来自内部类'ConnectThread'的消息'无法连接',以及来自该部分代码的'printStackTrace()'的IO错误。第二次尝试时,我似乎可以调用方法'stopConnection()',然后上面的行(以'generateDefaultAdapter()'开始),但我发现我无法连接。

package org.test; 

//some import statements here... 

public class Bluetooth { 

    public boolean mDebug = true; 
    public BluetoothAdapter mBluetoothAdapter; 

    public UUID mUUID = UUID.fromString(BLUETOOTH_UUID); 
    public Thread mAcceptThread; 
    public Thread mConnectThread; 

    public ConnectedThread mManageConnectionAccept; 
    public ConnectedThread mManageConnectionConnect; 


    public APDuellingBluetooth() { 

    } 


    public void generateDefaultAdapter() { 
     mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); 
     if (mBluetoothAdapter == null) { 
      // Device does not support Bluetooth 
     } 
     if (mBluetoothAdapter != null && !mBluetoothAdapter.isEnabled()) { 
      Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
      (mDialogDuel.getActivity()).startActivityForResult(enableBtIntent, INTENT_ACTIVITY_BLUETOOTH_REQUEST_ENABLE); 
     } 
    } 


    public void cancelDiscovery() { if (mBluetoothAdapter != null) mBluetoothAdapter.cancelDiscovery();} 
    public void startDiscovery() { mBluetoothAdapter.startDiscovery();} 
    public BluetoothAdapter getBluetoothAdapter() {return mBluetoothAdapter;} 


    public void stopConnection() { 

     try { 
      if (mAcceptThread != null) { 

       mAcceptThread.interrupt(); 
       //mAcceptThread.join(); 
       mAcceptThread = null; 
      } 

      if (mConnectThread != null) { 

       mConnectThread.interrupt(); 
       //mConnectThread.join(); 
       mConnectThread = null; 
      } 

      if (mManageConnectionConnect != null) { 
       mManageConnectionConnect.cancel(); 
       mManageConnectionConnect.interrupt(); 
       mManageConnectionConnect = null; 
      } 

      if (mManageConnectionAccept != null) { 
       mManageConnectionAccept.cancel(); 
       mManageConnectionAccept.interrupt(); 
       mManageConnectionAccept = null; 
      } 

     } 
     catch(Exception e) { 
      e.printStackTrace(); 
     } 


    } 



    public void startThreadAccept() { 

     if (mAcceptThread != null && !mAcceptThread.isInterrupted()) { 
      if (mDebug) System.out.println("server already open"); 
      //return; 
      mAcceptThread.interrupt(); 
      mAcceptThread = new AcceptThread(); 

     } 
     else { 
      mAcceptThread = new AcceptThread(); 
     } 
     if (mAcceptThread.getState() == Thread.State.NEW){ 
       //mAcceptThread.getState() == Thread.State.RUNNABLE) { 
      mAcceptThread.start(); 
     } 
    } 



    public void startThreadConnect() { 

     BluetoothDevice mDevice = mBluetoothAdapter.getRemoteDevice(mChosen.getAddress()); 
     //if (mDebug) System.out.println(mDevice.getAddress() + " -- " + mChosen.getAddress()); 

     if (mConnectThread != null && !mConnectThread.isInterrupted()) { 
      if (mDebug) System.out.println("client already open"); 
      //return; 
      mConnectThread.interrupt(); 
      mConnectThread = new ConnectThread(mDevice); 
     } 
     else { 
      mConnectThread = new ConnectThread(mDevice); 
     } 


     if (mConnectThread.getState() == Thread.State.NEW){// || 
       //mConnectThread.getState() == Thread.State.RUNNABLE) { 
      mConnectThread.start(); 
     } 
    } 



    public void manageConnectedSocketAccept(BluetoothSocket socket) { 


     String mTemp = mBluetoothAdapter.getName(); 
     if (mDebug) { 
      System.out.println("socket accept from " + mTemp); 
      System.out.println("info accept " + socket.getRemoteDevice().toString()); 
     } 
     if (mManageConnectionAccept != null && !mManageConnectionAccept.isInterrupted()) { 
      //mManageConnectionAccept.cancel(); 
      //mManageConnectionAccept.interrupt(); 
      if (mAcceptThread == null) System.out.println(" bad thread accept"); 
     } 
     else { 
      mManageConnectionAccept = new ConnectedThread(socket, "accept"); 
     } 

     if (mManageConnectionAccept.getState() == Thread.State.NEW){//|| 
       //mManageConnectionAccept.getState() == Thread.State.RUNNABLE) { 
      mManageConnectionAccept.start(); 
     } 

    } 

    public void manageConnectedSocketConnect(BluetoothSocket socket) { 


     String mTemp = mBluetoothAdapter.getName(); 
     if (mDebug) { 
      System.out.println("socket connect from " + mTemp); 
      System.out.println("info connect " + socket.getRemoteDevice().toString()); 

     } 

     if (mManageConnectionConnect != null && !mManageConnectionConnect.isInterrupted()) { 
      //mManageConnectionConnect.cancel(); 
      //mManageConnectionConnect.interrupt(); 
      if (mConnectThread == null) System.out.print(" bad thread connect "); 
     } 
     else { 
      mManageConnectionConnect = new ConnectedThread(socket, "connect"); 
     } 
     if (mManageConnectionConnect.getState() == Thread.State.NEW){// || 
       //mManageConnectionConnect.getState() == Thread.State.RUNNABLE) { 
      mManageConnectionConnect.start(); 
     } 
    } 




    public void decodeInput (String mIn, ConnectedThread mSource) { 
     // do something with info that is returned to me... 

    } 

    public void encodeOutput (String mMac1, String mMac2, int mLR1, int mLR2) { 


     String mTemp = composeOutputString (mServer, mMac1,mMac2, mLR1, mLR2); 


     if (mManageConnectionConnect != null && mManageConnectionConnect.isConnected()) { 
      mManageConnectionConnect.write(mTemp.getBytes()); 
      mManageConnectionConnect.flush(); 

     } 
     if (mManageConnectionAccept != null && mManageConnectionAccept.isConnected()) { 
      mManageConnectionAccept.write(mTemp.getBytes()); 
      mManageConnectionAccept.flush(); 
     } 

     mTemp = composeOutputString (mClient, mMac1,mMac2, mLR1, mLR2); 


     if (mManageConnectionConnect != null && mManageConnectionConnect.isConnected()) { 
      mManageConnectionConnect.write(mTemp.getBytes()); 
      mManageConnectionConnect.flush(); 
     } 
     if (mManageConnectionAccept != null && mManageConnectionAccept.isConnected()) { 
      mManageConnectionAccept.write(mTemp.getBytes()); 
      mManageConnectionAccept.flush(); 
     } 
    } 

    public String composeOutputString (SocketConnectData mData, String mMac1, String mMac2, int mLR1, int mLR2) { 

     // make a string here with the data I want to send... 
     String mTemp = new String(); 
     return mTemp; 
    } 



    ///////////////////////////////////////////// 
    private class AcceptThread extends Thread { 
     private final BluetoothServerSocket mmServerSocket; 
     private boolean mLoop = true; 

     public AcceptThread() { 


      // Use a temporary object that is later assigned to mmServerSocket, 
      // because mmServerSocket is final 
      mLoop = true; 

      BluetoothServerSocket tmp = null; 
      try { 
       // MY_UUID is the app's UUID string, also used by the client code 
       tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(mServiceNameReceive, mUUID); 
      } catch (IOException e) { 
       System.out.println("rfcomm problem "); 
      } 
      mmServerSocket = tmp; 
     } 

     public void run() { 
      BluetoothSocket socket = null; 
      // Keep listening until exception occurs or a socket is returned 
      while (mLoop) { 
       try { 
        if (mmServerSocket != null) { 
         socket = mmServerSocket.accept(); 
        } 
       } catch (IOException e) { 
        if (mDebug) System.out.println("rfcomm accept problem"); 
        e.printStackTrace(); 
        break; 
       } 
       // If a connection was accepted 
       if (socket != null && ! isConnectionOpen()) { 
        // Do work to manage the connection (in a separate thread) 
        manageConnectedSocketAccept(socket); 
        try { 
         mmServerSocket.close(); 

        } 
        catch (IOException e) {} 
        break; 
       } 
      } 
     } 

     /** Will cancel the listening socket, and cause the thread to finish */ 
     public void cancel() { 
      try { 
       mLoop = false; 
       mmServerSocket.close(); 
      } catch (IOException e) { } 
     } 
    } 
    ///////////////////////////////////////////// 

    private class ConnectThread extends Thread { 
     //private final BluetoothSocket mmSocket; 
     private BluetoothSocket mmSocket; 
     private final BluetoothDevice mmDevice; 

     public ConnectThread(BluetoothDevice device) { 


      // Use a temporary object that is later assigned to mmSocket, 
      // because mmSocket is final 
      BluetoothSocket tmp = null; 
      mmDevice = device; 

      try { 

       tmp = device.createRfcommSocketToServiceRecord(mUUID); 


       if (mDebug) System.out.println("connect -- rf socket to service record " + tmp); 

      } catch (Exception e) { 
       System.out.println("exception -- rf socket to service record problem " + tmp); 

      } 
      mmSocket = tmp; 
     } 

     public void run() { 
      // Cancel discovery because it will slow down the connection 
       mBluetoothAdapter.cancelDiscovery(); 


      try { 
       // Connect the device through the socket. This will block 
       // until it succeeds or throws an exception 

       mmSocket.connect(); 

      } 
      //catch (InterruptedException e) {System.out.println("interrupted exception");} 

      catch (IOException e) { 
       // Unable to connect; close the socket and get out 
       if (mDebug) System.out.println("unable to connect "); 

       e.printStackTrace(); // <---- I see output from this spot!! 



       try { 
        mmSocket.close(); 
       } catch (IOException closeException) { 
        System.out.println("unable to close connection "); 
       } 

       return; 
      } 


      // Do work to manage the connection (in a separate thread) 
      if (mmSocket.isConnected() && ! isConnectionOpen()) { 
       manageConnectedSocketConnect(mmSocket); 
      } 
     } 

     /** Will cancel an in-progress connection, and close the socket */ 
     public void cancel() { 
      try { 
       mmSocket.close(); 
      } catch (IOException e) { } 
     } 

     public boolean isConnected() { 
      return mmSocket.isConnected(); 
     } 
    } 

    ///////////////////////////////////////////// 
    private class ConnectedThread extends Thread { 
     private final BluetoothSocket mmSocket; 
     private final InputStream mmInStream; 
     private final OutputStream mmOutStream; 
     public String mTypeName = ""; 

     private boolean mLoop = true; 

     public StringWriter writer; 

     public ConnectedThread(BluetoothSocket socket, String type) { 
      mTypeName = type; 
      mLoop = true; 

      mmSocket = socket; 
      InputStream tmpIn = null; 
      OutputStream tmpOut = null; 

      // Get the input and output streams, using temp objects because 
      // member streams are final 
      try { 
       tmpIn = socket.getInputStream(); 
       tmpOut = socket.getOutputStream(); 
      } catch (IOException e) { } 

      mmInStream = tmpIn; 
      mmOutStream = tmpOut; 

      try { 


       writer = new StringWriter(); 
      } 
      catch (Exception e) {} 

     } 

     public void run() { 
      byte[] buffer = new byte[1024]; // 

      int bytes; // bytes returned from read() 
      String [] mLines ; 



      // Keep listening to the InputStream until an exception occurs 
      while (mLoop) { 
       try { 
        // Read from the InputStream 
        bytes = mmInStream.read(buffer); 

        if (bytes == -1 || bytes == 0) { 
         if (mDebug) System.out.println("zero read"); 
         return; 
        } 

        writer.append(new String(buffer, 0, bytes)); 

        mLines = writer.toString().split("!"); 

        if (mDebug) System.out.println("lines " +mLines.length); 

        for (int i = 0; i < mLines.length; i ++) { 


         if (true) { 
          if (mDebug) System.out.println(" " + mLines[i]); 
          decodeInput (mLines[i], this); 


         } 

        } 


       } catch (Exception e) { 
        e.printStackTrace(); 
        if (mDebug) System.out.println("read buffer problem"); 
        break; 
       } 
      } 
     } 

     /* Call this from the main activity to send data to the remote device */ 
     public void write(byte[] bytes) { 
      try { 

       mmOutStream.write(bytes); 


      } catch (IOException e) { 
       e.printStackTrace(); 
       if (mDebug) System.out.println("bad write"); 
      } 
     } 

     /* Call this from the main activity to shutdown the connection */ 
     public void cancel() { 
      try { 
       mLoop = false; 
       mmSocket.close(); 
       mmOutStream.close(); 
       mmInStream.close(); 
      } catch (IOException e) { } 
     } 

     public boolean isConnected() { 
      boolean mIsOpen = false; 
      try { 
       mIsOpen = mmSocket.isConnected() ; 
      } catch (Exception e) {} 
      return mIsOpen; 
     } 

     public void flush() { 
      try { 
       mmOutStream.flush(); 
      } 
      catch (IOException e) {e.printStackTrace();} 
     } 
    } 

    /////////////////////////////////////////////// 
} 

谢谢你的时间。

编辑:这是错误消息:

W/System.err﹕ java.io.IOException: read failed, socket might closed or timeout, read ret: -1 
W/System.err﹕ at android.bluetooth.BluetoothSocket.readAll(BluetoothSocket.java:553) 
W/System.err﹕ at android.bluetooth.BluetoothSocket.waitSocketSignal(BluetoothSocket.java:530) 
W/System.err﹕ at android.bluetooth.BluetoothSocket.connect(BluetoothSocket.java:357) 
W/System.err﹕ at org.davidliebman.test.Bluetooth$ConnectThread.run(Bluetooth.java:761) 

回答

0

试试这个: 而不是重新启动应用程序。关闭Android设备上的蓝牙,并在延迟5秒后重新打开。如果您可以成功连接,通常表示您没有完全关闭连接和套接字。记录你的代码。确保关闭套接字例程顺利执行。检查你在你的ConnectedThreadcancel方法具有IOException不捕获任何异常:

/* Call this from the main activity to shutdown the connection */ 
    public void cancel() { 
     try { 
      // ADD LOG 
      mLoop = false; 
      mmSocket.close(); 
      mmOutStream.close(); 
      mmInStream.close(); 
      // ADD LOG 
     } catch (IOException e) { 
      // ADD LOG} 
    } 
+0

切换蓝牙技术并允许应用程序运行第二次。我正在尝试向'cancel()'方法添加日志语句。 –

+0

似乎从不调用cancel()方法。当我将日志语句添加到代码的那部分时,我从来没有看到它们。我不知道该怎么做。我甚至试图在我的UI中添加一个名为finish()的按钮。我的想法是,我可以使用名为'finish()'的按钮更轻松地手动重新启动整个应用程序。不幸的是它没有奏效。无论如何,应用程序必须从系统程序的应用程序管理器重新启动,即使在成功执行finish()后也是如此。 –

+0

我的建议是避免重新启动应用程序。你所需要做的就是正确回溯为什么不调用取消方法。我可以看到你有一个调用cancel方法的stopConnection()方法。然而,我不确定的是你的连接线程。也许尝试向mConnectThread添加cancel()方法,并在stopConnection()中添加mAcceptThread。 – Kasra