title: How can I bind my Activity to my currently running Service in Android?
body: <p>I have an activity which I want to use to display data sent from my service. The activity updates a textview every time the service sends a message to the activity. The user is capable of starting and stopping the service using buttons from the activity (The service is started/stopped explicitly by the user). At the moment my activity binds to the service in onResume() and unbinds in onDestroy() which seems to be working for the moment.</p>
  
  <p>The problem occurs when I start the service, press the back button, and then attempt to focus the activity again. I'm confronted with a new activity which is not being updated by the service, but appears to be able to send messages to the service (I've noticed this from Logs in my handlers [Boy that phrase made me laugh!]). I ideally want only one instance of my activity to exist and remain bound to the service, but I definitely don't want to see an activity not keeping up with updates. I've updated my manifest with <code>&lt;activity android:launchMode="singleTop"&gt;</code>, but I'm not sure that helps the matter much. What can I do to ensure my activity rebinds to the existing instance of the service when it's later resumed? (I want to achieve this with message passing, I don't want to implement a database or use sharedprefereces for this bit). I'm including my code below- I'm relatively new to services, so go easy on me. Cheers.</p>
  
  <p>Optional Extra:
  I am aiming towards a service which runs continuously from startService(), and where  refocussing the activity is optional, but will immediately show the latest information from the service. I believe what I'm looking for is a foreground service. This is not part of the question, but please let me know if you think your answer may prevent me from achieving this.</p>
  
  <p>MainActivity.java:</p>
  
  <pre><code>public class MainActivity extends Activity 
  {
      private static final String debug = "MainActivity";
      private boolean bound = false;
      TextView mTextView;
      protected Messenger outMessenger;
  
      @Override
      public void onCreate(Bundle savedInstanceState) 
      {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          Log.i(debug, "onCreate called");
          mTextView = (TextView) findViewById(R.id.textView1);
  
          Button bind = (Button) findViewById(R.id.bind);
          Button unbind = (Button) findViewById(R.id.unbind);
  
          bind.setOnClickListener(new OnClickListener()
          {
              public void onClick(View v) 
              {
                  Message message = new Message();
                  Bundle bundle = new Bundle();
                  bundle.putString("ACTION", "START");
                  message.setData(bundle);
                  try
                  {
                      outMessenger.send(message);
                  } catch (RemoteException e)
                  {
                      Log.d(debug, "She can't reach the service captain!");
                  }
              }
          });
  
          unbind.setOnClickListener(new OnClickListener()
          {
              public void onClick(View v) 
              {
                  Message message = new Message();
                  Bundle bundle = new Bundle();
                  bundle.putString("ACTION", "STOP");
                  message.setData(bundle);
                  try
                  {
                      outMessenger.send(message);
                  } catch (RemoteException e)
                  {
                      Log.d(debug, "She can't reach the service captain!");
                  }
              }
          });
      }
  
      @Override 
      public void onPause()
      {
          super.onPause();
      }
  
      @Override
      public void onResume()
      {
          super.onResume();
          doBindService();
      }
  
      public void onDestroy()
      {
          super.onDestroy();
          Log.i(debug, "onDestroy Called");
          doUnbindService();
      }
  
      private void doBindService()
      {
          Log.i(debug, "Attempting to bind");
          bound = true;
          Intent i = new Intent(this, MyService.class);
          i.putExtra("MESSENGER", new Messenger(mHandler));
          bindService(i, mConnection, Context.BIND_AUTO_CREATE);
      }
  
      private void doUnbindService()
      {
          Log.i(debug, "Attempting to unbind");
          if (bound)
          {
              bound = false;
              unbindService(mConnection);
          }
      }
  
      private Handler mHandler = new Handler()
      {
          public void handleMessage(Message message)
          {
              Log.d(debug, "Got a message!");
              Bundle data = message.getData();
              if (data != null)
              {
                  Log.i(debug, "This data ain't null!");
                  if (data.containsKey("MESSAGE"))
                  {
                      mTextView.setText(data.getString("MESSAGE"));
                  }
              }
          }
      };
  
      private ServiceConnection mConnection = new ServiceConnection() 
      {
          public void onServiceConnected(ComponentName className, IBinder binder) 
          {
              Log.i(debug, "Service connected!");
              outMessenger = new Messenger(binder);
          }
  
          @Override
          public void onServiceDisconnected(ComponentName className) 
          {
              Log.d(debug, "Service Disconnected!");
          }
      };
  }
  </code></pre>
  
  <p>MyService.java</p>
  
  <pre><code>public class MyService extends Service
  {
      private static final String debug = "MyService";
      private Messenger inMessenger = new Messenger(new IncomingHandler());
      Messenger outMessenger;
      private boolean bound = false;
      int secret = 0;
  
      @Override
      public void onCreate()
      {
          Log.d(debug , "MyService Created");
      }
  
      @Override
      public int onStartCommand(Intent intent, int flags, int startId) 
      {
          Log.d(debug , "onStartCommand called");
          handleCommand(intent);
          return START_STICKY;
      }
  
      Handler handler = new Handler();
      public boolean running;
      void handleCommand(Intent i)
      {
          Runnable r = new Runnable()
          {
              public void run()
              {
                  updateResultsInUi();
                  if (running)
                  {
                      handler.postDelayed(this, 500);
                  }
              }
          };
          r.run();
      }
  
      void updateResultsInUi()
      {
          Bundle bundle = new Bundle();
          bundle.putString("MESSAGE", 
                  Integer.toString(secret = ++secret % 10));
          Message message = new Message();
          message.setData(bundle);
  
          if (bound)
          {
              try
              {
                  outMessenger.send(message);
              } 
              catch (RemoteException e)
              {
                  Log.d(debug, "Messaging failed");
              }
          } 
          else 
          {
              Log.d(debug, "Not connected, so not messaging!");
          }
  
      }
  
      @Override
      public IBinder onBind(Intent intent)
      {
          Log.i(debug, "Bound");
          bound = true;
          Bundle extras = intent.getExtras();
          outMessenger = (Messenger) extras.get("MESSENGER");
          return inMessenger.getBinder();
      }
  
      @Override
      public void onRebind(Intent i)
      {
          bound = true;
          Bundle extras = i.getExtras();
          outMessenger = (Messenger) extras.get("MESSENGER");
      }
  
      @Override
      public boolean onUnbind(Intent i)
      {
          Log.d(debug, "onUnbind() called.");
          bound = false;
          outMessenger = null;
          return true;
      }
  
      class IncomingHandler extends Handler 
      {
          @Override
          public void handleMessage(Message msg) 
          {
              Log.d(debug, "Got message");
              Bundle data = msg.getData();
              if (data.containsKey("ACTION"))
              {
                  if ("START".equals(data.getString("ACTION")))
                  {
                      if (!running)
                      {
                          running = true;
                          Intent i = new Intent(getApplicationContext(), MyService.class);
                          startService(i);
                      } 
                      else 
                      {
                          Log.d(debug, "We're already up and running!");
                      }
                  } 
                  else if ("STOP".equals(data.getString("ACTION")))
                  {
                      running = false;
                      Intent i = new Intent(getApplicationContext(), MyService.class);
                      stopService(i);
                  }
              }
          }
      }
  }
  </code></pre>
  
  <p>AndroidManifest.xml</p>
  
  <pre><code>&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.tests.servicetest"
      android:versionCode="1"
      android:versionName="1.0" &gt;
      &lt;uses-sdk
          android:minSdkVersion="8"
          android:targetSdkVersion="15" /&gt;
      &lt;application
          android:icon="@drawable/ic_launcher"
          android:label="@string/app_name"
          android:theme="@style/AppTheme" &gt;
          &lt;activity
              android:name="com.tests.servicetest.MainActivity"
              android:label="@string/title_activity_main" 
              android:launchMode="singleTop" &gt;
              &lt;intent-filter&gt;
                  &lt;action android:name="android.intent.action.MAIN" /&gt;
                  &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
              &lt;/intent-filter&gt;
          &lt;/activity&gt;
          &lt;service
              android:name="com.tests.servicetest.MyService"
              android:process=":inaneService"&gt;
          &lt;/service&gt;
      &lt;/application&gt;
  &lt;/manifest&gt;
  </code></pre>
  
  <p>And for those of you who want to run it, activity_main.xml</p>
  
  <pre><code>&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
      xmlns:tools="http://schemas.android.com/tools"
      android:layout_width="match_parent"
      android:layout_height="match_parent" &gt;
  
      &lt;TextView
          android:id="@+id/textView1"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_centerHorizontal="true"
          android:layout_centerVertical="true"
          android:padding="@dimen/padding_medium"
          android:text="@string/hello_world"
          tools:context=".MainActivity" /&gt;
  
      &lt;Button
          android:id="@+id/bind"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_alignLeft="@+id/textView1"
          android:layout_below="@+id/textView1"
          android:text="Start" /&gt;
  
      &lt;Button
          android:id="@+id/unbind"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_alignLeft="@+id/textView1"
          android:layout_below="@+id/bind"
          android:text="Stop" /&gt;
  
  &lt;/RelativeLayout&gt;
  </code></pre>