我的BluetoothCommandService中的NullPointerException(第2部分)

时间:2014-03-02 02:21:44

标签: java android bluetooth

我正在使用我的arduino uno和HC-05蓝牙模块创建家庭自动化Android应用程序。一切都很好。它可以扫描,连接,打开/关闭蓝牙,使用按钮和开关控制来打开和关闭灯泡。

我最大的问题是,当应用程序尚未连接到我的蓝牙模块时,如果单击开关控件,它会停止并自动结束应用程序。我一直在努力修复错误,但仍然没有发生任何事情。在此先感谢那些对此有所了解的人。

以下是LogCat中列出的内容:

03-02 00:02:48.807: E/AndroidRuntime(13767): FATAL EXCEPTION: main
03-02 00:02:48.807: E/AndroidRuntime(13767): java.lang.NullPointerException
03-02 00:02:48.807: E/AndroidRuntime(13767):    at com.example.javac101.BluetoothCommandService.write(BluetoothCommandService.java:222)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at com.example.javac101.ControllerTab.sendData(ControllerTab.java:390)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at com.example.javac101.ControllerTab.onCheckedChanged(ControllerTab.java:271)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at android.widget.CompoundButton.setChecked(CompoundButton.java:126)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at android.widget.Switch.setChecked(Switch.java:666)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at android.widget.CompoundButton.toggle(CompoundButton.java:87)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at android.widget.CompoundButton.performClick(CompoundButton.java:99)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at android.view.View$PerformClick.run(View.java:17476)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at android.os.Handler.handleCallback(Handler.java:800)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at android.os.Handler.dispatchMessage(Handler.java:100)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at android.os.Looper.loop(Looper.java:194)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at android.app.ActivityThread.main(ActivityThread.java:5371)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at java.lang.reflect.Method.invokeNative(Native Method)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at java.lang.reflect.Method.invoke(Method.java:525)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:833)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
03-02 00:02:48.807: E/AndroidRuntime(13767):    at dalvik.system.NativeStart.main(Native Method)

可能不太清楚,所以这里是我的BluetoothCommandService中的代码:

package com.example.javac101;

import java.util.UUID;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

public class BluetoothCommandService {

    private final BluetoothAdapter BTAdapter;
    private final Handler bluetoothHandler;
    private static int connectionState;
    private ConnectThread connectThread;
    //private ConnectedThread connectedThread;
    public static ConnectedThread connectedThread;
    private AcceptThread mainAcceptThread;

    public static final int stateNothing = 0; //doing nothing
    public static final int stateListen = 1; //listening for incoming connections
    public static final int stateConnecting = 2; //initiating an outgoing connection
    public static final int stateConnected = 3;

    //constants that indicate command to computer
    public static final int exitCMD = -1;
    public static final int VOL_UP = 1;
    public static final int VOL_DOWN = 2;

    private static final boolean D = true;
    private static final String tagState = "BluetoothCommandService";


     private static final UUID myUUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66");
    private static final String name = "BluetoothCommand";
    private static final String BluetoothCommandService = null;

    public BluetoothCommandService(Context context, Handler handler) { // context == UI Activity Context && handler == send message back to the UI Activity
        BTAdapter = BluetoothAdapter.getDefaultAdapter();
        connectionState = stateNothing;
        bluetoothHandler = handler;
    }

    private  synchronized void setState(int state) { // state == current connection state; an integer
        if (D) Log.d(tagState, "setState() " + connectionState + " -> " + state);
        connectionState = state;

        bluetoothHandler.obtainMessage(ControllerTab.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();       
    }

    public synchronized int getState() { //return the current connection state
        return connectionState;
    }

    public synchronized void start() {
        if (D) Log.d(tagState, "start");

        // Cancel any thread attempting to make a connection
        if (connectThread != null) 
        {
            connectThread.cancel();
            connectThread = null;
        }

        // Cancel any thread currently running a connection
        if (connectedThread != null)
        {
            connectedThread.cancel();
            connectedThread = null;
        }

        // Start the thread to listen on a BluetoothServerSocket
        if (mainAcceptThread == null) 
        {
            mainAcceptThread = new AcceptThread();
            mainAcceptThread.start();
        }

        setState(stateListen);
    }

    //device == the BluetoothDevice to connect
    public synchronized void connect(BluetoothDevice device) {
        if (D) Log.d(tagState, "connect to: " + device);

        // Cancel any thread attempting to make a connection
        if (connectionState == stateConnecting) {
            if (connectThread != null)
            {
                connectThread.cancel(); 
                connectThread = null;
            }
        }

        // Cancel any thread currently running a connection
        if (connectedThread != null) 
        {
            connectedThread.cancel(); 
            connectedThread = null;
        }

     // Cancel the accept thread because we only want to connect to one device
        if (mainAcceptThread != null) 
        {
            mainAcceptThread.cancel(); 
            mainAcceptThread = null;
        }

        // Start the thread to connect with the given device
        connectThread = new ConnectThread(device);
        connectThread.start();
        setState(stateConnecting);
    }

    public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
        if (D) Log.d(tagState, "connected");

        // Cancel the thread that completed the connection
        if (connectThread != null) 
        {
            connectThread.cancel(); 
            connectThread = null;
        }

        // Cancel any thread currently running a connection
        if (connectedThread != null) 
        {
            connectedThread.cancel(); 
            connectedThread = null;
        }

        if (mainAcceptThread != null) 
        {
            mainAcceptThread.cancel(); 
            mainAcceptThread = null;
        }

        // Start the thread to manage the connection and perform transmissions
        connectedThread = new ConnectedThread(socket);
        connectedThread.start();

        // Send the name of the connected device back to the UI Activity
        Message msg = bluetoothHandler.obtainMessage(ControllerTab.MESSAGE_DEVICE_NAME);
        Bundle bundle = new Bundle();
        bundle.putString(ControllerTab.DEVICENAME, device.getName());
        msg.setData(bundle);
        bluetoothHandler.sendMessage(msg);

        setState(stateConnected);
    }

