2012-04-17 87 views
0

對於我今年夏天的機器人考試,我正在構建一個機器人,我想通過藍牙與Android設備進行通信。爲此,我正在編寫自己的Android應用程序。我沒有問題發送數據,但我不能收到數據。我對接收數據的代碼,不工作,看起來是這樣的:在我的Android應用程序中通過藍牙接收數據的問題

new Thread(new Runnable() { 
     public void run(){ 
      byte[] buffer = new byte[1024]; //Buffer for the incoming message 
      int bytes; 
      TextView afstandsTekst = (TextView)findViewById(R.id.afstandsText); 
      //Listen to the InputStream 
      while(true){ 
       try { 
        if(mmInStream.available() != 0) 
        try { 
         bytes = mmInStream.read(buffer); //Read from the InputStream. This is where the app crashes. 
        } 
        catch(IOException e){ 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } catch (IOException e) { 
        // TODO Auto-generated catch block 
        break; 
       } 
       afstandsTekst.setText(String.valueOf(bytes)); 
      } 
     } 
    }).start(); 

應用崩潰的

bytes = mmInStream.read(buffer); 

,我不明白爲什麼。我已經使用Android Developers上的藍牙頁面尋求幫助(http://developer.android.com/guide/topics/wireless/bluetooth.html#ManagingAConnection),並試圖像一樣和他們一樣,但是仍然崩潰,這就是爲什麼我現在嘗試了我上面粘貼的代碼。 另外,即使應用程序在正常運行時崩潰,當我選擇在Samsung Galaxy Nexus中的Eclipse中進行調試時,應用程序也不會崩潰,我不知道爲什麼。

這是我第一篇帖子到這個論壇,我非常希望有人在那裏會有答案。提前致謝!

編輯:下面是完整的代碼:

package skole.migogjesper.hospitalsseng; 

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

    import android.app.Activity; 
    import android.bluetooth.BluetoothAdapter; 
    import android.bluetooth.BluetoothDevice; 
    import android.bluetooth.BluetoothSocket; 
    import android.bluetooth.BluetoothClass.Device; 
    import android.content.BroadcastReceiver; 
    import android.content.Context; 
    import android.content.Intent; 
    import android.content.IntentFilter; 
    import android.os.Bundle; 
    import android.view.View; 
    import android.widget.AdapterView; 
    import android.widget.AdapterView.OnItemClickListener; 
    import android.widget.ArrayAdapter; 
    import android.widget.CheckBox; 
    import android.widget.ListView; 
    import android.widget.TextView; 
    import android.widget.Toast; 

    public class HospitalssengActivity extends Activity { 
    private String address = "00:06:66:45:B8:DB"; 
     private static final int REQUEST_ENABLE_BT = 3; 
     protected static final String EXTRA_DEVICE_ADDRESS = null; 
     IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); 
     public ArrayAdapter<String> mArrayAdapter; 
     BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();     //Indlæser bluetooth modulet i enheden. 
     private BluetoothDevice mmDevice = mBluetoothAdapter.getRemoteDevice(address); 
     private OutputStream mmOutStream; 
     private InputStream mmInStream; 
     private char stueDestination = '0'; 
     private char scannerDestination = '1'; 
     private char operationsstueDestination = '2'; 
     private char krematorieDestination = '3'; 
     private char xrayDestination = '4'; 
     private char planlagtStueDestination = 'q'; 
     private char planlagtScannerDestination = 'w'; 
     private char planlagtOperationsstueDestination = 'e'; 
     private char planlagtKrematorieDestination = 'r'; 
     private char planlagtXrayDestination = 't'; 
     private byte sendByte; 


/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 
    if(mBluetoothAdapter == null){ //Tjekker om bluetooth er underst¯ttet. 
     Toast.makeText(HospitalssengActivity.this, "Enheden understøtter ikke bluetooth", Toast.LENGTH_LONG).show(); 
    } 
    if(!mBluetoothAdapter.isEnabled()){ //Tjekker om bluetooth er tÊndt. 
     Intent enableBtIntent = new Intent (BluetoothAdapter.ACTION_REQUEST_ENABLE); 
     startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); 
    } 
    new Thread(new Runnable() { 
     public void run(){ 
      byte[] buffer = new byte[1024]; //Buffer til den indkommende besked 
      int bytes; //Bytes der kommer fra read() 
      TextView afstandsTekst = (TextView)findViewById(R.id.afstandsText); 
      //Lyt efter InputStream indtil der sker en exception 
      while(true){ 
       try { 
        if(mmInStream.available() != 0) 
        try { 
         bytes = mmInStream.read(buffer); //Læs fra InputStream 
        } 
        catch(IOException e){ 
         // TODO Auto-generated catch block 
         e.printStackTrace(); 
        } 
       } catch (IOException e) { 
        // TODO Auto-generated catch block 
        break; 
       } 
       //afstandsTekst.setText(String.valueOf(bytes)); 
      } 
     } 
    }).start(); 
} 

