BluetoothServerSocketInstance.accept() not returning anything
And next step is not executing
Thread blocks at the same place
I have seen many similar questions but unfortunately none of them were helpful to me
I am creating Accept Thread like this
private class AcceptThread extends Thread {
// The local server socket
private String mSocketType;
boolean isRunning = true;
private BluetoothServerSocket mmServerSocket;
public AcceptThread(boolean isAndroid) {
BluetoothServerSocket tmp = null;
// Create a new listening server socket
try {
if (isAndroid)
tmp = mAdapter.listenUsingRfcommWithServiceRecord(
NAME_SECURE, UUID_ANDROID_DEVICE);
else
tmp = mAdapter.listenUsingRfcommWithServiceRecord(
NAME_SECURE, UUID_OTHER_DEVICE);
} catch (IOException e) {
}
mmServerSocket = tmp;
}
public void run() {
setName("AcceptThread" + mSocketType);
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != BluetoothState.STATE_CONNECTED && isRunning) {
try {
// This is a blocking call and will only return on a
// successful connection or an exception
if (mmServerSocket != null)
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
synchronized (BluetoothService.this) {
switch (mState) {
case BluetoothState.STATE_LISTEN:
case BluetoothState.STATE_CONNECTING:
// Situation normal. Start the connected thread.
connected(socket, socket.getRemoteDevice(),
mSocketType);
break;
case BluetoothState.STATE_NONE:
case BluetoothState.STATE_CONNECTED:
// Either not ready or already connected. Terminate
// new socket.
try {
socket.close();
} catch (IOException e) {
}
break;
}
}
}
}
}
public void cancel() {
try {
mmServerSocket.close();
mmServerSocket = null;
} catch (IOException e) {
}
}
public void kill() {
isRunning = false;
}
}
I have the following implementation of ToyVpnService which I got frome here
public class ToyVpnService extends VpnService implements Handler.Callback, Runnable {
private static final String TAG = "ToyVpnService";
private Handler mHandler;
private Thread mThread;
private ParcelFileDescriptor mInterface;
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
// The handler is only used to show messages.
if (mHandler == null) {
mHandler = new Handler(this);
}
// Stop the previous session by interrupting the thread.
if (mThread != null) {
mThread.interrupt();
}
// Start a new session by creating a new thread.
mThread = new Thread(this, "ToyVpnThread");
mThread.start();
return START_STICKY;
}
#Override
public void onDestroy() {
if (mThread != null) {
mThread.interrupt();
}
}
#Override
public boolean handleMessage(Message message) {
if (message != null) {
Toast.makeText(this, message.what, Toast.LENGTH_SHORT).show();
}
return true;
}
#Override
public synchronized void run() {
Log.i(TAG, "running vpnService");
try {
runVpnConnection();
} catch (Exception e) {
e.printStackTrace();
//Log.e(TAG, "Got " + e.toString());
} finally {
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = null;
mHandler.sendEmptyMessage(R.string.disconnected);
Log.i(TAG, "Exiting");
}
}
private boolean runVpnConnection() throws Exception {
configure();
FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());
// Allocate the buffer for a single packet.
ByteBuffer packet = ByteBuffer.allocate(32767);
// We keep forwarding packets till something goes wrong.
while (true) {
// Assume that we did not make any progress in this iteration.
boolean idle = true;
// Read the outgoing packet from the input stream.
int length = in.read(packet.array());
if (length > 0) {
Log.i(TAG, "************new packet");
System.exit(-1);
while (packet.hasRemaining()) {
Log.i(TAG, "" + packet.get());
//System.out.print((char) packet.get());
}
packet.limit(length);
// tunnel.write(packet);
packet.clear();
// There might be more outgoing packets.
idle = false;
}
Thread.sleep(50);
}
}
public String getLocalIpAddress() {
try {
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
NetworkInterface intf = en.nextElement();
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
InetAddress inetAddress = enumIpAddr.nextElement();
Log.i(TAG, "****** INET ADDRESS ******");
Log.i(TAG, "address: " + inetAddress.getHostAddress());
Log.i(TAG, "hostname: " + inetAddress.getHostName());
Log.i(TAG, "address.toString(): " + inetAddress.getHostAddress().toString());
if (!inetAddress.isLoopbackAddress()) {
//IPAddresses.setText(inetAddress.getHostAddress().toString());
Log.i(TAG, "IS NOT LOOPBACK ADDRESS: " + inetAddress.getHostAddress().toString());
return inetAddress.getHostAddress().toString();
} else {
Log.i(TAG, "It is a loopback address");
}
}
}
} catch (SocketException ex) {
String LOG_TAG = null;
Log.e(LOG_TAG, ex.toString());
}
return null;
}
private void configure() throws Exception {
// If the old interface has exactly the same parameters, use it!
if (mInterface != null) {
Log.i(TAG, "Using the previous interface");
return;
}
// Configure a builder while parsing the parameters.
Builder builder = new Builder();
builder.setMtu(1500);
builder.addAddress(getLocalIpAddress(), 24);
try {
mInterface.close();
} catch (Exception e) {
// ignore
}
mInterface = builder.establish();
}
}
It seems to be receiving packets but I have no idea on how to read the data in the paclkets. the code seems to be incomplete (hence the tunnel.write(packet) that's commented out cause there isn't a variable tunnel). Is this the right way? or is there a better way of doing this?
I'm trying to connect two mobile phone (galaxy note1, galaxy note2) with bluetooth but socket connection is fail.
this is my LogCat:
I/BluetoothService(24036): BEGIN mConnectThread
D/BluetoothUtils(24036): isSocketAllowedBySecurityPolicy start : device null
D/BluetoothService(24036): setState() 2 -> 1
D/BluetoothService(24036): Connect Fail
D/BluetoothService(24036): start
V/BluetoothSocket.cpp(24036): abortNative
V/BluetoothSocket.cpp(24036): ...asocket_abort(56) complete
V/BluetoothSocket.cpp(24036): destroyNative
V/BluetoothSocket.cpp(24036): ...asocket_destroy(56) complete
D/BluetoothUtils(24036): isSocketAllowedBySecurityPolicy start : device null
D/BluetoothService(24036): setState() 1 -> 1
D/BluetoothService(24036): Connect Fail
D/BluetoothService(24036): start
I don't know why 'connect fail' is occured.
isSocketAllowedBySecurityPolicy start : device null' is problem? OR bluetooth uuid is not correct?
Could you tell me what is the problem and how to solve this?
And I also add my src code about bluetoothservice part
public class BluetoothService {
// Debugging
private static final String TAG = "BluetoothService";
// Intent request code
private static final int REQUEST_CONNECT_DEVICE = 1;
private static final int REQUEST_ENABLE_BT = 2;
// RFCOMM Protocol
private static final UUID MY_UUID = UUID
.fromString("8ce255c0-200a-11e0-ac64-0800200c9a66");
private BluetoothAdapter btAdapter;
private Activity mActivity;
private Handler mHandler;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private int mState;
private static final int STATE_NONE = 0; // we're doing nothing
private static final int STATE_LISTEN = 1; // now listening for incoming
// connections
private static final int STATE_CONNECTING = 2; // now initiating an outgoing
// connection
private static final int STATE_CONNECTED = 3; // now connected to a remote
// device
// Constructors
public BluetoothService(Activity ac, Handler h) {
mActivity = ac;
mHandler = h;
btAdapter = BluetoothAdapter.getDefaultAdapter();
}
/**
* Check the Bluetooth support
*
* #return boolean
*/
public boolean getDeviceState() {
Log.i(TAG, "Check the Bluetooth support");
if (btAdapter == null) {
Log.d(TAG, "Bluetooth is not available");
return false;
} else {
Log.d(TAG, "Bluetooth is available");
return true;
}
}
/**
* Check the enabled Bluetooth
*/
public void enableBluetooth() {
Log.i(TAG, "Check the enabled Bluetooth");
if (btAdapter.isEnabled()) {
Log.d(TAG, "Bluetooth Enable Now");
// Next Step
scanDevice();
} else {
Log.d(TAG, "Bluetooth Enable Request");
Intent i = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
mActivity.startActivityForResult(i, REQUEST_ENABLE_BT);
}
}
/**
* Available device search
*/
public void scanDevice() {
Log.d(TAG, "Scan Device");
Intent serverIntent = new Intent(mActivity, DeviceListActivity.class);
mActivity.startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
}
/**
* after scanning and get device info
*
* #param data
*/
public void getDeviceInfo(Intent data) {
// Get the device MAC address
String address = data.getExtras().getString(
DeviceListActivity.EXTRA_DEVICE_ADDRESS);
// Get the BluetoothDevice object
// BluetoothDevice device = btAdapter.getRemoteDevice(address);
BluetoothDevice device = btAdapter.getRemoteDevice(address);
Log.d(TAG, "Get Device Info \n" + "address : " + address);
connect(device);
}
private synchronized void setState(int state) {
Log.d(TAG, "setState() " + mState + " -> " + state);
mState = state;
}
public synchronized int getState() {
return mState;
}
public synchronized void start() {
Log.d(TAG, "start");
// Cancel any thread attempting to make a connection
if (mConnectThread == null) {
} else {
mConnectThread.cancel();
mConnectThread = null;
}
// Cancel any thread currently running a connection
if (mConnectedThread == null) {
} else {
mConnectedThread.cancel();
mConnectedThread = null;
}
}
public synchronized void connect(BluetoothDevice device) {
Log.d(TAG, "connect to: " + device);
// Cancel any thread attempting to make a connection
if (mState == STATE_CONNECTING) {
if (mConnectThread == null) {
} else {
mConnectThread.cancel();
mConnectThread = null;
}
}
// Cancel any thread currently running a connection
if (mConnectedThread == null) {
} else {
mConnectedThread.cancel();
mConnectedThread = null;
}
// Start the thread to connect with the given device
mConnectThread = new ConnectThread(device);
mConnectThread.start();
setState(STATE_CONNECTING);
}
// ConnectedThread
public synchronized void connected(BluetoothSocket socket,
BluetoothDevice device) {
Log.d(TAG, "connected");
// Cancel the thread that completed the connection
if (mConnectThread == null) {
} else {
mConnectThread.cancel();
mConnectThread = null;
}
// Cancel any thread currently running a connection
if (mConnectedThread == null) {
} else {
mConnectedThread.cancel();
mConnectedThread = null;
}
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
setState(STATE_CONNECTED);
}
// thread stop
public synchronized void stop() {
Log.d(TAG, "stop");
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
setState(STATE_NONE);
}
public void write(byte[] out) { // Create temporary object
ConnectedThread r; // Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != STATE_CONNECTED)
return;
r = mConnectedThread;
} // Perform the write unsynchronized r.write(out); }
}
private void connectionFailed() {
setState(STATE_LISTEN);
}
private void connectionLost() {
setState(STATE_LISTEN);
}
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
try {
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Log.e(TAG, "create() failed", e);
}
mmSocket = tmp;
}
public void run() {
Log.i(TAG, "BEGIN mConnectThread");
setName("ConnectThread");
btAdapter.cancelDiscovery();
try {
mmSocket.connect();
Log.d(TAG, "Connect Success");
} catch (IOException e) {
connectionFailed();
Log.d(TAG, "Connect Fail");
try {
mmSocket.close();
} catch (IOException e2) {
Log.e(TAG,
"unable to close() socket during connection failure",
e2);
}
BluetoothService.this.start();
return;
}
synchronized (BluetoothService.this) {
mConnectThread = null;
}
connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "create ConnectedThread");
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e(TAG, "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
bytes = mmInStream.read(buffer);
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
}
/**
* Write to the connected OutStream.
*
* #param buffer
* The bytes to write
*/
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
} catch (IOException e) {
Log.e(TAG, "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
}
connect fail occurs at connectThread. I'm sorry that this question is not easy to read.
Try to get correct UUID by:
BluetoothDevice device;
ParcelUuid list[] = device.getUuids();
//use e.g. first list[0]
deviceUUID = UUID.fromString(list[0].toString());
try {
TheSocket = TheDevice.createRfcommSocketToServiceRecord(deviceUUID);
} catch (IOException e) {
e.printStackTrace();
}
I have a problem with bluetooth in Android, I follow the tutorial in the android developer but I am not able to connect to a paired device in Android, I am using android studio and this is my code:
public class BluetootConectionManager
{
private static final String TAG = "BLUETOOTH CONECTION";
public static BluetootConectionManager BLUETOOTH_MANAGER= new BluetootConectionManager();
private BluetoothStateListener mBluetoothStateListener = null;
// Unique UUID for this application
private static final UUID UUID_OTHER_DEVICE = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb");
private ConnectThread mConnectThread;
private AcceptThread mSecureAcceptThread;
private static final String NAME_SECURE = "Bluetooth Secure";
private ConnectedThread mConnectedThread;
private BluetoothAdapter mAdapter;
private int mState;
public interface BluetoothStateListener
{
public void onServiceStateChanged(int state);
}
public BluetootConectionManager()
{
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = BluetoothState.STATE_NONE;
mAdapter = BluetoothAdapter.getDefaultAdapter();
}
public void setBluetoothStateListener(BluetoothStateListener listener)
{
this.mBluetoothStateListener = listener;
}
public String[] getPairedDeviceName() {
int c = 0;
Set<BluetoothDevice> devices = mAdapter.getBondedDevices();
String[] name_list = new String[devices.size()];
for(BluetoothDevice device : devices) {
name_list[c] = device.getName();
c++;
}
return name_list;
}
public String[] getPairedDeviceAddress() {
int c = 0;
Set<BluetoothDevice> devices = mAdapter.getBondedDevices();
String[] address_list = new String[devices.size()];
for(BluetoothDevice device : devices) {
address_list[c] = device.getAddress();
c++;
}
return address_list;
}
public synchronized int getState()
{
return mState;
}
// CONECTAR CON DISPOSITIVOS
public synchronized void connect(String address)
{
BluetoothDevice device = mAdapter.getRemoteDevice(address);
connect(device);
}
public synchronized void connect(BluetoothDevice device)
{
// Cancel any thread attempting to make a connection
if (mState == BluetoothState.STATE_CONNECTING)
{
if (mConnectThread != null)
{
mConnectThread.cancel();
mConnectThread = null;
}
}
// Cancel any thread currently running a connection
if (mConnectedThread != null)
{
mConnectedThread.cancel();
mConnectedThread = null;
}
// Start the thread to connect with the given device
mConnectThread = new ConnectThread(device);
mConnectThread.start();
setState(BluetoothState.STATE_CONNECTING);
}
// METODO PARA OBTENER CONEXIONES ENTRANTES
public synchronized void start()
{
if (mConnectThread != null)
{
mConnectThread.cancel();
mConnectThread = null;
}
// Cancel any thread currently running a connection
if (mConnectedThread != null)
{
mConnectedThread.cancel();
mConnectedThread = null;
}
setState(BluetoothState.STATE_LISTEN);
if (mSecureAcceptThread == null) {
mSecureAcceptThread = new AcceptThread();
mSecureAcceptThread.start();
}
}
public synchronized void stop() {
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mSecureAcceptThread != null) {
mSecureAcceptThread.cancel();
mSecureAcceptThread.kill();
mSecureAcceptThread = null;
}
setState(BluetoothState.STATE_NONE);
}
public void send(byte[] data, boolean CRLF) {
if(getState() == BluetoothState.STATE_CONNECTED) {
if(CRLF) {
byte[] data2 = new byte[data.length + 2];
for(int i = 0 ; i < data.length ; i++)
data2[i] = data[i];
data2[data2.length - 0] = 0x0A;
data2[data2.length] = 0x0D;
write(data2);
} else {
write(data);
}
}
}
public void send(String data, boolean CRLF) {
if(getState() == BluetoothState.STATE_CONNECTED) {
if(CRLF)
data += "\r\n";
write(data.getBytes());
}
}
private void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (this) {
if (mState != BluetoothState.STATE_CONNECTED) return;
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
private void connectionFailed() {
// Start the service over to restart listening mode
BluetootConectionManager.this.start();
}
// Indicate that the connection was lost and notify the UI Activity
private void connectionLost() {
// Start the service over to restart listening mode
BluetootConectionManager.this.start();
}
private synchronized void setState(int state)
{
mState = state;
// Give the new state to the Handler so the UI Activity can update
mBluetoothStateListener.onServiceStateChanged(state);
}
// session in listening (server) mode. Called by the Activity onResume()
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device)
{
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try
{
tmp = device.createRfcommSocketToServiceRecord(UUID_OTHER_DEVICE);
} catch (IOException e)
{
e.printStackTrace();
}
mmSocket = tmp;
}
public void run() {
// Always cancel discovery because it will slow down a connection
mAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
mmSocket.connect();
} catch (IOException e) {
// Close the socket
e.printStackTrace();
try {
mmSocket.close();
} catch (IOException e2)
{
e.printStackTrace();
}
connectionFailed();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetootConectionManager.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
public synchronized void connected(BluetoothSocket socket, BluetoothDevice
device)
{
// Cancel the thread that completed the connection
if (mConnectThread != null)
{
mConnectThread.cancel();
mConnectThread = null;
}
// Cancel any thread currently running a connection
if (mConnectedThread != null)
{
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mSecureAcceptThread != null) {
mSecureAcceptThread.cancel();
mSecureAcceptThread = null;
}
// Start the thread to manage the connection and perform transmissions
mConnectedThread = new ConnectedThread(socket);
mConnectedThread.start();
// Send the name of the connected device back to the UI Activity
setState(BluetoothState.STATE_CONNECTED);
}
// This thread runs during a connection with a remote device.
// It handles all incoming and outgoing transmissions.
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket)
{
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the BluetoothSocket input and output streams
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer;
ArrayList<Integer> arr_byte = new ArrayList<Integer>();
// Keep listening to the InputStream while connected
while (true) {
try {
int data = mmInStream.read();
if(data == 0x0A) {
} else if(data == 0x0D) {
buffer = new byte[arr_byte.size()];
for(int i = 0 ; i < arr_byte.size() ; i++) {
buffer[i] = arr_byte.get(i).byteValue();
}
// Send the obtained bytes to the UI A
arr_byte = new ArrayList<Integer>();
} else {
arr_byte.add(data);
}
} catch (IOException e) {
connectionLost();
// Start the service over to restart listening mode
BluetootConectionManager.this.start();
break;
}
}
}
// Write to the connected OutStream.
// #param buffer The bytes to write
public void write(byte[] buffer) {
try {/*
byte[] buffer2 = new byte[buffer.length + 2];
for(int i = 0 ; i < buffer.length ; i++)
buffer2[i] = buffer[i];
buffer2[buffer2.length - 2] = 0x0A;
buffer2[buffer2.length - 1] = 0x0D;*/
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
} catch (IOException e) { }
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
private class AcceptThread extends Thread {
// The local server socket
private BluetoothServerSocket mmServerSocket;
private String mSocketType;
boolean isRunning = true;
public AcceptThread() {
BluetoothServerSocket tmp = null;
// Create a new listening server socket
try {
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE, UUID_OTHER_DEVICE);
} catch (IOException e) { }
mmServerSocket = tmp;
}
public void run() {
setName("AcceptThread" + mSocketType);
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != BluetoothState.STATE_CONNECTED && isRunning) {
try {
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
synchronized (BluetootConectionManager.this) {
switch (mState) {
case BluetoothState.STATE_LISTEN:
case BluetoothState.STATE_CONNECTING:
// Situation normal. Start the connected thread.
connected(socket, socket.getRemoteDevice());
break;
case BluetoothState.STATE_NONE:
case BluetoothState.STATE_CONNECTED:
// Either not ready or already connected. Terminate new socket.
try {
socket.close();
} catch (IOException e) { }
break;
}
}
}
}
}
public void cancel() {
try {
mmServerSocket.close();
mmServerSocket = null;
} catch (IOException e) { }
}
public void kill() {
isRunning = false;
}
}
}
I am trying to connect with
btManager.connect(address);
But I get the following error when trying to connect:
java.io.IOException: Service discovery failed
I'm pretty new to Android. Right now I'm trying to make a two-player Pong game using the Bluetooth API. I've more or less tried to copy the BluetoothChat tutorial on the Android website, but I still get an error where the socket immediately disconnects after I switch over to the ConnectedThread. Would anyone have any idea why this is?
I have each of the three types of threads as a private class on a screen of a menu. ConnectThread is split into reading and writing, and is placed inside the screen of the game.
public abstract class FindScreen extends EngineView {
private GUIFactory guiFact;
private TextButton backButton;
private ScrollingList buttonList;
public ConnectThread connectThread;
private BluetoothAdapter adapter;
public FindScreen(Context c, AndroidView aView) {
super(c, aView, 1);
adapter = BluetoothAdapter.getDefaultAdapter();
guiFact = new GUIFactory(new Vector2d(EngineConstants.CENTER_X,
EngineConstants.CENTER_Y), 8, 8, EngineConstants.VIRTUAL_W,
EngineConstants.VIRTUAL_H, EngineConstants.VIRTUAL_W / 32);
GUITask backTask = new GUITask() {
public void execute() {
goBack();
}
};
backButton = guiFact.newGradientTextButton(1, 6, 7, 7, backTask, "Back");
this.add(backButton, 0);
buttonList = guiFact.newScrollingList(1,1,7,6);
this.add(buttonList, 0);
}
#Override
public boolean onTouchEvent(MotionEvent e) {
backButton.executeIfContained(e.getX(), e.getY());
buttonList.executeIfContained(e.getX(), e.getY());
return true;
}
public void onIn() {
// Register for broadcasts when a device is discovered
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
context.registerReceiver(receiver, filter);
// Register for broadcasts when discovery has finished
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
context.registerReceiver(receiver, filter);
buttonList.clearButtons();
if(!adapter.startDiscovery()) { // if discovery doesn't start successfully, leave the screen
goBack();
}
}
public void onOut() {
if (adapter.isDiscovering()) {
adapter.cancelDiscovery();
}
context.unregisterReceiver(receiver);
if (connectThread != null) {
connectThread.cancel();
}
}
/**
* Return to the previous screen, the menu screen
*/
public abstract void goBack();
/**
* Do something after we've connected
* #param socket
*/
public abstract void connected(BluetoothSocket socket);
/**
* Broadcast receiver;
* Listens for discovered devices
* When discovery is finished, changes the list of discovered devices
* When discoverability is changed, changes text
*/
private final BroadcastReceiver receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
buttonList.addButton(device.getName(), new ConnectTask(device.getAddress()));
// }
// doDiscovery();
}
}
};
private class ConnectTask extends GUITask {
private String address;
public ConnectTask(String addr) {
address = addr;
}
#Override
public void execute() {
BluetoothDevice device = adapter.getRemoteDevice(address);
if (connectThread != null) {
connectThread.cancel();
}
connectThread = new ConnectThread(device);
connectThread.start();
}
}
private class ConnectThread extends Thread {
private final BluetoothSocket socket;
private final BluetoothDevice device;
public ConnectThread(BluetoothDevice dev) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
device = dev;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(EngineConstants.MY_UUID);
} catch (IOException e) { }
socket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
if (adapter.isDiscovering()) {
adapter.cancelDiscovery();
}
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
socket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
socket.close();
} catch (IOException closeException) { }
return;
}
// Do work to manage the connection (in a separate thread)
connected(socket);
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
socket.close();
} catch (IOException e) { }
}
}
public abstract class HostScreen extends EngineView {
private GUIFactory guiFact;
private TextButton backButton;
private TextLabel waitText;
private BluetoothAdapter adapter;
public AcceptThread acceptThread;
private static final int DISCOVERY_LENGTH = 300;
public HostScreen(Context c, AndroidView aView) {
super(c, aView, 1);
adapter = BluetoothAdapter.getDefaultAdapter();
guiFact = new GUIFactory(new Vector2d(EngineConstants.CENTER_X,
EngineConstants.CENTER_Y), 8, 8, EngineConstants.VIRTUAL_W,
EngineConstants.VIRTUAL_H, EngineConstants.VIRTUAL_W / 32);
GUITask backTask = new GUITask() {
public void execute() {
goBack();
}
};
backButton = guiFact.newGradientTextButton(1, 6, 7, 7, backTask, "Back");
this.add(backButton, 0);
waitText = guiFact.newLabel(2, 3, 6, 4, Color.WHITE, "...");
this.add(waitText, 0);
}
public void onIn() {
if (adapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, DISCOVERY_LENGTH);
((Activity) context).startActivityForResult(discoverableIntent, EngineConstants.REQUEST_DISCOVERABLE);
}
if (!adapter.isEnabled()) {
Intent enableIntent = new Intent(
BluetoothAdapter.ACTION_REQUEST_ENABLE);
context.startActivity(enableIntent);
}
}
public void onOut() {
if (acceptThread != null) {
acceptThread.cancel();
}
}
public void discoverableAccepted() {
if (acceptThread != null) {
acceptThread.cancel();
}
acceptThread = new AcceptThread();
acceptThread.start();
}
public void discoverableDeclined() {
goBack();
}
/**
* Do something after we've connected
* #param socket
*/
public abstract void connected(BluetoothSocket socket);
#Override
public boolean onTouchEvent(MotionEvent e) {
backButton.executeIfContained(e.getX(), e.getY());
return true;
}
/**
* Return to the previous screen, the menu screen
*/
public abstract void goBack();
private class AcceptThread extends Thread {
private final BluetoothServerSocket serverSocket;
public AcceptThread() {
// Use a temporary object that is later assigned to mmServerSocket,
// because mmServerSocket is final
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code
tmp = adapter.listenUsingRfcommWithServiceRecord(EngineConstants.NAME, EngineConstants.MY_UUID);
} catch (IOException e) { }
serverSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
while (true) {
try {
socket = serverSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
connected(socket);
try {
serverSocket.close();
} catch (IOException e) {
android.util.Log.d("Accept thread", "Could not close serverSocket");
}
break;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
serverSocket.close();
} catch (IOException e) { }
}
}
}
public class GameScreen extends EngineView {
public ConnectedThread connectedThread;
public ConnectedWriteThread writeThread;
private PacketHandler handler;
private final static int N_LAYERS = 4;
// layer 0 = walls
// layer 1 = puck
// layer 2 = paddles
// layer 3 = GUI
public Paddle enemyPaddle, playerPaddle;
public Puck puck;
private GUIFactory guiFact;
private TextLabel playerLabel, enemyLabel;
public int playerScore = 0, enemyScore = 0;
private boolean isHeld;
private float startX, startTouchX, moveToX;
private final static float MIN_X = Paddle.RADIUS, MAX_X = EngineConstants.VIRTUAL_W - MIN_X;
public float myPaddlePrevPosX;
public boolean enemyScoreChanged = false;
private final static long PACKET_RATE = 200;
private long packetTime = 0;
public GameScreen(Context c, final AndroidView aView) {
super(c, aView, N_LAYERS);
enemyPaddle = new Paddle(new Vector2d(EngineConstants.CENTER_X, EngineConstants.VIRTUAL_H/8f), 255, 255, 100, 100);
playerPaddle = new Paddle(new Vector2d(EngineConstants.CENTER_X, EngineConstants.VIRTUAL_H*7f/8f), 255, 100, 255, 100);
puck = new Puck();
this.add(enemyPaddle, 2);
this.add(playerPaddle, 2);
this.add(puck, 1);
guiFact = new GUIFactory(new Vector2d(EngineConstants.CENTER_X, EngineConstants.CENTER_Y), 8, 10, EngineConstants.VIRTUAL_W, EngineConstants.VIRTUAL_H, 0);
playerLabel = guiFact.newLabel(2, 4, 3, 5, Color.rgb(100, 150, 100), "0");
enemyLabel = guiFact.newLabel(7, 3, 8, 4, Color.rgb(150, 100, 100), "0");
this.add(playerLabel, 3);
this.add(enemyLabel, 3);
this.constraints.add(new BoxConstraint(puck, false, false, 0 + Puck.RADIUS));
this.constraints.add(new BoxConstraint(puck, false, true, EngineConstants.VIRTUAL_W - Puck.RADIUS));
myPaddlePrevPosX = playerPaddle.pos.x;
}
public void onOut() {
if (connectedThread != null) {
connectedThread.cancel();
}
if (writeThread != null) {
writeThread.cancel();
}
}
public void update(long interval) {
super.update(interval);
EngineFunctions.collide(playerPaddle, puck);
EngineFunctions.collide(enemyPaddle, puck);
if (puck.pos.y < 0) {
score(true);
} else if (puck.pos.y > EngineConstants.VIRTUAL_H) {
score(false);
}
packetTime += interval;
if (packetTime > PACKET_RATE) {
// android.util.Log.d("fillQueue", "called");
packetTime = 0;
writeThread.fillQueue();
}
}
private void score(boolean isPlayer) {
if (isPlayer) {
playerScore++;
playerLabel.setText(String.valueOf(playerScore));
} else {
enemyScore++;
enemyLabel.setText(String.valueOf(enemyScore));
enemyScoreChanged = true;
}
puck.pos.x = EngineConstants.CENTER_X;
puck.pos.y = EngineConstants.CENTER_Y;
puck.prevPos.x = EngineConstants.CENTER_X;
puck.prevPos.y = EngineConstants.CENTER_Y;
}
#Override
public boolean onTouchEvent(MotionEvent e) {
switch(e.getAction()) {
case MotionEvent.ACTION_DOWN:
if (playerPaddle.touching(e.getX(), e.getY())) {
isHeld = true;
startX = playerPaddle.pos.x;
startTouchX = e.getX();
}
break;
case MotionEvent.ACTION_MOVE:
if (isHeld) {
myPaddlePrevPosX = playerPaddle.pos.x;
moveToX = startX + (e.getX() - startTouchX);
if (moveToX < MIN_X) {
moveToX = MIN_X;
} else if (moveToX > MAX_X) {
moveToX = MAX_X;
}
playerPaddle.pos.x = moveToX;
playerPaddle.prevPos.x = moveToX;
}
break;
case MotionEvent.ACTION_UP:
isHeld = false;
break;
}
return true;
}
public void startNewConnectedThread(BluetoothSocket soc, boolean isServer) {
if (connectedThread != null) {
connectedThread.cancel();
}
connectedThread = new ConnectedThread(soc, handler);
connectedThread.start();
if (writeThread != null) {
writeThread.cancel();
}
writeThread = new ConnectedWriteThread(soc, handler, isServer);
writeThread.start();
}
public void setHandler(PacketHandler h) {
handler = h;
}
public class ConnectedThread extends Thread {
private final BluetoothSocket socket;
private final InputStream inStream;
private final BufferedReader in;
private PacketHandler handler;
public ConnectedThread(BluetoothSocket soc, PacketHandler pHandler) {
socket = soc;
handler = pHandler;
InputStream tmpIn = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
} catch (IOException e) {
}
inStream = tmpIn;
in = new BufferedReader(new InputStreamReader(inStream));
}
public void run() {
/*
// Keep listening to the InputStream until an exception occurs
android.util.Log.d("connectedThread", "started");
String str;
try {
inStream.read();
inStream.read();
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
android.util.Log.d("connectedThread", "normal read is fine");
while (true) {
try {
// Read from the InputStream
str = in.readLine();
byte type = Byte.valueOf(str);
android.util.Log.d("connectedThread", "read");
handler.handlePacket(in, type);
} catch (IOException e) {
break;
}
}*/
for (int i = 0; i < 20; i++) {
try {
String str = in.readLine();
android.util.Log.d("read", str + " ");
} catch (IOException e) {
// TODO Auto-generated catch block
android.util.Log.d("io exception", e.getMessage() + " " + e.getLocalizedMessage() + " " + e.getCause());
}
}
while (true) {
}
}
/* Call this from the main Activity to shutdown the connection */
public void cancel() {
try {
socket.close();
} catch (IOException e) { }
}
}
public class ConnectedWriteThread extends Thread {
public ConcurrentLinkedQueue<String> que;
private final BluetoothSocket socket;
private final OutputStream outStream;
private final BufferedWriter out;
private PacketHandler handler;
private boolean isServ;
public ConnectedWriteThread(BluetoothSocket soc, PacketHandler pHandler, boolean isServer) {
socket = soc;
handler = pHandler;
isServ = isServer;
OutputStream tmpOut = null;
que = new ConcurrentLinkedQueue<String>();
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
outStream = tmpOut;
out = new BufferedWriter(new OutputStreamWriter(outStream));
}
public void run() {
// Keep listening to the InputStream until an exception occurs
android.util.Log.d("connectedThread", "started");
/*
try {
if (isServ) {
out.write(String.valueOf(EngineConstants.PACKET_SYNC) + '\n');
out.write(String.valueOf(0) + '\n');
}
} catch (IOException e1) {
android.util.Log.d("connectedThread", "io exception " + e1.getMessage() + " " + e1.getLocalizedMessage() + " " + e1.getCause());
}
//android.util.Log.d("connectedThread", "sent initial packet");
while (true) {
if (!que.isEmpty()) {
try {
out.write(que.poll());
out.flush();
// android.util.Log.d("connectedThread", "sent packet");
} catch (IOException e) {
android.util.Log.d("write thread", "io exception " + e.getMessage());
}
}
}*/
try {
outStream.write(3);
out.write("343567\n");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
while (true) {
}
}
public void fillQueue() {
// android.util.Log.d("fillQueue", "in method");
handler.queuePacket(que);
}
/* Call this from the main Activity to send data to the remote device */
public void write(String str) {
try {
out.write(str);
} catch (IOException e) { }
}
/* Call this from the main Activity to shutdown the connection */
public void cancel() {
try {
socket.close();
} catch (IOException e) { }
}
}
Try to use reflection:
try {
BluetoothDevice mDevice = mBluetoothAdapter.getRemoteDevice("MAC of remote device");
Method m = mDevice.getClass().getMethod("createRfcommSocket",
new Class[] { int.class });
mSocket = (BluetoothSocket) m.invoke(mDevice, Integer.valueOf(1));
mSocket.connect();
} catch (NoSuchMethodException e) {
} catch (SecurityException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
} catch (InvocationTargetException e) {
} catch (Exception e) {}
And after some time in your thread
mInStream = mSocket.getInputStream();
mOutStream = mSocket.getOutputStream();
mInStream is InputStream() and mOutStream is OutputStream().
I came across this problem when used bluetooth connection on HTC device.