    public synchronized void stop() {
        if (D) Log.d(tagState, "stop");

        if (connectThread != null) 
        {
            connectThread.cancel(); 
            connectThread = null;
        }

        if (connectedThread != null) 
        {
            connectedThread.cancel(); 
            connectedThread = null;
        }

        if (mainAcceptThread != null) 
        {
            mainAcceptThread.cancel(); 
            mainAcceptThread = null;
        }

        setState(stateNothing);
    }

    public static void write(byte[] out) {
        // Create temporary object
        ConnectedThread r;
            r = connectedThread;
        r.write(out);
    }

    public void write(int out) {
        // Create temporary object
        ConnectedThread r;
        // Synchronize a copy of the ConnectedThread
        synchronized (this) {
            if (connectionState != stateConnected) return;
            r = connectedThread;
        }
        // Perform the write unsynchronized
        r.write(out);
    }

    private void connectionFailed() {
        setState(stateListen);

        // Send a failure message back to the Activity
        Message msg = bluetoothHandler.obtainMessage(ControllerTab.MESSAGE_TOAST);
        Bundle bundle = new Bundle();
        bundle.putString(ControllerTab.TOAST, "Unable to connect device");
        msg.setData(bundle);
        bluetoothHandler.sendMessage(msg);
    }

    private void connectionLost() {
            setState(stateListen);
            // Send a failure message back to the Activity
            Message msg = bluetoothHandler.obtainMessage(ControllerTab.MESSAGE_TOAST);
            Bundle bundle = new Bundle();
            bundle.putString(ControllerTab.TOAST, "Device connection was lost");
            msg.setData(bundle);
            bluetoothHandler.sendMessage(msg);
    }

    public class ConnectThread extends Thread {
        public final BluetoothSocket connectThread_socket;
        public final BluetoothDevice connectThread_device;

        public ConnectThread(BluetoothDevice device) {
            connectThread_device = device;
            BluetoothSocket tmp = null;

            //Get a BluetoothSocket for a connection w/ the given BT device
            //try {
                //tmp = device.createRfcommSocketToServiceRecord(myUUID);} //ready to start a secure outgoing connection to this remote device using SDP lookup of uuid

            //catch (IOException e) {
                //Log.e(tag, msg, tr)
                //Log.e(tagState, "create() failed", e);}

            //Added 12/28/13
            Method m;
            try {
                    m = device.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
                    tmp = (BluetoothSocket) m.invoke(device, 1);

            } catch (SecurityException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
            } catch (NoSuchMethodException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
            } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
            } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
            } catch (InvocationTargetException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
            } 


