【问题标题】:Application stopped unexpectedly: Fatal Exception应用程序意外停止:致命异常
【发布时间】:2014-01-08 14:08:57
【问题描述】:

谁能帮助我的应用程序代码。我尝试制作一个可以通过蓝牙向 arduino 发送数据(数字或字母)的应用程序。这就是我的 JAVA 代码的样子:

package com.example.btprojektas;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;

import android.content.Intent;

import android.os.Bundle;
import android.util.Log;
import android.view.View;

import android.widget.Button;
import android.widget.Toast;

import java.io.IOException;
import java.io.OutputStream;
import java.util.Set;
import java.util.UUID;

public class MainActivity extends Activity{

private static final String TAG = "btprojektas";

Button btnON, btnOFF;

BluetoothAdapter bluetoothAdapter = null;
BluetoothDevice device = null;
OutputStream outputStream = null;
BluetoothSocket socket = null;



@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

    btnON = (Button) findViewById(R.id.btnON);
    btnOFF = (Button) findViewById(R.id.btnOFF);

    if(!bluetoothAdapter.isEnabled()){
        Intent enableBluetooth = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBluetooth, 0);
    }

    loadPairedDevice();
    connectBT();

    btnON.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            sendData("0");
            Toast.makeText(getBaseContext(), "Turn on LED", Toast.LENGTH_SHORT).show();
        }
    });

    btnOFF.setOnClickListener(new View.OnClickListener() {
        public void onClick(View v) {
            sendData("1");
            Toast.makeText(getBaseContext(), "Turn off LED", Toast.LENGTH_SHORT).show();
        }
    });
}

private void connectBT() {
    if (device != null) {
        UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); //Standard SerialPortService ID
        try {
            socket = device.createRfcommSocketToServiceRecord(uuid);
            socket.connect();
            outputStream = socket.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


private void disconnect() {
    try {
        if (outputStream != null) outputStream.close();
        if (socket != null) socket.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

private void loadPairedDevice() {
    Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();

    if (pairedDevices.size() > 0) {
        Log.d(TAG, "Device found");

        for (BluetoothDevice device : pairedDevices)
            if (device.getName().equals("HC-06")) {
                this.device = device;
                break;
            }
    }
}

@Override
protected void onPause() {
    super.onPause();
    disconnect();
}

@Override
protected void onResume() {
    super.onResume();
    loadPairedDevice();
    connectBT();
}

private void sendData(String message) {
    byte[] buffer = message.getBytes();
    Log.d(TAG,"Send data:"+ message);
    try{
        outputStream.write (buffer);
    } catch (IOException e) {}

}

}

在 XML 中,我有两个按钮。当程序启动时,我按下其中一个按钮,“应用程序...意外停止”出现,并带有致命的异常错误代码:

01-08 15:55:15.439  15354-15354/com.example.btprojektas E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.NullPointerException
        at com.example.btprojektas.MainActivity.sendData(MainActivity.java:122)
        at com.example.btprojektas.MainActivity.access$000(MainActivity.java:22)
        at com.example.btprojektas.MainActivity$1.onClick(MainActivity.java:55)
        at android.view.View.performClick(View.java:2485)
        at android.view.View$PerformClick.run(View.java:9080)
        at android.os.Handler.handleCallback(Handler.java:587)
        at android.os.Handler.dispatchMessage(Handler.java:92)
        at android.os.Looper.loop(Looper.java:130)
        at android.app.ActivityThread.main(ActivityThread.java:3687)
        at java.lang.reflect.Method.invokeNative(Native Method)
        at java.lang.reflect.Method.invoke(Method.java:507)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
        at dalvik.system.NativeStart.main(Native Method)

附:抱歉这个问题我知道这很常见,但我是编程新手,尤其是 JAVA。

【问题讨论】:

  • 当您尝试访问它们时,outputStreammessage 为 null。通过将所有套接字调用包装在try {} catch(IOException ) 中,您可能会忽略一些重要错误。您至少应该在e.printStackTrace() 调用上放置一个断点。最好在这里实际做一些有用的事情,即通知用户连接失败
  • 检查device是否不是null
  • 并且不要用catch (IOException e) {}翻转异常

标签: java android bluetooth fault


【解决方案1】:

要么是套接字,要么是输出流。在 ConnectBT 中,您不检查套接字是否不为空。假设套接字有效,您直接调用 socket.connect() 。这同样适用于输出流。在确保它不为空之前使用它。

你也叫

startActivityForResult(enableBluetooth, 0);

但您不检查蓝牙是否启用的结果。这使您的设备也很可疑。

打电话

loadPairedDevice();
connectBT();

仅在启用蓝牙时才有意义。启用蓝牙可能需要几秒钟,但您会立即调用它们。

【讨论】:

    【解决方案2】:

    几个提示:

    • 您调用 loadPairedDevice() 和 connectBT() 两次:在 onCreate() 和 onResume() 中 - 只调用一次
    • 在使用 outputStream 之前,检查它是否不为空(根据其他人的建议)
    • 在 sendData() 中,捕获并打印您的异常:

      try {
          if (outputStream != null) {
              outputStream.write(buffer);
          }
          else {
              Log.d("TAG", "sendData() - outputStream is null!");
          }
      }
      catch (IOException e) {
          e.printStackTrace();
      }
      
    • 在loadPairedDevice()中,如果你没有找到设备“HC-06”,你的变量设备将为空...

    • 启用蓝牙需要几秒钟,所以注册并收听 ACTION_STATE_CHANGED 广播意图。它将包含额外的字段 EXTRA_STATE;寻找 STATE_ON,然后在那里调用你的 loadPairedDevices() 和 connectBT():

      • 创建接收器(在您的 MainActivity 类中):

        private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
            public void onReceive(Context context, Intent intent) {
                final String action = intent.getAction();
        
                //this is the action you are observing
                if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) {
                    final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);
                    switch(state) {
                        //and the state we were looking for
                        //which means that bluetooth has switched on
                        //so now you can call your functions
                        //and set the flag to true, which then use in your
                        //onClick listeners 
                        case BluetoothAdapter.STATE_ON:
                            loadPairedDevice();
                            connectBT();
                            isBluetoothOn = true;
                            break;
                    }
                }
            }
        }
        
      • 在onCreate()中,创建IntentFilter并注册receiver

        IntentFilter btFilter = new IntentFilter();
        btFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        
        registerReceiver(mReceiver, btFilter); 
        
      • 记得在 onPause() 中取消注册接收器:

        unregisterReceiver(mReceiver);
        
    • 当您知道 BT 已打开时,禁用您的按钮并在上述侦听器中启用它们;或者,保留一个标志并在您的点击侦听器中使用它,例如:

      boolean isBluetoothOn = false;
      

    然后当你得到 STATE_ON 时在监听器中

    isBluetooth = true;
    

    在你的按钮点击监听器:

    //for btnON
    public void onClick(View v) {
        if (isBluetoothOn) {
            sendData("0");
            Toast.makeText(getBaseContext(), "Turn on LED", Toast.LENGTH_SHORT).show();
        }
    }
    

    对 btnOFF 执行相同操作。

    【讨论】:

    • 感谢您的帮助,我检查了 outputStream 是否不为空,我发现它实际上是,现在我在按下按钮时没有出现“应用程序...意外停止”错误。运行应用程序时我仍然遇到“致命异常”,但我会尝试应用其他可能有用的提示。
    猜你喜欢
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    • 1970-01-01
    • 2013-06-14
    • 2013-08-29
    • 1970-01-01
    相关资源
    最近更新 更多