BluetoothChat like app not communicating

橙三吉。 提交于 2019-12-13 06:13:16

问题


Have a problem while developing an app based in the BluetoothChat example, but divided in 2 activities.

  1. The main with bluetooth actions ()BTActivity
  2. The chat (BTCommunication)

I have the BluetoothChatService too divided in the following files, but they aren't activities:

  1. Transmission: All the Handler actions
  2. ConnectThread
  3. ConnectedThread
  4. AccpetThread

The app finds de device, starts connecting it and then crashes. I'm trying to find out what i'm doing wrong comparing with the BluetoothChat App, but i don't find the problem.

07-23 10:58:43.076: D/AbsListView(17279): unregisterIRListener() is called 
07-23 10:58:43.076: D/AbsListView(17279): unregisterIRListener() is called 
07-23 10:58:43.086: D/BluetoothUtils(17279): isSocketAllowedBySecurityPolicy start : device null
07-23 10:58:43.086: W/BluetoothAdapter(17279): getBluetoothService() called with no BluetoothManagerCallback
07-23 10:58:43.106: E/SpannableStringBuilder(17279): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
07-23 10:58:43.106: E/SpannableStringBuilder(17279): SPAN_EXCLUSIVE_EXCLUSIVE spans cannot have a zero length
07-23 10:58:43.116: D/AbsListView(17279): onDetachedFromWindow
07-23 10:58:43.116: D/AbsListView(17279): unregisterIRListener() is called 
07-23 10:58:43.116: D/AbsListView(17279): onDetachedFromWindow
07-23 10:58:43.116: D/AbsListView(17279): unregisterIRListener() is called 
07-23 10:58:44.527: D/AndroidRuntime(17279): Shutting down VM
07-23 10:58:44.527: W/dalvikvm(17279): threadid=1: thread exiting with uncaught exception (group=0x41d58ac8)
07-23 10:58:44.537: E/AndroidRuntime(17279): FATAL EXCEPTION: main
07-23 10:58:44.537: E/AndroidRuntime(17279): java.lang.NullPointerException
07-23 10:58:44.537: E/AndroidRuntime(17279):    at com.example.btaplication.BTActivity$1.handleMessage(BTActivity.java:288)
07-23 10:58:44.537: E/AndroidRuntime(17279):    at android.os.Handler.dispatchMessage(Handler.java:99)
07-23 10:58:44.537: E/AndroidRuntime(17279):    at android.os.Looper.loop(Looper.java:137)
07-23 10:58:44.537: E/AndroidRuntime(17279):    at android.app.ActivityThread.main(ActivityThread.java:5328)
07-23 10:58:44.537: E/AndroidRuntime(17279):    at java.lang.reflect.Method.invokeNative(Native Method)
07-23 10:58:44.537: E/AndroidRuntime(17279):    at java.lang.reflect.Method.invoke(Method.java:511)
07-23 10:58:44.537: E/AndroidRuntime(17279):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1102)
07-23 10:58:44.537: E/AndroidRuntime(17279):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:869)
07-23 10:58:44.537: E/AndroidRuntime(17279):    at dalvik.system.NativeStart.main(Native Method)
07-23 10:58:55.428: I/Process(17279): Sending signal. PID: 17279 SIG: 9

/ Here the Main activity

public class BTActivity extends Activity {


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    final Button button1 = (Button) findViewById(R.id.boton1);
    final Button button2 = (Button) findViewById(R.id.boton2);
    final Button button4 = (Button) findViewById(R.id.boton4);
    final Button button5 = (Button) findViewById(R.id.boton5);

    button5.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View view) {
            lanzarComunicacion (null);
        }
    });


    GlobalVar.mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

    if (GlobalVar.mBluetoothAdapter == null) {
        Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
        finish();
        return;
    }

    button2.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            LanzarBusqueda(null);

        }
    });

    button1.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (!GlobalVar.mBluetoothAdapter.isDiscovering()) {

                Context context = getApplicationContext();
                CharSequence text = "MAKING YOUR DEVICE DISCOVERABLE";
                int duration = Toast.LENGTH_SHORT;

                Toast toast = Toast.makeText(context, text, duration);
                toast.show();

                Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
                discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);

                startActivity(discoverableIntent);
            }
        }
    });

    button4.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            GlobalVar.mBluetoothAdapter.disable();

            Context context = getApplicationContext();
            CharSequence text = "TURNING OFF BLUETOOTH";
            int duration = Toast.LENGTH_LONG;

            Toast toast = Toast.makeText(context, text, 15);
            toast.show();

        }
    });
}