            connectThread_socket = tmp;
        }

        public void run() {
            Log.i(tagState, "BEGIN ConnectThread");
            setName("ConnectThread");

            // Always cancel discovery because it will slow down a connection
            BTAdapter.cancelDiscovery();

            // Make a connection to the BluetoothSocket
            try {
                connectThread_socket.connect();}
            catch (IOException e) {
                connectionFailed();
                // Close the socket
                try {
                    connectThread_socket.close();
                } catch (IOException e2) {
                    Log.e(tagState, "Unable to close() socket during connection failure", e2);
                }
                // Start the service over to restart listening mode
                BluetoothCommandService.this.start();
                return;
            }

            // Reset the ConnectThread because we're done
            synchronized (BluetoothCommandService.this) {
                connectThread = null;
            }

            // Start the connected thread
            connected(connectThread_socket, connectThread_device); //ERROR: will still create "connected"
        }

        public void cancel() {
            try {
                connectThread_socket.close();
            } catch (IOException e) {
                Log.e(tagState, "close() of connect socket failed", e);
            }
        }       
    }

    public class ConnectedThread extends Thread {
        public final BluetoothSocket connectedThread_socket;
        public final InputStream connectedThread_inStream;
        public final OutputStream connectedThread_outStream;
        public ConnectedThread(BluetoothSocket socket) {
            Log.d(tagState, "create ConnectedThread");
            connectedThread_socket = socket;

            InputStream tmpIn = null;
            OutputStream tmpOut = null;

         // Get the BluetoothSocket input and output streams
            try {
                tmpIn = socket.getInputStream();
                tmpOut = socket.getOutputStream();
            } catch (IOException e) {
                Log.e(tagState, "temp sockets not created", e);
            }

            connectedThread_inStream = tmpIn;
            connectedThread_outStream = tmpOut;
        }

        public void run() {
            Log.i(tagState, "BEGIN ConnectedThread");
            //BufferedInputStream bis = new BufferedInputStream(fis, 8 * 128);
            byte[] buffer = new byte[1024]; // WALA JUD KO KASABOT ANI MAN :D
                                            //buffer == the bytes to write
                                            //buffer store for the stream

            // Keep listening to the InputStream while connected
            while (true) {
                try {
                    // Read from the InputStream
                    int bytes = connectedThread_inStream.read(buffer);
                            //BufferedInputStream bis = new BufferedInputStream(fis, 8 * 128);
//                          int bytes = new BufferedInputStream(null, 8 * 128).read(buffer);

                    // Send the obtained bytes to the UI Activity
                    bluetoothHandler.obtainMessage(ControllerTab.MESSAGE_READ, bytes, -1, buffer) 
                            .sendToTarget();
                } catch (IOException e) {
                    Log.e(tagState, "disconnected", e);
                    connectionLost(); //ERROR: will still create "private void CONNECTIONLOST"
                    break;
                }
            }
        }

        public void write(byte[] buffer) {
            try {
                connectedThread_outStream.write(buffer);
            } catch (IOException e) {
                Log.e(tagState, "Exception during write", e);
            }
        }

        public void write(int out) {
            try {
                connectedThread_outStream.write(out);
            } catch (IOException e) {
                Log.e(tagState, "Exception during write", e);
            }
        }

        public void cancel() {
            try {
                connectedThread_outStream.write(exitCMD);
                connectedThread_socket.close();
            } catch (IOException e) {
                Log.e(tagState, "close() of connect socket failed", e);
            }
        }
    }

    private class AcceptThread extends Thread {
        // The local server socket
        private final BluetoothServerSocket acceptThread_ServerSocket;

        public AcceptThread() {
            BluetoothServerSocket tmp = null;

            // Create a new listening server socket
            try {
                tmp = BTAdapter.listenUsingRfcommWithServiceRecord(name, myUUID);
            } catch (IOException e) {
                Log.e(tagState, "listen() failed", e);
            }
            acceptThread_ServerSocket = tmp;
        }

        public void run() {
            if (D) Log.d(tagState, "BEGIN mainAcceptThread" + this);
            setName("AcceptThread");
            BluetoothSocket socket = null;

            // Listen to the server socket if we're not connected
            while (connectionState != stateConnected) {
                try {
                    // This is a blocking call and will only return on a
                    // successful connection or an exception
                    socket = acceptThread_ServerSocket.accept();
                } catch (IOException e) {
                    Log.e(tagState, "accept() failed", e);
                    break;
                }

                // If a connection was accepted
                if (socket != null) {
                    synchronized (BluetoothCommandService.this) {
                        switch (connectionState) {
                        case stateListen:
                        case stateConnecting:
                            // Situation normal. Start the connected thread.
                            connected(socket, socket.getRemoteDevice());
                            break;
                        case stateNothing:
                        case stateConnected:
                            // Either not ready or already connected. Terminate new socket.
                            try {
                                socket.close();
                            } catch (IOException e) {
                                Log.e(tagState, "Could not close unwanted socket", e);
                            }
                            break;
                        }
                    }
                }
            }
            if (D) Log.i(tagState, "END mainAcceptThread");
        }

        public void cancel() {
            if (D) Log.d(tagState, "cancel " + this);
            try {
                acceptThread_ServerSocket.close();
            } catch (IOException e) {
                Log.e(tagState, "close() of server failed", e);
            }
        }
    }
}

这是我的ControllerTab第390行所在位置:

private void sendData(String message) throws IOException
{
byte[] msgBuffer = message.getBytes();
Log.d(tagStateCTRL, "...Sending data: " + message + "...");
BluetoothCommandService.write(msgBuffer);
}

如果r的值确实是问题,我应该分配给它的是不会为空?

1 个答案:

答案 0 :(得分:0)

为了使用write的{​​{1}}方法,您应首先实例化BluetoothCommandService实例,然后调用其BluetoothCommandService方法,以便它应分配新的connect()实例到ConnectThread变量,而不是从connectThread

调用write()方法