Pages

Saturday, July 13, 2013

Add missing Android Activity tools

One major issue with Android, is that Google have never implemented a proper way of detecting which Activity is currently in the foreground and which are behind. If you open multiple Activities in an application, and then flip the screen, all the callbacks (onCreate(), onResume() etc) will be invoked in all your Activities. The problem is that you might have some code in some of these Activities that you do not wish to have executed, unless the Activity holding that code, is currently placed in the foreground. Problem is that you can't check this state of an Activity. At least not in a proper way.

public Boolean isForeground() {
    ActivityManager am = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    ComponentName cn = am.getRunningTasks(1).get(0).topActivity;
}

There is the possibility to use something like the above. There is just two issues regarding this. For one, google states that getSystemService(Context.ACTIVITY_SERVICE) is only intended for debugging and presenting task management user interfaces, and that it should never be used for core logic in an application. Second, you need to have android.permission.GET_TASKS added to the application in order to use this, which is not ideal for a simple task like this.

So what we can do instead, is extending the Activity class with a custom one which includes this missing feature and then extend our application Activities with our custom one instead.

public class ExtendedActivity extends Activity {
 
 private final static ArrayList mActivities = new ArrayList();
 
 private final static Object oLock = new Object();
 
 private Boolean mReCreate = false;
 
 @Override
 public void onSaveInstanceState(Bundle savedInstanceState) {
  savedInstanceState.putBoolean("mReCreate", true);

  super.onSaveInstanceState(savedInstanceState);
 }
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  
  if (savedInstanceState != null) {
   mReCreate = savedInstanceState.getBoolean("mReCreate");
  }
  
  synchronized (oLock) {
   mActivities.add( (mReCreate ? mActivities.size() : 0), this.getClass().getName());
  }
 }
 
 @Override
 protected void onDestroy() {
  super.onDestroy();
  
  synchronized (oLock) {
   mActivities.remove(this.getClass().getName());
  }
 }
 
 public final Boolean isForeground() {
  synchronized (oLock) {
   return mActivities.size() == 0 || mActivities.get(0).equals(this.getClass().getName());
  }
 }
}

What this does, it keep track of all active Activities and in which order they where opened. We only need to extend all of our Activities using this one, and then we can use isForeground() to check the state of an Activity Object.

public class MyActivity extends ExtendedActivity {

 @Override
 protected void onResume() {
  super.onResume();
  
  if ( isForeground() ) {
            // Do something
        }
 }
}