我正在爲Android設計一款遊戲,其中兩臺設備連接並交易少量數據,然後斷開並使用該數據。我從藍牙聊天的例子開始。在這一點上,我主要工作,但一些(大多數)時間,其中一個設備從未收到任何數據。這是兩個設備上的同一個應用程序,因此兩者的發送和接收代碼都是相同的。 我連這樣的:Android藍牙Inputstream.read永不接收數據
public BluetoothClientThread(BluetoothDevice get_device,boolean secure){
BluetoothSocket temp=null;
device=get_device;
socket_type=secure?"Secure":"Insecure";
try{
if(secure){
temp=device.createRfcommSocketToServiceRecord(UUID_SECURE);
}
else{
temp=device.createRfcommSocketToServiceRecord(UUID_INSECURE);
}
}
catch(IOException e){
StorageManager.error_log_add(context,TAG,"create() on "+socket_type+" client socket failed.",e);
}
socket=temp;
}
public void run(){
bluetooth_adapter.cancelDiscovery();
try{
socket.connect();
}
catch(IOException e){
StorageManager.error_log_add(context,TAG,"Connection failed.",e);
try{
socket.close();
}
catch(IOException ioe){
StorageManager.error_log_add(context,TAG,"close() on "+socket_type+" client socket failed during connection failure.",ioe);
}
connection_failed();
return;
}
synchronized(BluetoothService.this){
bluetooth_client_thread=null;
}
connected(socket,device,socket_type,false);
}
連接後,我搶座的的getInputStream()和getOutputStream方法()。 我然後使用下面的代碼到插座上讀取輸入:
public void run(){
String packet="";
while(true){
try{
int get_byte=input.read();
char get_char=(char)get_byte;
if(get_char!='\u0003'){
StorageManager.error_log_add(context,"BluetoothService","Adding packet raw data: \""+get_char+"\"",null);
packet+=get_char;
}
else{
StorageManager.error_log_add(context,"BluetoothService","Packet received:\n"+packet,null);
handler.obtainMessage(Activity_Battle_Menu.HANDLER_READ,packet).sendToTarget();
packet="";
}
if(done && they_done){
handler.obtainMessage(Activity_Battle_Menu.HANDLER_READY).sendToTarget();
}
}
catch(IOException e){
StorageManager.error_log_add(context,TAG,"Connection lost.",e);
connection_lost();
break;
}
}
}
它一次讀取數據的一個字節,追加字節的數據包串。當到達ETX字符時(我把它發送到所有東西的末尾),已經收到一個完整的數據包,並通過處理程序傳遞給活動,在該處理程序中執行該活動。 這是我寫代碼:
public void write(byte[] buffer){
try{
StorageManager.error_log_add(context,"BluetoothService","Writing data:\n"+new String(buffer),null);
output.write(buffer);
}
catch(IOException e){
StorageManager.error_log_add(context,TAG,"write() on "+socket_type+" connected socket failed.",e);
}
}
正如你所看到的,我寫的,當數據「包」發送日誌,接收到一個字節時,當整個「包」已收到。
我不確定這是否有任何相關性,但: 我使用帶有Cyanogenmod 7.1(Android 2.3.7)和運行在VirtualBox(Android 2.3.5)中的Android x86的Nook Color進行測試。我的應用程序minSdkVersion是8(Android 2.2)。對於在我的電腦上運行的Android,我正在使用Rocketfish USB藍牙適配器。
應該有兩個數據包由每個實例發送。首先,發送保存所有所需遊戲數據的數據分組。 當收到其他實例的遊戲數據時,應用程序將自己的布爾值設置爲true。 它也發送一個「完成」數據包到另一個實例。 因此,一旦兩個實例都完成了,並且知道另一個完成了,我們知道所有的數據已經被髮送和接收,並且它們都斷開/停止它們的藍牙線程並且對數據執行操作。
由於我在發送和接收數據時在兩臺設備上登錄,日誌告訴我一個發生了什麼事情的故事。
- 首先,我開始兩款遊戲並進入藍牙活動(顯然)。
- 下一步,我連接到仿真實例的Nook實例。
- 模擬實例發送它的遊戲數據包。 - Nook實例接收模擬實例的遊戲數據,併發送它自己的(有時這兩個按順序切換,僅僅因爲它們是異步發生的)。
- 由於它收到一個遊戲數據包,Nook實例現在發送它的「完成」數據包。
- 就是這樣。仿真實例永遠不會收到任何數據包。它甚至從來沒有收到一個字節,並且input.read()只是阻塞,等待從未到達的輸入(就像它應該)。
這就是我的問題。看來,兩件事情正在發生:
的數據將無法得到output.write()上的Nook實例發送,即使它不拋出任何異常,並且日誌驗證它被調用。
數據永遠不會被仿真實例上的input.read()接收到。也許它在傳輸中丟失了?
據我所知,我的代碼是堅如磐石的。這個問題似乎與藍牙相關。也許一個或兩個Android實例有一個棘手的藍牙設置?
我還想補充一點,每隔一段時間(也許只有1/15次),所有數據包都會正確發送和接收,並且遊戲繼續進行。所以不管怎麼樣,只有USUALLY會發生,但並非總是如此。