在我的Android应用程序中通过蓝牙接收数据的问题

时间:2012-04-17 13:40:34

标签: java android bluetooth

对于今年夏天的机器人考试,我正在构建一个机器人,我希望通过蓝牙与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开发者处使用蓝牙页面寻求帮助(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);
    }
}

}

2 个答案:

答案 0 :(得分:0)

如果它在调试器中运行,通常听起来不像竞争条件。似乎在多个线程中可用的唯一变量是mmInStream。你在这个线程之外对mmInStream做了什么?

竞争条件是两个线程都可以访问共享可变状态(在本例中为mmInStream)。有时一个线程赢了,你看到一个结果,另一个线程获胜,你看到另一个结果。这些事情很难调试。

您可以在创建线程的位置发布代码吗?

查看您发布的代码,我看不到mmInstream的初始化位置。这会导致像你报告的空指针异常,但它也会在调试器中发生(除非该线程永远不会运行)。

答案 1 :(得分:0)

您不应该使用线程。

将Service用于后台内容,对于线程使用ASyncTask而不是Thread!

作为提示:您可以在服务和活动之间广播本地! (你必须为此导入android支持库(参见LocalBroadcast)。

Android已经意味着OS在另一个操作系统(Linux)之上。您不需要自己处理线程通信,让Android负责处理!