@Override
public void onStart() {
    super.onStart();

    if (!GlobalVar.mBluetoothAdapter.isEnabled()) {

        Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        startActivityForResult(enableBtIntent, GlobalVar.REQUEST_ENABLE_BT);
    }
    else {
        if (GlobalVar.mTransmission == null) setupCaller();
    }
}


@Override
public void onResume() {
    super.onResume();

    if (GlobalVar.mTransmission != null) {
        /**Only if the state is STATE_NONE, do we know that we haven't started already*/
        if (GlobalVar.mTransmission.getState() == GlobalVar.STATE_NONE) {

        }
    }
}


@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case GlobalVar.REQUEST_CONNECT_DEVICE:
            /**When DeviceListActivity returns with a device to connect*/
            if (resultCode == Activity.RESULT_OK) {
                connectDevice(data);
            }
        case GlobalVar.REQUEST_ENABLE_BT:
            /**When the request to enable Bluetooth returns*/
            if (resultCode == Activity.RESULT_OK) {
                /**Bluetooth is now enabled, so set up a chat session*/
                setupCaller();
            } else {
                /**User did not enable Bluetooth or an error occurred*/
                Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
                finish();
            }
            break;
    }

}


private void connectDevice(Intent data) {
    /**Get the device MAC address*/
    String address = data.getExtras().getString(DeviceListDialog.EXTRA_DEVICE_ADDRESS);
    /**Get the BluetoothDevice object*/
    BluetoothDevice device = GlobalVar.mBluetoothAdapter.getRemoteDevice(address);
    /**Attempt to connect to the device*/
    try{
        GlobalVar.mTransmission.connect(device);
    }catch(Exception ex) {
    }
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
    /**Inflate the menu; this adds items to the action bar if it is present.*/
    getMenuInflater().inflate(R.menu.bt, menu);
    return true;
}

public void lanzarComunicacion (View view) {
    Intent i = new Intent(this, BTCommunication.class);
    startActivity(i);
}

public void LanzarBusqueda (View view) {
    Intent serverintent = new Intent(this, DeviceListDialog.class);
    startActivityForResult(serverintent, GlobalVar.REQUEST_CONNECT_DEVICE);
}


private final void setStatus(int resId) {
    final ActionBar actionBar = getActionBar();
    actionBar.setSubtitle(resId);
}

private final void setStatus(CharSequence subTitle) {
    final ActionBar actionBar = getActionBar();
    actionBar.setSubtitle(subTitle);
}


/**
 * The Handler that gets information back from the Transmission
 */
private final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case GlobalVar.MESSAGE_STATE_CHANGE:
                switch (msg.arg1) {
                    case GlobalVar.STATE_CONNECTED:
                        setStatus(getString(R.string.title_connected_to, GlobalVar.mConnectedDeviceName));
                        GlobalVar.mConversationArrayAdapter.clear();
                        break;
                    case GlobalVar.STATE_CONNECTING:
                        setStatus(R.string.title_connecting);
                        break;
                    case GlobalVar.STATE_LISTEN:
                    case GlobalVar.STATE_NONE:
                        setStatus(R.string.title_not_connected);
                        break;
                }
                break;
            case  GlobalVar.MESSAGE_WRITE:
                byte[] writeBuf = (byte[]) msg.obj;
                /**construct a string from the buffer*/
                String writeMessage = new String(writeBuf);
                GlobalVar.mConversationArrayAdapter.add("Me:  " + writeMessage);
                break;
            case  GlobalVar.MESSAGE_READ:
                byte[] readBuf = (byte[]) msg.obj;
                /**construct a string from the valid bytes in the buffer*/
                String readMessage = new String(readBuf, 0, msg.arg1);
                GlobalVar.mConversationArrayAdapter.add(GlobalVar.mConnectedDeviceName+":  " + readMessage);
                break;
            case  GlobalVar.MESSAGE_DEVICE_NAME:
                /**save the connected device's name*/
                GlobalVar.mConnectedDeviceName = msg.getData().getString(GlobalVar.DEVICE_NAME);
                Toast.makeText(getApplicationContext(), "Connected to " + GlobalVar.mConnectedDeviceName, Toast.LENGTH_SHORT).show();
                break;
            case  GlobalVar.MESSAGE_TOAST:
                Toast.makeText(getApplicationContext(), msg.getData().getString(GlobalVar.TOAST), Toast.LENGTH_SHORT).show();
                break;
        }
    }
};

