Android Bluetooth background listener

Sreyas picture Sreyas · Oct 16, 2013 · Viewed 11k times · Source

I am developing an android application with bluetooth chat. I have successfully implemented bluetooth chat with two phones.But my problem is that if I Change to next activity from the chatting activity the connection is lost then I am not able to send messages from second activity. How can I maintain my connection?
That is I want to stay connected through out my app. Whenever the user press on exit button then only the connection can disconnect. I want to send message from one activity and receive from another activity this is what I want. I am not able to create a background service with my code.
Can anyone help me to split my code? If I got a message from one phone then I want to process the message and I want to send back the result, that processing will be on next activity this is the working of my app.

  public class BluetoothTexting extends Activity {

  private static int DISCOVERY_REQUEST = 1;

  private Handler handler = new Handler();

  private ArrayList<BluetoothDevice> foundDevices = new ArrayList<BluetoothDevice>();
    private ArrayAdapter<BluetoothDevice> aa; 
  private ListView list;

  private BluetoothAdapter bluetooth;
  private BluetoothSocket socket;
  private UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);


    configureBluetooth();


    setupListView();    


    setupSearchButton();


    setupListenButton();
    }

     private void configureBluetooth() {
     bluetooth = BluetoothAdapter.getDefaultAdapter();
     }

      private void setupListenButton() {
      Button listenButton = (Button)findViewById(R.id.button_listen);
      listenButton.setOnClickListener(new OnClickListener() {
      public void onClick(View view) {
       Intent disc = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
      startActivityForResult(disc, DISCOVERY_REQUEST);     
     }
    });
    }

     @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
     if (requestCode == DISCOVERY_REQUEST) {
      boolean isDiscoverable = resultCode > 0;
      if (isDiscoverable) {
       String name = "bluetoothserver";
        try {
         final BluetoothServerSocket btserver = 
         bluetooth.listenUsingRfcommWithServiceRecord(name, uuid);

          AsyncTask<Integer, Void, BluetoothSocket> acceptThread = 
         new AsyncTask<Integer, Void, BluetoothSocket>() {

        @Override
        protected BluetoothSocket doInBackground(Integer... params) {
          try {
            socket = btserver.accept(params[0]*1000);
            return socket;
          } catch (IOException e) {
            Log.d("BLUETOOTH", e.getMessage());            
          }
          return null;
        }

        @Override
        protected void onPostExecute(BluetoothSocket result) {
          if (result != null)
            switchUI();
        }            
      };          
      acceptThread.execute(resultCode);
    } catch (IOException e) {
      Log.d("BLUETOOTH", e.getMessage());            
    }
  }
}
}

      private void setupListView() {
        aa = new ArrayAdapter<BluetoothDevice>(this, 
           android.R.layout.simple_list_item_1,
           foundDevices);
      list = (ListView)findViewById(R.id.list_discovered);    
      list.setAdapter(aa);

     list.setOnItemClickListener(new OnItemClickListener() {
      public void onItemClick(AdapterView<?> arg0, View view, 
                          int index, long arg3) {
       AsyncTask<Integer, Void, Void> connectTask = 
       new AsyncTask<Integer, Void, Void>() { 
        @Override
        protected Void doInBackground(Integer... params) {
          try {
            BluetoothDevice device = foundDevices.get(params[0]);
            socket = device.createRfcommSocketToServiceRecord(uuid);
            socket.connect();              
          } catch (IOException e) {
            Log.d("BLUETOOTH_CLIENT", e.getMessage());
          }
          return null;
        }

        @Override
        protected void onPostExecute(Void result) {
          switchUI();
        }
      };
    connectTask.execute(index);
  }      
});
}

        private void setupSearchButton() {
        Button searchButton = (Button)findViewById(R.id.button_search);

         searchButton.setOnClickListener(new OnClickListener() {
         public void onClick(View view) {
         registerReceiver(discoveryResult, 
                     new IntentFilter(BluetoothDevice.ACTION_FOUND));

    if (!bluetooth.isDiscovering()) {
      foundDevices.clear();
      bluetooth.startDiscovery();
    }
  }
});
}

   private void switchUI() {    
   final TextView messageText = (TextView)findViewById(R.id.text_messages);
   final EditText textEntry = (EditText)findViewById(R.id.text_message);
   final Button btnSend = (Button)findViewById(R.id.send); 

   messageText.setVisibility(View.VISIBLE);
   list.setVisibility(View.GONE);
  textEntry.setEnabled(true);
    btnSend.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {

        if(textEntry.getText().length()>0)
        {
             sendMessage(socket, textEntry.getText().toString());   

        }
        else
        {
             sendMessage(socket, "Test_String");    
        }
    }
});  
      /*textEntry.setOnKeyListener(new OnKeyListener() {
        public boolean onKey(View view, int keyCode, KeyEvent keyEvent) {
         if ((keyEvent.getAction() == KeyEvent.ACTION_DOWN) &&
        (keyCode == KeyEvent.KEYCODE_DPAD_CENTER)) {
        sendMessage(socket, textEntry.getText().toString());
         textEntry.setText("");
         return true;
         }
        return false;
  }      
});*/
       BluetoothSocketListener bsl = new BluetoothSocketListener(socket, handler,         messageText);