private BluetoothSocket mmSocket; 

public void Connect(BluetoothDevice device){ 
    BluetoothSocket tmp = null; //Dette er er et midlertidigt objekt, som senere bliver assigned til mmSocket. 
    mmDevice = device; 

    try { //Få en BluetoothSocket, som kan bruges til at forbinde med en BluetoothDevice 
     Method m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}); 
     tmp = (BluetoothSocket) m.invoke(device, 1); 
    } catch(Exception e) { 
     Toast.makeText(HospitalssengActivity.this, "FEJL!", Toast.LENGTH_LONG).show(); 
    } 
    mmSocket = tmp; 
    try{ //Forbind enheden gennem socket'en. Dette blokerer indtil den er succesfuld eller den fejler. 
     mmSocket.connect(); 
    } catch (IOException connectException) { 
     try{mmSocket.close();} //Fejlet forbindelse. Luk socket'en og hop ud af metoden. 
     catch(IOException closeException) {} 
     return; 
    } 
} 

public void cancel(){ //Lukker en forbindelse og lukker socket'en. 
    try{mmSocket.close();} 
    catch(IOException e) {} 
} 

public void write(byte sendByte){ 
    try { 
     mmOutStream = mmSocket.getOutputStream(); 
     mmOutStream.write(sendByte); 
     Toast.makeText(HospitalssengActivity.this, "Sendt", Toast.LENGTH_SHORT).show(); 
    } 
    catch (IOException e) {} 
} 

public void scanKnap(View view){ 
    Connect(mmDevice); 
} 

public void afbrydKnap(View view){ 
    cancel(); 
} 

public void stueKnap(View view){ 
    CheckBox planlagtCheck = (CheckBox) findViewById(R.id.planlagtCheck); 
    if(!planlagtCheck.isChecked()){ 
     sendByte = (byte) stueDestination; 
     write(sendByte); 
    } 
    if(planlagtCheck.isChecked()){ 
     sendByte = (byte) planlagtStueDestination; 
     write(sendByte); 
    } 
} 

public void scannerKnap(View view){ 
    CheckBox planlagtCheck = (CheckBox) findViewById(R.id.planlagtCheck); 
    if(!planlagtCheck.isChecked()){ 
     sendByte = (byte) scannerDestination; 
    write(sendByte); 
    } 
    if(planlagtCheck.isChecked()){ 
     sendByte = (byte) planlagtScannerDestination; 
     write(sendByte); 
    } 
} 

public void operationsstueKnap(View view){ 
    CheckBox planlagtCheck = (CheckBox) findViewById(R.id.planlagtCheck); 
    if(!planlagtCheck.isChecked()){ 
     sendByte = (byte) operationsstueDestination; 
     write(sendByte); 
    } 
    if(planlagtCheck.isChecked()){ 
     sendByte = (byte) planlagtOperationsstueDestination; 
     write(sendByte); 
    } 
} 

public void krematorieKnap(View view){ 
    CheckBox planlagtCheck = (CheckBox) findViewById(R.id.planlagtCheck); 
    if(!planlagtCheck.isChecked()){ 
     sendByte = (byte) krematorieDestination; 
     write(sendByte); 
    } 
    if(planlagtCheck.isChecked()){ 
     sendByte = (byte) planlagtKrematorieDestination; 
     write(sendByte); 
    } 
} 

