2013-10-01 86 views
0

我看到很多有关蓝牙问题/蓝牙超时的问题,但没有人帮助我。Android中的蓝牙套接字超时。 HCI_STATUS = 36错误

我正在开发一个应用程序,用于向另一个蓝牙设备发送数据或从另一个蓝牙设备接收数据。我每秒发送约3次。我知道响应应该如何(像[FC ... FF]这样的字节数组)。

我正在构建基于BluetoothChat演示的应用程序,并且我主要更改了BluetoothChatService类中的代码。

我所做的是实现一个返回布尔值的新方法(我称之为boolean readWrite(byte [] data))。在这种方法中,我首先写入输出流,然后从输入流中读取数据。如果写入顺利,我将布尔值设置为true,如果读取正常,我将另一个布尔值设置为true,并将响应字节数组转换为String,并将此String设置为响应。如果写入/读取出错,我的方法将返回false;

在ConnectedThread的run()方法中,我有一个while(true)循环,我使用这个readWrite方法。然后我得到字符串响应,并根据响应我readWrite()另一个数据。

我会在这里发布一些代码,这样你就可以理解我实际做了什么。通过这种方式,我试图摆脱套接字超时,并在读写错误时重置连接。我得到如下所示的一些错误,但它可能是我的设备?

private class ConnectedThread extends Thread { 
    private final BluetoothSocket mmSocket; 
    private final InputStream mmInStream; 
    private final 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; 
    } 

    private boolean readWrite(byte[] data) { 
     byte[] read = null; 
     int bytes = 0; 
     String bc; 
     String packet; 
     boolean readPacket = false; 
     boolean writing = false 
     boolean reading = false; 

     try { 
      // Log.d(TAG, "write to the device"); 
      mmOutStream.write(data); 
      writing = true; 
     } catch (IOException e) { 
      Log.e(TAG, "Exception occurred during write: " + e.getMessage()); 
      setState(STATE_NONE); 
      writing = false; 
     } 
     // if writing goes ok 
     if(writing){ 
      read = new byte[64]; 
      // the response packet should be a byte array like [FC ... FF] 
      while(!readPacket) 
      try { 
       // Read from the InputStream 
       bytes = mmInStream.read(); 
       bc = String.format("%02x", (0xFF & bytes)).toUpperCase(); 
        if(bc.equalsIgnoreCase("fc")) 
        { 
         packet = ""; 
         packet += bc; 
        } 
        else if(bc.equalsIgnoreCase("ff")) 
        { 
         readPacket = true; 
         packet += bc; // finish the response packet 
         Log.d(TAG, "read packet -> to UI: " + packet); 
         reading = true; 
         read = null; 
         myBluetoothService.this.setReceivedMessage(packet); 
         packet = ""; 
        } 
        else{ 
         packet += bc; 
        } 
      } 
      catch (IOException e) { 
       reading = false; 
       connectionLost(); 
       break; 
      } 
     } 
     else return false; 
     return (reading&&writing); 
    } 

    public void run() { 
     setName("ConnectedThread");   
     byte[] buffer = new byte[64]; 
     String globalString = ""; 
     String requestCommand = "request";   
     buffer = requestCommand.getBytes(); 

     // Keep listening to the InputStream until an exception occurs 
     while (true) {    
      Log.d(TAG, "in the LOOP"); 
      if(readWrite(buffer)) 
      { 
       // get response from the remoteDevice 
       globalString = getReceivedMessage(); 
       String key = globalString.substring(18, 20); //substract the key pressed on the device 
       int keyNum = HexString2Int(key); // convert the string to int 
       switch (keyNum) { 
        case 1: 
         // code here 
         break; 
        case 2: 
         // code here 
         break; 
        default: 
         break; 
       } 
      }else { 
       try { 
        Log.d(TAG, "else JOIN - in the LOOP"); 
        resetConnection(); 
        Thread.currentThread().join(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      }    
      // pause between the loops 
      try {Thread.sleep(300);Log.d(TAG, "300 sleeping time");} catch (InterruptedException e) {e.printStackTrace();} 
     } // out of while loop 
     try { 
      resetConnection(); 
      Thread.currentThread().join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } // end run() 

    private void resetConnection() { 
     setState(STATE_NONE); 
     Log.d(TAG, "reset connection"); 
     if (mmInStream != null) { 
      try {mmInStream.close();} catch (Exception e) {Log.d(TAG,"exception in closing inputstream - " + e.getMessage());} 
     } 
     if (mmOutStream != null) { 
      try {mmOutStream.close();} catch (Exception e) {Log.d(TAG,"exception in closing outputstream - " + e.getMessage());} 
     } 
     if (mmSocket != null) { 
      try {mmSocket.close();} catch (Exception e) {Log.d(TAG,"exception in closing socket - " + e.getMessage());} 
     } 
    } 

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

所有这一切工作正常,但有时几分钟后(最长30分钟),我收到以下错误:

09-20 10:44:31.270: W/bt-btif(883): dm_pm_timer expires 
09-20 10:44:31.270: W/bt-btif(883): dm_pm_timer expires 0 
09-20 10:44:31.290: W/bt-btif(883): proc dm_pm_timer expires 
09-20 10:44:31.310: E/bt-btif(883): bta_dm_pm_btm_status hci_status=36 

有谁知道为什么出现这种情况的任何想法?这真的令人沮丧。我的设备是搭载Android 4.3的Nexus 7,内部编号为JWR66V。我用android 2.3.3在另一台设备上测试了这个应用程序。日志是不同的,但我想它是关于同样的错误。

请帮忙!

+0

有没有人发现为什么这是/是怎么回事?解决方法可能工作,但我想知道最新的 – NikkyD

回答

2

我有这个问题,我通过创建一个Keep Alive线程来解决它,每隔0.3秒在套接字上传输一个字节的数据。我相信这个问题是全新的Android 4.3,因为我没有更新之前遇到这个问题..

public class KeepAlive extends Thread{ 
private ConnectedThread connectedThread; 
private final String TAG = "KeepAlive"; 
private volatile boolean running = true; 

public KeepAlive(ConnectedThread connectedThread) { 
    this.connectedThread = connectedThread; 
    running = true; 
} 

public synchronized void run() { 
    Log.d(TAG,"KeepAlive Thread starting"); 
    while(running) { 

     try { 
      wait(300); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

     connectedThread.write('!'); 
    } 
    Log.d(TAG,"KeepAlive Thread closing"); 
} 

public void setRunning(boolean running) { 
    this.running = running; 
} 

}

+0

嘿,它看起来像连接更稳定。但你从哪里开始这个线程?哪里是最好的地方设置运行(真)并启动它? – bboydflo

+0

更新:我在公共同步无效连接(BluetoothSocket套接字)方法中的服务类中完成了它。感谢您的解决方案。据我测试它的作品!让我们看看连接将持续多久。 – bboydflo

+0

我接受了您的解决方案,至今连接似乎很可靠。我在KeepAlive线程中写入方法的日志告诉我,KeepAlive继续写入ConnectedThread,但我的主要ConnectedThread块在while(true)的某个位置。我似乎只能从KeepAlive线程写入输出流。我不知道为什么会发生。你有什么主意吗?我在这里发布了我的日志:http://pastebin.com/dUjmBRQd – bboydflo