public void setupCaller() {
    /**Initialize the Transmission to perform bluetooth connections*/
    GlobalVar.mTransmission = new Transmission(this, mHandler);
}

}

/ The Chat Avtivity

public class BTCommunication extends Activity {


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    /**Set up the window layout*/
    setContentView(R.layout.chat);

    /**Start the Bluetooth chat services*/
    GlobalVar.mTransmission.start();
    setupChat(); //PROBAMOS A LLAMAR AQUI\\
}



public void setupChat() {
    /**Initialize the array adapter for the conversation thread*/
    GlobalVar.mConversationArrayAdapter = new ArrayAdapter<String>(this, R.layout.message);
    GlobalVar.mConversationView = (ListView) findViewById(R.id.in);
    GlobalVar.mConversationView.setAdapter(GlobalVar.mConversationArrayAdapter);

    /**Initialize the compose field with a listener for the return key*/
    GlobalVar.mOutEditText = (EditText) findViewById(R.id.edit_text_out);
    GlobalVar.mOutEditText.setOnEditorActionListener(mWriteListener);

    /**Initialize the send button with a listener that for click events*/
    GlobalVar.mSendButton = (Button) findViewById(R.id.button_send);
    GlobalVar.mSendButton.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
            /**Send a message using content of the edit text widget*/
            TextView view = (TextView) findViewById(R.id.edit_text_out);
            String message = view.getText().toString();
            sendMessage(message);
        }
    });

    /**Initialize the Transmission to perform bluetooth connections*/
    //Done it in BTActivity in the function "setupCaller()"\\


    /**Initialize the buffer for outgoing messages*/
    GlobalVar.mOutStringBuffer = new StringBuffer("");
}



@Override
public void onDestroy() {
    super.onDestroy();
    /**Stop the Bluetooth chat services*/
    if (GlobalVar.mTransmission != null) GlobalVar.mTransmission.stop();
}


/**
 * Sends a message.
 * @param message  A string of text to send.
 */
public void sendMessage(String message) {
    /**Check that we're actually connected before trying anything*/
    if (GlobalVar.mTransmission.getState() != GlobalVar.STATE_CONNECTED) {
        Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT).show();
        return;
    }

    /**Check that there's actually something to send*/
    if (message.length() > 0) {
        /**Get the message bytes and tell the BluetoothChatService to write*/
        byte[] send = message.getBytes();
        GlobalVar.mTransmission.write(send);

        /**Reset out string buffer to zero and clear the edit text field*/
        GlobalVar.mOutStringBuffer.setLength(0);
        GlobalVar. mOutEditText.setText(GlobalVar.mOutStringBuffer);
    }
}

/**The action listener for the EditText widget, to listen for the return key*/
private final TextView.OnEditorActionListener mWriteListener = new TextView.OnEditorActionListener() {
    @Override
    public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
        /**If the action is a key-up event on the return key, send the message*/
        if (actionId == EditorInfo.IME_NULL && event.getAction() == KeyEvent.ACTION_UP) {
            String message = view.getText().toString();
            sendMessage(message);
        }
        return true;
    }
};

}

/The Transmission file:

