Reputation: 43
In my application i want to do bluetooth chat. I'm facing a problem in threading. In my application my android phone will work as server which has a blocking statement
socket=mServerSocket.accept();
for this purpose i've created a child thread so that it will run separately. But before finishing this child thread main thread goes down giving Force Close
and if i use the .join()
method it hangs up my UI
.
What is the solution to run both threads parallel?
this is my code main Activity
package com.my.bluechat_2_1;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class BlueChat extends Activity {
/** Called when the activity is first created. */
private BlueHandler btHandler=null;
private BluetoothAdapter btAdapter = null;
private Context context=this;
TextView chatWindow=null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
chatWindow=(TextView)findViewById(R.id.textView1);
doStart();
}
private void doStart(){
Button btnStart=(Button)findViewById(R.id.button1);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// Get local Bluetooth adapter
btAdapter = BluetoothAdapter.getDefaultAdapter();
// If the adapter is null, then Bluetooth is not supported
if(btAdapter == null)
{
Toast.makeText(context, "Device does not support Bluetooth", Toast.LENGTH_LONG).show();
}
if (!btAdapter.isEnabled()) {
Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
}
chatWindow.append("Waiting for connection...\n");
btHandler=new BlueHandler(context,chatWindow,btAdapter);
Thread acceptThread=new Thread(btHandler);
acceptThread.start();
}
});
}
}
BlueHandler
package com.my.bluechat_2_1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.widget.TextView;
import android.widget.Toast;
public class BlueHandler implements Runnable{
// Name for the SDP record when creating server socket
private static final String SMARTCAM_BT_SERVICE_NAME = "SmartCam";
// Unique UUID for this application
private static final UUID SMARTCAM_BT_SERVICE_UUID = UUID.fromString("95b82690-4c94-11e1-b86c-0800200c9a66");
private BluetoothAdapter btAdapter = null;
private BluetoothServerSocket btServerSocket = null;
private BluetoothSocket btSocket = null;
private InputStream btInputStream=null;
private Context contextObj=null;
private TextView textView;
public BlueHandler(Context contextObj,TextView textView,BluetoothAdapter btAdapter){
this.contextObj=contextObj;
this.btAdapter=btAdapter;
this.textView=textView;
try {
btServerSocket=this.btAdapter.listenUsingRfcommWithServiceRecord(SMARTCAM_BT_SERVICE_NAME, SMARTCAM_BT_SERVICE_UUID);
} catch (IOException e) {
// TODO Auto-generated catch block
Toast.makeText(this.contextObj, "Service not created", Toast.LENGTH_LONG);
}
}
@Override
public void run() {
// TODO Auto-generated method stub
textView.append("Inside child thread.\n");
textView.append(btServerSocket+"\n");
while (true) {
try {
btSocket = btServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (btSocket != null) {
// Do work to manage the connection (in a separate thread)
try {
btServerSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
textView.append("Connected.\n");
try {
btInputStream=btSocket.getInputStream();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
byte[] buffer = new byte[1024]; // buffer store for the stream
String s;
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes=btInputStream.read(buffer);
s= new String(buffer);
// Send the obtained bytes to the UI Activity
textView.append("received ::" +s+"\n");
} catch (IOException e) {
break;
}
}
}
}
Upvotes: 1
Views: 421
Reputation: 14740
You're probably getting a crash because you're accessing a textView on the worker thread. You'll need to use TextView.post(Runnable) to make that not happen.
In reality you should be using a bindable Service to do this kind of work. You can post back to the UI via broadcast intents or callback methods, That way you don't have to worry about rotation bugs.
Upvotes: 1
Reputation: 2101
Are you performing a long operation in the constructor of your children thread? Each long operation must be done in the run() method.
Upvotes: 0