Thread messageListener = new Thread(bsl);
    messageListener.start();
}

    private void sendMessage(BluetoothSocket socket, String msg) {
    OutputStream outStream;
    try {
     outStream = socket.getOutputStream();
    byte[] byteString = (msg + " ").getBytes();
    byteString[byteString.length - 1] = 0;
    outStream.write(byteString);
  //  outStream.close();
   // socket.close();
  } catch (IOException e) {
    Log.d("BLUETOOTH_COMMS", e.getMessage());
  }    
  }

  BroadcastReceiver discoveryResult = new BroadcastReceiver() {
   @Override
    public void onReceive(Context context, Intent intent) {
   BluetoothDevice remoteDevice;
   remoteDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
   if (bluetooth.getBondedDevices().contains(remoteDevice)) {  
     foundDevices.add(remoteDevice);
     aa.notifyDataSetChanged();
   }
 }
 };

    private class MessagePoster implements Runnable {
     private TextView textView;
     private String message;

     public MessagePoster(TextView textView, String message) {
     this.textView = textView;
     this.message = message;
   }

    public void run() {
     textView.append("\n"+message);
    Toast.makeText(getApplicationContext(),message,Toast.LENGTH_LONG).show();
    }     
  }

      private class BluetoothSocketListener implements Runnable {

  private BluetoothSocket socket;
  private TextView textView;
  private Handler handler;

  public BluetoothSocketListener(BluetoothSocket socket, 
                                 Handler handler, TextView textView) {
    this.socket = socket;
    this.textView = textView;
    this.handler = handler;
  }

    public void run() {
    int bufferSize = 1024;
  byte[] buffer = new byte[bufferSize];      
  try {
    InputStream instream = socket.getInputStream();
    int bytesRead = -1;
    String message = "";
    while (true) {
      message = "";
      bytesRead = instream.read(buffer);
      if (bytesRead != -1) {
        while ((bytesRead==bufferSize)&&(buffer[bufferSize-1] != 0)) {
          message = message + new String(buffer, 0, bytesRead);
          bytesRead = instream.read(buffer);
        }
        message = message + new String(buffer, 0, bytesRead - 1); 

        handler.post(new MessagePoster(textView, message));              
        socket.getInputStream();

      }
    }
  } catch (IOException e) {
    Log.d("BLUETOOTH_COMMS", e.getMessage());
  } 
}
}
}

Answer

Tom picture Tom · Oct 16, 2013

I developed a similar bt-chat and i'll tell u what i did different which evantually worked:

instead of doInBackground, asyncTask and defining new runnable inside the activity i initiated and managed the connection on different threads. that way the connection stays opened.

EDIT: i added the server thread code. notice that when the server is connected it sends a broadcast so any activity could register it and receive so there is no problem in changing activities while the BT connects.

public class Server extends Thread {


    private BluetoothAdapter btAdapter;
    private String socketString = "a random string";
    private BluetoothServerSocket btServerSocket;
    private BluetoothSocket btConnectedSocket;
    private final String TAG = "Server";
    private MainActivity parent;
    /*package-protected*/ static final String ACTION = "Bluetooth socket is connected";
    private boolean connected;

    public Server(MainActivity parent) {
        this.parent = parent;
        connected= false;
    }

    @Override
    public void run() {
        btAdapter = BluetoothAdapter.getDefaultAdapter();

        try {
            Log.i(TAG, "getting socket from adapter");
            btServerSocket = btAdapter.listenUsingRfcommWithServiceRecord(socketString, MainActivity.BT_UUID);
            listen();

        }
        catch (IOException ex) {
            Log.e(TAG, "error while initializing");
        }
    }

    private void listen() {
        Log.i(TAG, "listening");
        btConnectedSocket = null;
        while (!connected) {
            try {
                btConnectedSocket = btServerSocket.accept();
            }
            catch (IOException ex) {
                Log.e(TAG,"connection failed");
                connectionFailed();
            }

            if (btConnectedSocket != null) {
                broadcast();
                closeServerSocket();
            }
            else {
                Log.i(TAG,  "socket is null");
                connectionFailed();
            }
        }

    }

    private void broadcast() {
        try {
            Log.i(TAG, "connected? "+btConnectedSocket.isConnected());
            Intent intent = new Intent();
            intent.setAction(ACTION);
            intent.putExtra("state", btConnectedSocket.isConnected());
            parent.sendBroadcast(intent); 
            connected = true;
        }
        catch (RuntimeException runTimeEx) {

        }

        closeServerSocket();
    }


    private void connectionFailed () {

    }

    public void closeServerSocket() {
        try {
            btServerSocket.close();
        }
        catch (IOException ex) {
            Log.e(TAG+":cancel", "error while closing server socket");
        }
    }
}