Reputation: 1362
I am building a chat app for android and in the following part (second line):
// The Handler that gets information back from the BluetoothChatService
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
case BluetoothChatService.STATE_CONNECTED:
//setStatus(getString(R.string.title_connected_to, mConnectedDeviceName));
otherDeviceName.setText(mConnectedDeviceName.toString());
mConversationArrayAdapter.clear();
break;
case BluetoothChatService.STATE_CONNECTING:
//setStatus(R.string.title_connecting);
break;
case BluetoothChatService.STATE_LISTEN:
case BluetoothChatService.STATE_NONE:
otherDeviceName.setText(R.string.friendo);
break;
}
break;
case MESSAGE_WRITE:
byte[] writeBuf = (byte[]) msg.obj;
// construct a string from the buffer
String writeMessage = new String(writeBuf);
mConversationArrayAdapter.add("Me: " + writeMessage);
break;
case 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);
mConversationArrayAdapter.add(mConnectedDeviceName+": " + readMessage);
break;
case MESSAGE_DEVICE_NAME:
// save the connected device's name
mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
Toast.makeText(getApplicationContext(), "Connected to "
+ mConnectedDeviceName, Toast.LENGTH_SHORT).show();
break;
case MESSAGE_TOAST:
Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),
Toast.LENGTH_SHORT).show();
break;
}
}
};
it gives me the following warning: this handler class should be static or leaks might occur
But when I change it to static, it fills up with errors.
Here is the full code of my main activity (didn't put all the imports and stuff here though, to avoid making it too long):
public class MainActivity extends Activity {
/* Message types sent from the BluetoothChatService Handler */
public static final int MESSAGE_STATE_CHANGE = 1;
public static final int MESSAGE_READ = 2;
public static final int MESSAGE_WRITE = 3;
public static final int MESSAGE_DEVICE_NAME = 4;
public static final int MESSAGE_TOAST = 5;
/* Name of the other device received from the BluetoothChatService Handler */
public static final String DEVICE_NAME = "device_name";
public static final String TOAST = "toast";
/* Intent request codes. For show and connect */
private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
private static final int REQUEST_ENABLE_BT = 3;
/*Initializing part*/
TextView chatHistory;
TextView otherDeviceName;
BluetoothAdapter mBluetoothAdapter = null;
EditText myTextbox;
private String mConnectedDeviceName = null; // Name of the connected device
private ArrayAdapter<String> mConversationArrayAdapter; // Array adapter for the conversation thread
private StringBuffer mOutStringBuffer; // String buffer for outgoing messages
private BluetoothChatService mChatService = null; // Member object for the chat services
/*On Create*/
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
/*Now we connect the names to the actual objects in the activity*/
Button connectButton = (Button)findViewById(R.id.button2);
Button showButton = (Button)findViewById(R.id.button3);
otherDeviceName = (TextView)findViewById(R.id.textView1);
chatHistory = (TextView)findViewById(R.id.textView2);
myTextbox = (EditText)findViewById(R.id.editText1);
myTextbox.setMovementMethod(new ScrollingMovementMethod());
/*First we make sure that the user has bluetooth (otherwise this App has no use)
This was previously located in findBT(), but it seemed unnecesary to have it that late*/
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(mBluetoothAdapter == null) //if there is no bluetooth
{
Toast.makeText(this, "This device doesn't have Bluetooth. Adquire new device", Toast.LENGTH_LONG).show();
//Toast is like a pop-up that displays the message. Changed to this so it doesn't display it in the chat history
finish(); //close activity
return;
}
chatHistory.setText("Welcome " + mBluetoothAdapter.getName() + "!");
/*For personal reasons the user might not want to activate the bluetooth until later (for example if the other user is still installing the app).
Therefore turning on bluetooth won't be requested until he chooses to connect or show */
/*connect Button: Send you to the connection activity */
connectButton.setOnClickListener(new View.OnClickListener()
{
public void onClick(View view)
{
Intent myIntent = new Intent(view.getContext(), ConnectionActivity.class);
startActivityForResult(myIntent, REQUEST_CONNECT_DEVICE_SECURE);
// Launch the DeviceListActivity to see devices and do scan
}
});
/*show Button: has to make you visible. No need for the turn on bluetooth, because it does it automatically together with the discovery */
showButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v) {
if (mBluetoothAdapter.getScanMode() != //getscanmode finds out if other can discover us
BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) { //makes sure other devices can find us AND connect to us
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); //asks for permission to (turn on bluetooth) and make me visible
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); //makes me discoverable for 300 seconds
startActivity(discoverableIntent);
}
}
});
}
/*ON START, RESUME, PAUSE, STOP AND DESTROY*/
@Override
public void onStart() {
super.onStart();
if (mChatService == null) setupChat(); //setupChat again if not done yet.
}
@Override
public synchronized void onResume() {
super.onResume();
if (mChatService != null) {
// Only if the state is STATE_NONE, do we know that we haven't started already
if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
// Start the Bluetooth chat services
mChatService.start();
}
}
}
@Override
public synchronized void onPause() {
super.onPause();
}
@Override
public void onStop() {
super.onStop();
}
@Override
public void onDestroy() {
super.onDestroy();
if (mChatService != null) mChatService.stop();
}
/* The send button */
private void setupChat() {
/*Step 1: The listener for the send button */
Button sendButton = (Button)findViewById(R.id.button1);
sendButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
String message = chatHistory.getText().toString(); //save the written thing in message
sendMessage(message); //run the sendMessage
}
});
/* Step 2: Initialize the BluetoothChatService to perform bluetooth connections*/
mChatService = new BluetoothChatService(this, mHandler);
/* Step 3: Initialize the buffer for outgoing messages */
mOutStringBuffer = new StringBuffer("");
}
/* Send message */
private void sendMessage(String message) {
/* Check that we're actually connected before trying anything, so you can't send while not connected */
if (mChatService.getState() != BluetoothChatService.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();
mChatService.write(send);
// Reset out string buffer to zero and clear the edit text field
mOutStringBuffer.setLength(0);
myTextbox.setText(mOutStringBuffer);
}
}
// The Handler that gets information back from the BluetoothChatService
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MESSAGE_STATE_CHANGE:
switch (msg.arg1) {
case BluetoothChatService.STATE_CONNECTED:
//setStatus(getString(R.string.title_connected_to, mConnectedDeviceName));
otherDeviceName.setText(mConnectedDeviceName.toString());
mConversationArrayAdapter.clear();
break;
case BluetoothChatService.STATE_CONNECTING:
//setStatus(R.string.title_connecting);
break;
case BluetoothChatService.STATE_LISTEN:
case BluetoothChatService.STATE_NONE:
otherDeviceName.setText(R.string.friendo);
break;
}
break;
case MESSAGE_WRITE:
byte[] writeBuf = (byte[]) msg.obj;
// construct a string from the buffer
String writeMessage = new String(writeBuf);
mConversationArrayAdapter.add("Me: " + writeMessage);
break;
case 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);
mConversationArrayAdapter.add(mConnectedDeviceName+": " + readMessage);
break;
case MESSAGE_DEVICE_NAME:
// save the connected device's name
mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
Toast.makeText(getApplicationContext(), "Connected to "
+ mConnectedDeviceName, Toast.LENGTH_SHORT).show();
break;
case MESSAGE_TOAST:
Toast.makeText(getApplicationContext(), msg.getData().getString(TOAST),
Toast.LENGTH_SHORT).show();
break;
}
}
};
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case REQUEST_CONNECT_DEVICE_SECURE:
// When DeviceListActivity returns with a device to connect
if (resultCode == Activity.RESULT_OK) {
connectDevice(data, true);
}
break;
case 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
setupChat();
} else {
// User did not enable Bluetooth or an error occurred
Toast.makeText(this, R.string.bt_not_enabled_leaving, Toast.LENGTH_SHORT).show();
finish();
}
}
}
private void connectDevice(Intent data, boolean secure) {
// Get the device MAC address
String address = data.getExtras()
.getString(ConnectionActivity.EXTRA_DEVICE_ADDRESS);
// Get the BluetoothDevice object
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
// Attempt to connect to the device
mChatService.connect(device, secure);
}
}
This makes it crash. Anybody that can help me out? Any help is appreciated. Let me know if I should add something to this question,
Thanks for your time.
Upvotes: 2
Views: 2440
Reputation: 4752
The warning it gives is actually correct. The way you have declared the Handler class is not recommended. Your current implementation actually creates a inner class (handler)
Ref: This Handler class should be static or leaks might occur: IncomingHandler
Handlers and memory leaks in Android
Upvotes: 1