Bluetooth를 이용하는 앱을 개발하는 도중
BluetoothServerSocket을 한 쓰레드에서는 aceept()하고 다른 쓰래드에서 close()하려고 했더니
모토로이에서는 안생기는 교착상태가 갤럭시 S에서만 발생하는 것을 발견했습니다.
음.. 이거 갤럭시 S쪽의 문제 맞는거겠죠??? 모토로이가 특이한건가...
에효.. 이거 어떻게 교착상태를 피할 방법이 없을지 모르겠네요...
//-------------------------------------------------------------------------------------------------------------------
package lbibj.utility;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothServerSocket;
import android.bluetooth.BluetoothSocket;
import android.os.Bundle;
public class Test extends Activity
{
private BluetoothAdapter mBluetoothAdapter = null;
private AcceptThread mAcceptThread;
private static final String MY_NAME = "LBIBJ_Test";
private static final UUID MY_UUID = UUID.fromString("531d016f-adf8-4bdb-b548-3b8ffd94d9be");
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
}
public void onStart()
{
super.onStart();
mAcceptThread = new AcceptThread();
mAcceptThread.setDaemon(true);
mAcceptThread.start();
mAcceptThread.cancel();
}
private synchronized void connected(BluetoothSocket socket)
{
ConnectedThread tempCT = new ConnectedThread(socket);
tempCT.setDaemon(true);
tempCT.start();
}
private class AcceptThread extends Thread
{
private BluetoothServerSocket mmServerSocket;
public AcceptThread()
{
BluetoothServerSocket tmp = null;
try
{
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(MY_NAME, MY_UUID);
}
catch (IOException e)
{
e.printStackTrace();
}
mmServerSocket = tmp;
}
public void run()
{
setName("AcceptThread");
BluetoothSocket socket;
while (mmServerSocket != null)
{
socket = null;
try
{
socket = mmServerSocket.accept();
int a=0;
a++;
}
catch (IOException e)
{
// 모토로이의 경우 이 서버소켓으로 얻어진 소켓이 닫아져도 서버소켓에는 아무 변화가 없으나
// 갤럭시S의 경우 이 서버소켓으로 얻어진 소켓이 닫히면 서버소켓도 IOException이 발생한다.
// 클라이언트와의 연결이 끊겼다고 서버소켓이 닫히길 원하지 않으므로 break문을 없애고 다시 루프 돌린다.
e.printStackTrace();
//break;
}
if (socket != null)
{
connected(socket);
}
}
}
public void cancel()
{
try
{
// 서버소켓을 닫을 때 내부적으로 교착상태가 발생하는 듯 하다..
// 원인은 파악이 안되고.. 미치고 팔짝 뛰겠네..
// 아악.. 갤럭시S에서만 에러난다.. 모토로이는 잘 된다.....
mmServerSocket.close();
mmServerSocket = null;
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
private class ConnectedThread extends Thread
{
private BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket)
{
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try
{
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
}
catch (IOException e)
{
e.printStackTrace();
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run()
{
setName("ConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
while (mmSocket != null)
{
try
{
bytes = mmInStream.read(buffer);
}
catch (IOException e)
{
this.cancel();
break;
}
}
}
public void write(byte[] buffer)
{
try
{
mmOutStream.write(buffer);
}
catch (IOException e)
{
e.printStackTrace();
}
}
public BluetoothSocket getSocket()
{
return mmSocket;
}
public void cancel()
{
try
{
mmSocket.close();
mmSocket = null;
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}




갤럭시S에서 블루투스 APP 만들어 봤을 때, 특이한 교착상태는 보지 못했습니다.
참고하세요!