2015-09-15 49 views
0

有人可以幫我找出爲什麼我只能通過BluetoothServerSocket.accept()打開的藍牙套接字獲得一個空文件描述符?爲什麼我的文件描述符到藍牙套接字爲空?

我的目標是通過藍牙在兩臺設備之間流式傳輸視頻,方法是將視頻寫入文件描述符並從另一端的文件描述符中讀取。我的藍牙連接很好,我可以來回發送原始數據,但我只能在客戶端獲得文件描述符。在服務器端,使用相同的代碼,我只能得到一個空文件描述符。在調試器中,我可以在服務器端看到一個文件描述符,位於mySocket.mSocketIS.this $ 0.fd,但我無法弄清楚如何訪問它。誰能幫忙?這是Android 4.4.2,這裏是我的代碼:

首先斷碼(服務器端):

// Listen for an incoming Bluetooth connection 
class AcceptThread extends Thread 
{ 
    // Thread that accepts incoming bluetooth connections 
    public AcceptThread() 
    { 
     try 
     { 
      // Open a listening server socket. This is non-blocking 
      btServerSocket = BA.listenUsingRfcommWithServiceRecord("ServerApp", videoUUID); 
     } catch(IOException e){ btServerSocket = null; } 
    } // AcceptThread() 

    public void run() 
    { 
     BluetoothSocket btSocket = null; 

     // Listen until exception or we have a socket 
     while(true) 
     { 
      try 
      { 
       // Blocking call to accept an incoming connection. To get out of this, call cancel() which closes the socket, causing .accept() to throw an exception 
       btSocket = btServerSocket.accept(); 
       // If we get here, we're connected! 

       Field pfdField = btSocket.getClass().getDeclaredField("mPfd"); 
       pfdField.setAccessible(true); 
       ParcelFileDescriptor pfd = (ParcelFileDescriptor) pfdField.get(btSocket); 

       // >>> ERROR - pfd is null <<<< I can see a fd at mySocket.mSocketIS.this$0.fd;, but how do I access it? 


       FileDescriptor myFd = pfd.getFileDescriptor(); 


       // ... blah blah... 

現在運行的代碼(客戶端):

// Connect to a remote device as the client (we are the client) 
class ConnectThread extends Thread 
{ 
    // ctor 
    // remoteUUID - The UUID of the remote device that we want to connect to 
    public ConnectThread(BluetoothDevice btDevice, UUID remoteUUID) 
    { 
     // Get a BT socket to connect with the given BluetoothDevice 
     try 
     { 
      // MY_UUID is the app's UUID string, also used by the server code 
      btClientSocket = btDevice.createRfcommSocketToServiceRecord(remoteUUID); 
     }catch(Exception e){ postUIMessage("ConnectThread exception: " + e.toString()); } 
    } // ConnectThread ctor 

    public void run() 
    { 
     // Cancel discovery because it will slow down the connection 
     BA.cancelDiscovery(); 
     try 
     { 
      // Connect the device through the socket. This will block until it succeeds or throws an exception. To get out, call cancel() below, which will cause .connect() to throw an exception. 
      btClientSocket.connect(); 

      Field pfdField = btClientSocket.getClass().getDeclaredField("mPfd"); 
      pfdField.setAccessible(true); 
      ParcelFileDescriptor pfd = (ParcelFileDescriptor) pfdField.get(btClientSocket); 
      FileDescriptor myFd = pfd.getFileDescriptor(); // Pass this to Recorder.setOutputFile(); 

      // Yay myFd is good! 

回答

0

我找到了就這個問題修復我的問題,我們也使用藍牙作爲服務器。我從BluetoothSocket的LocalSocket字段中找到文件描述符。我的目標是獲得文件並關閉它。

int mfd = 0; 
     Field socketField = null; 
     LocalSocket mSocket = null; 

     try 
     { 
      socketField = btSocket.getClass().getDeclaredField("mSocket"); 
      socketField.setAccessible(true); 

      mSocket = (LocalSocket)socketField.get(btSocket); 
     } 
     catch(Exception e) 
     { 
      Log ("Exception getting mSocket in cleanCloseFix(): " + e.toString()); 
     } 

     if(mSocket != null) 
     { 
      FileDescriptor fileDescriptor = 
        mSocket.getFileDescriptor(); 

      String in = fileDescriptor.toString(); 

      //regular expression to get filedescriptor index id 
      Pattern p = Pattern.compile("\\[(.*?)\\]"); 
      Matcher m = p.matcher(in); 

      while(m.find()) { 
       Log ("File Descriptor " + m.group(1)); 
       mfd = Integer.parseInt(m.group(1)); 
       break; 
      } 

      //Shutdown the socket properly 
      mSocket.shutdownInput(); 
      mSocket.shutdownOutput(); 
      mSocket.close(); 

      mSocket = null; 

      try { socketField.set(btSocket, mSocket); } 
      catch(Exception e) 
      { 
       Log ("Exception setting mSocket = null in cleanCloseFix(): " + e.toString()); 
      } 

      //Close the file descriptor when we have it from the Local Socket 
      try { 
       ParcelFileDescriptor parcelFileDescriptor = ParcelFileDescriptor.adoptFd(mfd); 
       if (parcelFileDescriptor != null) { 
        parcelFileDescriptor.close(); 
        Log ("File descriptor close succeed : FD = " + mfd); 
       } 
      } catch (Exception ex) { 
       Log ("File descriptor close exception " + ex.getMessage()); 
      } 
     } 
+0

感謝您的信息!當我重新開始項目時,我會嘗試這個。 – Matt

相關問題