对于今年夏天的机器人考试,我正在构建一个机器人,我希望通过蓝牙与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);
}
}
}
答案 0 :(得分:0)
如果它在调试器中运行,通常听起来不像竞争条件。似乎在多个线程中可用的唯一变量是mmInStream。你在这个线程之外对mmInStream做了什么?
竞争条件是两个线程都可以访问共享可变状态(在本例中为mmInStream)。有时一个线程赢了,你看到一个结果,另一个线程获胜,你看到另一个结果。这些事情很难调试。
您可以在创建线程的位置发布代码吗?
查看您发布的代码,我看不到mmInstream的初始化位置。这会导致像你报告的空指针异常,但它也会在调试器中发生(除非该线程永远不会运行)。
答案 1 :(得分:0)
将Service用于后台内容,对于线程使用ASyncTask而不是Thread!
作为提示:您可以在服务和活动之间广播本地! (你必须为此导入android支持库(参见LocalBroadcast)。
Android已经意味着OS在另一个操作系统(Linux)之上。您不需要自己处理线程通信,让Android负责处理!