title: Android BluetoothSocket immediately disconnects after connecting
body: <p>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?</p>
  
  <p>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.</p>
  
  <pre><code>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) { }
      }
  }
  </code></pre>
  
  <hr>
  
  <pre><code>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) { }
      }
  }
  </code></pre>
  
  <p>}</p>
  
  <hr>
  
  <pre><code>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 &lt; 0) {
          score(true);
      } else if (puck.pos.y &gt; EngineConstants.VIRTUAL_H) {
          score(false);
      }
  
      packetTime += interval;
      if (packetTime &gt; 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 &lt; MIN_X) {
                  moveToX = MIN_X;
              } else if (moveToX &gt; 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;
  }
  </code></pre>
  
  <hr>
  
  <pre><code>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 &lt; 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) { }
  }
  </code></pre>
  
  <p>}</p>
  
  <hr>
  
  <pre><code>public class ConnectedWriteThread extends Thread {
  public ConcurrentLinkedQueue&lt;String&gt; 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&lt;String&gt;();
  
      // 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) { }
  }
  </code></pre>
  
  <p>}</p>