public class Transmission {

/**
 * Constructor. Prepares a new session.
 * @param context  The UI Activity Context
 * @param handler  A Handler to send messages back to the UI Activity
 */
public Transmission(Context context, Handler handler) {
    GlobalVar.mAdapter = BluetoothAdapter.getDefaultAdapter();
    GlobalVar.mState = GlobalVar.STATE_NONE;
    GlobalVar.mHandler = handler;
}

/**
 * Set the current state of the connection
 * @param state  An integer defining the current connection state
 */
public synchronized void setState(int state) {
    GlobalVar.mState = state;

    /**Give the new state to the Handler so the UI Activity can update*/
    GlobalVar.mHandler.obtainMessage(GlobalVar.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}

/**
 * Return the current connection state.
 */
public synchronized int getState() {
    return GlobalVar.mState;
}

/**
 * Start the chat service. Specifically start AcceptThread to begin a
 * session in listening (server) mode. Called by the Activity onResume()
 */
public synchronized void start() {
    /**Cancel any thread attempting to make a connection*/
    if (GlobalVar.mConnectThread != null) {GlobalVar.mConnectThread.cancel(); GlobalVar.mConnectThread = null;}

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

    setState(GlobalVar.STATE_LISTEN);

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

/**
 * Start the ConnectThread to initiate a connection to a remote device.
 * @param device  The BluetoothDevice to connect
 */
public synchronized void connect(BluetoothDevice device) {
    /**Cancel any thread attempting to make a connection*/
    if (GlobalVar.mState == GlobalVar.STATE_CONNECTING) {
        if (GlobalVar.mConnectThread != null) {GlobalVar.mConnectThread.cancel(); GlobalVar.mConnectThread = null;}
    }

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

    /**Start the thread to connect with the given device*/
    GlobalVar.mConnectThread = new ConnectThread(device);
    GlobalVar.mConnectThread.start();
    setState(GlobalVar.STATE_CONNECTING);
}

/**
 * Start the ConnectedThread to begin managing a Bluetooth connection
 * @param socket  The BluetoothSocket on which the connection was made
 * @param device  The BluetoothDevice that has been connected
 */
public synchronized void connected(BluetoothSocket socket, BluetoothDevice device) {
    /**Cancel the thread that completed the connection*/
    if (GlobalVar.mConnectThread != null) {GlobalVar.mConnectThread.cancel(); GlobalVar.mConnectThread = null;}

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

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

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

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

    setState(GlobalVar.STATE_CONNECTED);
}

/**
 * Stop all threads
 */
public synchronized void stop() {

    if (GlobalVar.mConnectThread != null) {
        GlobalVar.mConnectThread.cancel();
        GlobalVar.mConnectThread = null;
    }

    if (GlobalVar.mConnectedThread != null) {
        GlobalVar.mConnectedThread.cancel();
        GlobalVar.mConnectedThread = null;
    }

    if (GlobalVar.mAcceptThread != null) {
        GlobalVar.mAcceptThread.cancel();
        GlobalVar.mAcceptThread = null;
    }

    setState(GlobalVar.STATE_NONE);
}

/**
 * Write to the ConnectedThread in an unsynchronized manner
 * @param out The bytes to write
 * @see ConnectedThread#write(byte[])
 */
public void write(byte[] out) {
    /**Create temporary object*/
    ConnectedThread r;
    /**Synchronize a copy of the ConnectedThread*/
    synchronized (this) {
        if (GlobalVar.mState != GlobalVar.STATE_CONNECTED) return;
        r = GlobalVar.mConnectedThread;
    }
    /**Perform the write unsynchronized*/
    r.write(out);
}

/**
 * Indicate that the connection attempt failed and notify the UI Activity.
 */
public void connectionFailed() {
    /**Send a failure message back to the Activity*/
    Message msg = GlobalVar.mHandler.obtainMessage(GlobalVar.MESSAGE_TOAST);
    Bundle bundle = new Bundle();
    bundle.putString(GlobalVar.TOAST, "Unable to connect device");
    msg.setData(bundle);
    GlobalVar.mHandler.sendMessage(msg);

    /**tart the service over to restart listening mode*/
    Transmission.this.start();
}

/**
 * Indicate that the connection was lost and notify the UI Activity.
 */
public void connectionLost() {
    /**Send a failure message back to the Activity*/
    Message msg = GlobalVar.mHandler.obtainMessage(GlobalVar.MESSAGE_TOAST);
    Bundle bundle = new Bundle();
    bundle.putString(GlobalVar.TOAST, "Device connection was lost");
    msg.setData(bundle);
    GlobalVar.mHandler.sendMessage(msg);

    /**Start the service over to restart listening mode*/
    Transmission.this.start();
}

}

/The Accept, connect and connected threads are the same as in BleutoothChat app but each one has it's own file.


回答1:


07-23 10:58:44.537: E/AndroidRuntime(17279):    at com.example.btaplication.BTActivity$1.handleMessage(BTActivity.java:288)

You need more condition in your Handler. It crashes because you have a null pointer in your BTActivity.

I exactly had this problem 2 weeks ago (I was trying to change text of a textview in a Handler). So, in my Handler I just put :

if(mTextView == null) {mTextView = (TextView) findViewById(R.id.tv)}

even if mTextView was define before. In that case you will be sure that your attribute is define, and you will avoid NPE

Hope it helps



来源:https://stackoverflow.com/questions/17806069/bluetoothchat-like-app-not-communicating

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!