Tuesday, December 21, 2010

Detecting is home(launcher) screen showing

While developing widgets for android, especially the clock widget which should updates each second, determining whether the home screen is on top is important to save for batteries and CPU power. After quite some time of research, following is the method I could find to do this:

 public boolean HomeIsShowing(){
  Intent intent = new Intent(Intent.ACTION_MAIN);
  intent.addCategory(Intent.CATEGORY_HOME);
  ArrayList homeList = new ArrayList();
  for(ResolveInfo info : this.getPackageManager().queryIntentActivities(intent, 0)){
   homeList.add(info.activityInfo.packageName);
  }
  
  ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
        for (RunningTaskInfo t : am.getRunningTasks(1)) {
            if (t != null && t.numRunning > 0) {
                ComponentName cn = t.baseActivity;
                if (cn == null)
                 continue;
                else
                 if (homeList.contains(cn.getPackageName())) return true;
            }
        }
        return false;
 }

Tested on my HTC Desire, it tooks about 5000ms to run 1000 iteration of the above query: that's about 5ms each time, it's quite heavy since it is querying all the applications installed (maybe?) so you probably won't use this too often.

7 comments:

  1. Generellay the first iteration is the heaviest, maybe android is caching all the subsequent queries to the applications?

    anyway it's really a great find, thank you for the code!

    ReplyDelete
  2. How expensive is this method? Could it be that it costs more than doing the widget update anyway?

    ReplyDelete
    Replies
    1. Idea: this seems cacheable, and then subscribe to install/uninstall/enable/disable broadcasts as that's the only thing that could change the package list?

      Delete
  3. getRunningTasks(1) is deprecated, is there any other option?

    ReplyDelete
    Replies
    1. The deprecation note says:

      For backwards compatibility, it will still return a small subset of its data: at least the caller's own tasks, and possibly some other tasks such as home that are known to not be sensitive.

      https://developer.android.com/reference/android/app/ActivityManager#getRunningTasks(int)

      Which is exactly what we need here :)

      Delete
  4. Does this still work with Android 11's changes?

    https://medium.com/androiddevelopers/package-visibility-in-android-11-cc857f221cd9

    ReplyDelete