public void xrayKnap(View view){ 
    CheckBox planlagtCheck = (CheckBox) findViewById(R.id.planlagtCheck); 
    if(!planlagtCheck.isChecked()){ 
     sendByte = (byte) xrayDestination; 
     write(sendByte); 
    } 
    if(planlagtCheck.isChecked()){ 
     sendByte = (byte) planlagtXrayDestination; 
     write(sendByte); 
    } 
} 

}

+0

發佈例外 – Ran 2012-04-17 13:42:37

+0

嗨@Ran感謝您的回覆!Eclipse中LogCat窗口的輸出如下,在崩潰後: 04-17 16:29:20.559:W/dalvikvm(13854):threadid = 11:線程退出與未捕獲的異常(組= 0x40a341f8) 04 - 17 16:29:20.559:E/AndroidRuntime(13854):致命例外:線程 - 1635年 04 - 17日16:29:20。559:E/AndroidRuntime(13854):java.lang.NullPointerException 04-17 16:29:20.559:E/AndroidRuntime(13854):\t at skole.migogjesper.hospitalsseng.HospitalssengActivity $ 1.run(HospitalssengActivity.java:71) 04-17 16:29:20.559:E/AndroidRuntime(13854):\t at java.lang.Thread.run(Thread.java:856) – WuPtI 2012-04-17 14:32:04

回答

0

如果在調試器中運行,而不是通常這聽起來像一個競爭條件。似乎在多個線程中可用的唯一變量是mmInStream。你在這個線程之外對mmInStream做什麼?

競態條件是兩個線程都可以訪問共享可變狀態(在本例中爲mmInStream)。有時候一個線程獲勝,你會看到一個結果,另一個線程獲勝並且你看到另一個結果。這些東西可能很難調試。

你可以在你創建線程的地方發佈代碼嗎?

看着你發佈的代碼,我看不到mmInstream在哪裏初始化。這會導致一個空指針異常像你報告的,但它也會發生在調試器(除非該線程從未運行)。

+0

究竟是一種競爭條件@JonStrayer?我對編程相當陌生,並且希望學習:-)實際上,除了創建它之外,我沒有在這個線程之外對mmInStream做任何事情:private InputStream mmInStream; – WuPtI 2012-04-17 15:02:45

+0

好的,我會嘗試發佈整個代碼@JonStrayer。 – WuPtI 2012-04-19 07:00:28

0

你不應該使用線程。

使用服務的背景東西,和線程使用ASyncTask而不是線程!

作爲提示:您可以在本地服務和活動之間在本地廣播! (你要導入Android的支持庫爲(見LocalBroadcast)。

的Android已經意味着OS上的另一個OS(Linux)的頂部。你並不需要處理線程通信自己,讓Android爲採取照顧!

+0

正如我在之前的一個評論中所說的,我不是一個非常有經驗的程序員,也不是一個Android(這是我的第一個「真正的」Android應用程序),所以我基本上只是配合Google的文檔和一些我以前的經歷。我會如何創建一些能夠不斷用您建議的@Radu方法監聽傳入的藍牙通信? – WuPtI 2012-04-19 15:55:54

+0

很難解釋所有這些,但你需要有一個服務(它始終在後臺運行 - 你可以開始閱讀)。然後,在該服務中,監視藍牙連接的狀態。如果斷開連接,請啓動偵聽連接的ASyncTask以及嘗試建立新連接的A​​SyncTask。如果連接,啓動ASyncTask讀取傳入數據並寫入傳出數據。所有這些之間的溝通可以通過很多方式完成。我用LocalBroadcast來做。再次,閱讀所有這些類的Android文檔。 – Radu 2012-04-20 13:24:59

+0

嗯好吧,我可能會試着去研究它,但它聽起來像是需要對應用程序進行幾乎完全的重寫,而我很遺憾沒有時間。不過,謝謝你的回答@Radu! – WuPtI 2012-04-20 16:05:41

相關問題