title: Using BluetoothChat to communicate with ELM327
body: <p>I am currently trying to communicate with an ELM327 OBDII bluetooth dongle via the BluetoothChat Sample Application. I am able to connect as I have changed the UUID, however I am only able to recieve the startup commands and the prompt ">" to send a command, whenever I try to send a command I get the following</p>
  
  <ul>
  <li>CAN OBDII:ELM327 v1.2a></li>
  <li>Me:ATRV</li>
  <li>CAN OBDII:ATRV</li>
  <li>CAN OBDII:></li>
  <li>CAN OBDII:?</li>
  </ul>
  
  <p>Now I read on here to append "\r" to the commands, however when I do this I get the exact same response. I am using the sample application "BluetoothChat" </p>
  
  <p>Main Class...</p>
  
  <pre><code>public class BluetoothChat extends Activity {
      // Debugging
      private static final String TAG = "BluetoothChat";
      private static final boolean D = true;
  
      // 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;
  
      // Key names received from the BluetoothChatService Handler
      public static final String DEVICE_NAME = "device_name";
      public static final String TOAST = "toast";
  
      // Intent request codes
      private static final int REQUEST_CONNECT_DEVICE_SECURE = 1;
      private static final int REQUEST_CONNECT_DEVICE_INSECURE = 2;
      private static final int REQUEST_ENABLE_BT = 3;
  
      // Layout Views
      private TextView mTitle;
      private ListView mConversationView;
      private EditText mOutEditText;
      private Button mSendButton;
  
      // Name of the connected device
      private String mConnectedDeviceName = null;
      // Array adapter for the conversation thread
      private ArrayAdapter&lt;String&gt; mConversationArrayAdapter;
      // String buffer for outgoing messages
      private StringBuffer mOutStringBuffer;
      // Local Bluetooth adapter
      private BluetoothAdapter mBluetoothAdapter = null;
      // Member object for the chat services
      private BluetoothChatService mChatService = null;
  
  
      @Override
      public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          if(D) Log.e(TAG, "+++ ON CREATE +++");
  
          // Set up the window layout
          requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
          setContentView(R.layout.main);
          getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title);
  
          // Set up the custom title
          mTitle = (TextView) findViewById(R.id.title_left_text);
          mTitle.setText(R.string.app_name);
          mTitle = (TextView) findViewById(R.id.title_right_text);
  
          // Get local Bluetooth adapter
          mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  
          // If the adapter is null, then Bluetooth is not supported
          if (mBluetoothAdapter == null) {
              Toast.makeText(this, "Bluetooth is not available", Toast.LENGTH_LONG).show();
              finish();
              return;
          }
      }
  
      @Override
      public void onStart() {
          super.onStart();
          if(D) Log.e(TAG, "++ ON START ++");
  
          // If BT is not on, request that it be enabled.
          // setupChat() will then be called during onActivityResult
          if (!mBluetoothAdapter.isEnabled()) {
              Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
              startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
          // Otherwise, setup the chat session
          } else {
              if (mChatService == null) setupChat();
          }
      }
  
      @Override
      public synchronized void onResume() {
          super.onResume();
          if(D) Log.e(TAG, "+ ON RESUME +");
  
          // Performing this check in onResume() covers the case in which BT was
          // not enabled during onStart(), so we were paused to enable it...
          // onResume() will be called when ACTION_REQUEST_ENABLE activity returns.
          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();
              }
          }
      }
  
      private void setupChat() {
          Log.d(TAG, "setupChat()");
  
          // Initialize the array adapter for the conversation thread
          mConversationArrayAdapter = new ArrayAdapter&lt;String&gt;(this, R.layout.message);
          mConversationView = (ListView) findViewById(R.id.in);
          mConversationView.setAdapter(mConversationArrayAdapter);
  
          // Initialize the compose field with a listener for the return key
          mOutEditText = (EditText) findViewById(R.id.edit_text_out);
          mOutEditText.setOnEditorActionListener(mWriteListener);
  
          // Initialize the send button with a listener that for click events
          mSendButton = (Button) findViewById(R.id.button_send);
          mSendButton.setOnClickListener(new OnClickListener() {
              public void onClick(View v) {
                  // Send a message using content of the edit text widget
                  TextView view = (TextView) findViewById(R.id.edit_text_out);
                  String message = view.getText().toString();
                  sendMessage(message);
              }
          });
  
          // Initialize the BluetoothChatService to perform bluetooth connections
          mChatService = new BluetoothChatService(this, mHandler);
  
          // Initialize the buffer for outgoing messages
          mOutStringBuffer = new StringBuffer("");
      }
  
      @Override
      public synchronized void onPause() {
          super.onPause();
          if(D) Log.e(TAG, "- ON PAUSE -");
      }
  
      @Override
      public void onStop() {
          super.onStop();
          if(D) Log.e(TAG, "-- ON STOP --");
      }
  
      @Override
      public void onDestroy() {
          super.onDestroy();
          // Stop the Bluetooth chat services
          if (mChatService != null) mChatService.stop();
          if(D) Log.e(TAG, "--- ON DESTROY ---");
      }
  
      private void ensureDiscoverable() {
          if(D) Log.d(TAG, "ensure discoverable");
          if (mBluetoothAdapter.getScanMode() !=
              BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
              Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
              discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
              startActivity(discoverableIntent);
          }
      }
  
      /**
       * Sends a message.
       * @param message  A string of text to send.
       */
      private void sendMessage(String message) {
          // Check that we're actually connected before trying anything
          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() &gt; 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);
              mOutEditText.setText(mOutStringBuffer);
          }
      }
  
      // The action listener for the EditText widget, to listen for the return key
      private TextView.OnEditorActionListener mWriteListener =
          new TextView.OnEditorActionListener() {
          public boolean onEditorAction(TextView view, int actionId, KeyEvent event) {
              // If the action is a key-up event on the return key, send the message
              if (actionId == EditorInfo.IME_NULL &amp;&amp; event.getAction() == KeyEvent.ACTION_UP) {
                  String message = view.getText().toString();
                  sendMessage(message);
              }
              if(D) Log.i(TAG, "END onEditorAction");
              return true;
          }
      };
  
      // 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:
                  if(D) Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
                  switch (msg.arg1) {
                  case BluetoothChatService.STATE_CONNECTED:
                      mTitle.setText(R.string.title_connected_to);
                      mTitle.append(mConnectedDeviceName);
                      mConversationArrayAdapter.clear();
                      break;
                  case BluetoothChatService.STATE_CONNECTING:
                      mTitle.setText(R.string.title_connecting);
                      break;
                  case BluetoothChatService.STATE_LISTEN:
                  case BluetoothChatService.STATE_NONE:
                      mTitle.setText(R.string.title_not_connected);
                      break;
                  }
                  break;
              case MESSAGE_WRITE:
                  Log.i(TAG, "WRITING!");
                  byte[] writeBuf = (byte[]) msg.obj;
                  // construct a string from the buffer
                  String writeMessage = new String(writeBuf);
                  mConversationArrayAdapter.add("Me:  " + writeMessage);
                  break;
              case MESSAGE_READ:
                  Log.i(TAG, "READING");
                  String readMessage = (String) msg.obj;
  
                  // construct a string from the valid bytes in the buffer
  
                  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) {
          if(D) Log.d(TAG, "onActivityResult " + resultCode);
          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_CONNECT_DEVICE_INSECURE:
              // When DeviceListActivity returns with a device to connect
              if (resultCode == Activity.RESULT_OK) {
                  connectDevice(data, false);
              }
              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 occured
                  Log.d(TAG, "BT not enabled");
                  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(DeviceListActivity.EXTRA_DEVICE_ADDRESS);
          // Get the BLuetoothDevice object
          BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
          // Attempt to connect to the device
          mChatService.connect(device, secure);
      }
  
      @Override
      public boolean onCreateOptionsMenu(Menu menu) {
          MenuInflater inflater = getMenuInflater();
          inflater.inflate(R.menu.option_menu, menu);
          return true;
      }
  
      @Override
      public boolean onOptionsItemSelected(MenuItem item) {
          Intent serverIntent = null;
          switch (item.getItemId()) {
          case R.id.secure_connect_scan:
              // Launch the DeviceListActivity to see devices and do scan
              serverIntent = new Intent(this, DeviceListActivity.class);
              startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_SECURE);
              return true;
          case R.id.insecure_connect_scan:
              // Launch the DeviceListActivity to see devices and do scan
              serverIntent = new Intent(this, DeviceListActivity.class);
              startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE_INSECURE);
              return true;
          case R.id.discoverable:
              // Ensure this device is discoverable by others
              ensureDiscoverable();
              return true;
          }
          return false;
      }
  
  }
  
  
  
  
  
  
  
  
  
  
  package com.example.android.BluetoothChat;
  
  import java.io.IOException;
  
  /**
   * This class does all the work for setting up and managing Bluetooth
   * connections with other devices. It has a thread that listens for
   * incoming connections, a thread for connecting with a device, and a
   * thread for performing data transmissions when connected.
   */
  public class BluetoothChatService {
      // Debugging
      private static final String TAG = "BluetoothChatService";
      private static final boolean D = true;
  
      // Name for the SDP record when creating server socket
      private static final String NAME_SECURE = "BluetoothChatSecure";
      private static final String NAME_INSECURE = "BluetoothChatInsecure";
  
      // Unique UUID for this application
      private static final UUID MY_UUID_SECURE =
          UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
      private static final UUID MY_UUID_INSECURE =
          UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
  
      // Member fields
      private final BluetoothAdapter mAdapter;
      private final Handler mHandler;
      private AcceptThread mSecureAcceptThread;
      private AcceptThread mInsecureAcceptThread;
      private ConnectThread mConnectThread;
      private ConnectedThread mConnectedThread;
      private int mState;
  
      // Constants that indicate the current connection state
      public static final int STATE_NONE = 0;       // we're doing nothing
      public static final int STATE_LISTEN = 1;     // now listening for incoming connections
      public static final int STATE_CONNECTING = 2; // now initiating an outgoing connection
      public static final int STATE_CONNECTED = 3;  // now connected to a remote device
  
      /**
       * Constructor. Prepares a new BluetoothChat session.
       * @param context  The UI Activity Context
       * @param handler  A Handler to send messages back to the UI Activity
       */
      public BluetoothChatService(Context context, Handler handler) {
          mAdapter = BluetoothAdapter.getDefaultAdapter();
          mState = STATE_NONE;
          mHandler = handler;
      }
  
      /**
       * Set the current state of the chat connection
       * @param state  An integer defining the current connection state
       */
      private synchronized void setState(int state) {
          if (D) Log.d(TAG, "setState() " + mState + " -&gt; " + state);
          mState = state;
  
          // Give the new state to the Handler so the UI Activity can update
          mHandler.obtainMessage(BluetoothChat.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
      }
  
      /**
       * Return the current connection state. */
      public synchronized int getState() {
          return mState;
      }
  
      /**
       * Start the chat service. Specifically start AcceptThread to begin a
       * session in listening (server) mode. Called by the Activity onResume() */
      public synchronized void start() {
          if (D) Log.d(TAG, "start");
  
          // Cancel any thread attempting to make a connection
          if (mConnectThread != null) {mConnectThread.cancel(); mConnectThread = null;}
  
          // Cancel any thread currently running a connection
          if (mConnectedThread != null) {mConnectedThread.cancel(); mConnectedThread = null;}
  
          setState(STATE_LISTEN);
  
          // Start the thread to listen on a BluetoothServerSocket
          if (mSecureAcceptThread == null) {
              mSecureAcceptThread = new AcceptThread(true);
              mSecureAcceptThread.start();
          }
          if (mInsecureAcceptThread == null) {
              mInsecureAcceptThread = new AcceptThread(false);
              mInsecureAcceptThread.start();
          }
      }
  
      /**
       * Start the ConnectThread to initiate a connection to a remote device.
       * @param device  The BluetoothDevice to connect
       * @param secure Socket Security type - Secure (true) , Insecure (false)
       */
      public synchronized void connect(BluetoothDevice device, boolean secure) {
          if (D) Log.d(TAG, "connect to: " + device);
  
          // Cancel any thread attempting to make a connection
          if (mState == 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, secure);
          mConnectThread.start();
          setState(STATE_CONNECTING);
      }
  
      /**
       * Start the ConnectedThread to begin managing a Bluetooth connection
       * @param socket  The BluetoothSocket on which the connection was made
       * @param device  The BluetoothDevice that has been connected
       */
      public synchronized void connected(BluetoothSocket socket, BluetoothDevice
              device, final String socketType) {
          if (D) Log.d(TAG, "connected, Socket Type:" + socketType);
  
          // 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;}
  
          // Cancel the accept thread because we only want to connect to one device
          if (mSecureAcceptThread != null) {
              mSecureAcceptThread.cancel();
              mSecureAcceptThread = null;
          }
          if (mInsecureAcceptThread != null) {
              mInsecureAcceptThread.cancel();
              mInsecureAcceptThread = null;
          }
  
          // Start the thread to manage the connection and perform transmissions
          mConnectedThread = new ConnectedThread(socket, socketType);
          mConnectedThread.start();
  
          // Send the name of the connected device back to the UI Activity
          Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_DEVICE_NAME);
          Bundle bundle = new Bundle();
          bundle.putString(BluetoothChat.DEVICE_NAME, device.getName());
          msg.setData(bundle);
          mHandler.sendMessage(msg);
  
          setState(STATE_CONNECTED);
      }
  
      /**
       * Stop all threads
       */
      public synchronized void stop() {
          if (D) Log.d(TAG, "stop");
  
          if (mConnectThread != null) {
              mConnectThread.cancel();
              mConnectThread = null;
          }
  
          if (mConnectedThread != null) {
              mConnectedThread.cancel();
              mConnectedThread = null;
          }
  
          if (mSecureAcceptThread != null) {
              mSecureAcceptThread.cancel();
              mSecureAcceptThread = null;
          }
  
          if (mInsecureAcceptThread != null) {
              mInsecureAcceptThread.cancel();
              mInsecureAcceptThread = null;
          }
          setState(STATE_NONE);
      }
  
      /**
       * Write to the ConnectedThread in an unsynchronized manner
       * @param out The bytes to write
       * @see ConnectedThread#write(byte[])
       */
      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);
      }
  
      /**
       * Indicate that the connection attempt failed and notify the UI Activity.
       */
      private void connectionFailed() {
          // Send a failure message back to the Activity
          Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
          Bundle bundle = new Bundle();
          bundle.putString(BluetoothChat.TOAST, "Unable to connect device");
          msg.setData(bundle);
          mHandler.sendMessage(msg);
  
          // Start the service over to restart listening mode
          BluetoothChatService.this.start();
      }
  
      /**
       * Indicate that the connection was lost and notify the UI Activity.
       */
      private void connectionLost() {
          // Send a failure message back to the Activity
          Message msg = mHandler.obtainMessage(BluetoothChat.MESSAGE_TOAST);
          Bundle bundle = new Bundle();
          bundle.putString(BluetoothChat.TOAST, "Device connection was lost");
          msg.setData(bundle);
          mHandler.sendMessage(msg);
  
          // Start the service over to restart listening mode
          BluetoothChatService.this.start();
      }
  
      /**
       * This thread runs while listening for incoming connections. It behaves
       * like a server-side client. It runs until a connection is accepted
       * (or until cancelled).
       */
      private class AcceptThread extends Thread {
          // The local server socket
          private final BluetoothServerSocket mmServerSocket;
          private String mSocketType;
  
          public AcceptThread(boolean secure) {
              BluetoothServerSocket tmp = null;
              mSocketType = secure ? "Secure":"Insecure";
  
              // Create a new listening server socket
              try {
                  if (secure) {
                      tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME_SECURE,
                          MY_UUID_SECURE);
                  } else {
                      tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord(
                              NAME_INSECURE, MY_UUID_INSECURE);
                  }
              } catch (IOException e) {
                  Log.e(TAG, "Socket Type: " + mSocketType + "listen() failed", e);
              }
              mmServerSocket = tmp;
          }
  
          public void run() {
              if (D) Log.d(TAG, "Socket Type: " + mSocketType +
                      "BEGIN mAcceptThread" + this);
              setName("AcceptThread" + mSocketType);
  
              BluetoothSocket socket = null;
  
              // Listen to the server socket if we're not connected
              while (mState != STATE_CONNECTED) {
                  try {
                      // This is a blocking call and will only return on a
                      // successful connection or an exception
                      socket = mmServerSocket.accept();
                  } catch (IOException e) {
                      Log.e(TAG, "Socket Type: " + mSocketType + "accept() failed", e);
                      break;
                  }
  
                  // If a connection was accepted
                  if (socket != null) {
                      synchronized (BluetoothChatService.this) {
                          switch (mState) {
                          case STATE_LISTEN:
                          case STATE_CONNECTING:
                              // Situation normal. Start the connected thread.
                              connected(socket, socket.getRemoteDevice(),
                                      mSocketType);
                              break;
                          case STATE_NONE:
                          case STATE_CONNECTED:
                              // Either not ready or already connected. Terminate new socket.
                              try {
                                  socket.close();
                              } catch (IOException e) {
                                  Log.e(TAG, "Could not close unwanted socket", e);
                              }
                              break;
                          }
                      }
                  }
              }
              if (D) Log.i(TAG, "END mAcceptThread, socket Type: " + mSocketType);
  
          }
  
          public void cancel() {
              if (D) Log.d(TAG, "Socket Type" + mSocketType + "cancel " + this);
              try {
                  mmServerSocket.close();
              } catch (IOException e) {
                  Log.e(TAG, "Socket Type" + mSocketType + "close() of server failed", e);
              }
          }
      }
  
  
      /**
       * This thread runs while attempting to make an outgoing connection
       * with a device. It runs straight through; the connection either
       * succeeds or fails.
       */
      private class ConnectThread extends Thread {
          private final BluetoothSocket mmSocket;
          private final BluetoothDevice mmDevice;
          private String mSocketType;
  
          public ConnectThread(BluetoothDevice device, boolean secure) {
              mmDevice = device;
              BluetoothSocket tmp = null;
              mSocketType = secure ? "Secure" : "Insecure";
  
              // Get a BluetoothSocket for a connection with the
              // given BluetoothDevice
              try {
                  if (secure) {
                      tmp = device.createRfcommSocketToServiceRecord(
                              MY_UUID_SECURE);
                  } else {
                      tmp = device.createInsecureRfcommSocketToServiceRecord(
                              MY_UUID_INSECURE);
                  }
              } catch (IOException e) {
                  Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
              }
              mmSocket = tmp;
          }
  
          public void run() {
              Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
              setName("ConnectThread" + mSocketType);
  
              // 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
                  try {
                      mmSocket
  </code></pre>