List all installed apps

Posted by on May 19, 2011 in Android | 1 comment

List all installed apps

This tutorial will show you how to retrieve all currently installed apps on your phone as well as to start them. We will keep the GUI very simple: our main activity will only contain a list where each row contains the name of an installed app. By clicking on the row the respective app is started.

The layout

As I mentioned, the GUI will be fairly simple. We will only need to define a layout file for our main activity and one for each entry of the app list.

The main activity simply contains a list which spans the entire screen:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="vertical"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
    <ListView android:id="@+id/appslist"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content" />
</LinearLayout>

The layout for a row of that list is equally simple: we will only display a textview which will hold the app’s name:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
  <TextView
    android:id="@+id/apptitle"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="20dip"
    android:layout_gravity="center_vertical" />
</LinearLayout>

The code

We will first create a simple Java bean which will hold the interesting attributes of an app. It merely consists of a few fields and respective getters and setters:

public class App {

  private String title;
  private String packageName;
  private String versionName;
  private int versionCode;

  // ...getters and setters omitted...
}

Next up is a custom list adapter which we will use to render our list of apps. It will hold a reference to the list of App beans that it is displaying. Don’t worry about the ViewHolder class too much; it is only used to reuse views and speed things up.

public class AppListAdapter extends BaseAdapter {

  private LayoutInflater mInflater;
  private List<App> mApps;

  public AppListAdapter(Context context) {
     // cache the LayoutInflater to avoid asking for a new one each time
     mInflater = LayoutInflater.from(context);
  }

  @Override
  public int getCount() {
    return mApps.size();
  }

  @Override
  public Object getItem(int position) {
    return mApps.get(position);
  }

  @Override
  public long getItemId(int position) {
    return position;
  }

  @Override
  public View getView(int pos, View convertView, ViewGroup parent) {

    AppViewHolder holder;
    if (convertView == null) {
      convertView = mInflater.inflate(R.layout.row, null);

      // creates a ViewHolder and stores a reference to the child view
      holder = new AppViewHolder();
      holder.mTitle = (TextView) convertView.findViewById(R.id.apptitle);
      convertView.setTag(holder);
    } else {
      // reuse/overwrite the view passed assuming(!) that it is castable!
      holder = (AppViewHolder) convertView.getTag();
    }
    holder.setTitle(mApps.get(pos).getTitle());

    return convertView;
  }

  public void setListItems(List<App> list) {
    mApps = list;
  }

  /**
   * A view holder which is used to reuse views inside a list.
   */
  public class AppViewHolder {

    private TextView mTitle;

    /**
     * Sets the text to be shown as the app's title
     *
     * @param title the text to be shown inside the list row
     */
     public void setTitle(String title) {
       mTitle.setText(title);
     }
  }
}

So far, so easy. Now comes the most interesting class: our main activity which handles the retrieval of the installed apps as well as the start of an app when it’s title is being pressed in the list.

public class ListInstalledApps extends Activity
implements OnItemClickListener {

  /** whether or not to include system apps */
  private static final boolean INCLUDE_SYSTEM_APPS = true;

  private ListView mAppsList;
  private List<App> mApps;

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

    mAppsList = (ListView) findViewById(R.id.appslist);
    mAppsList.setOnItemClickListener(this);

    mApps = loadInstalledApps(INCLUDE_SYSTEM_APPS);

    AppListAdapter adapter = new AppListAdapter(getApplicationContext());
    adapter.setListItems(mApps);
    mAppsList.setAdapter(adapter);
  }

  @Override
  public void onItemClick(AdapterView<?> p, View v, int pos, long id) {
    // start the app by invoking its launch intent
    App app = (App) parent.getItemAtPosition(position);
    Intent i = getPackageManager().getLaunchIntentForPackage(
      app.getPackageName());
    try {
      if (i != null) {
        startActivity(i);
      } else {
        i = new Intent(app.getPackageName());
        startActivity(i);
      }
    } catch (ActivityNotFoundException err) {
      Toast.makeText(ListInstalledApps.this, "Error launching app",
        Toast.LENGTH_SHORT).show();
    }
  }

  /**
   * Uses the package manager to query for all currently installed apps
   * which are put into beans and returned in form of a list.
   *
   * @param includeSysApps whether or not to include system apps
   * @return a list containing {@code App} beans
   */
  private List<App> loadInstalledApps(boolean includeSysApps) {
    List<App> apps = new ArrayList<App>();

    // the PackageManager contains information about installed apps
    PackageManager packageManager = getPackageManager();

    List<PackageInfo> pgs = packageManager.getInstalledPackages(0);

    for(int i=0; i < pgs.size(); i++) {
      PackageInfo p = pgs.get(i);
      ApplicationInfo a = p.applicationInfo;
      // skip system apps if they shall not be included
      if ((!includeSysApps) &&
         ((a.flags & ApplicationInfo.FLAG_SYSTEM) == 1)) {
        continue;
      }
      App app = new App();
      app.setTitle(p.applicationInfo.loadLabel(packageManager)
        .toString());
      app.setPackageName(p.packageName);
      app.setVersionName(p.versionName);
      app.setVersionCode(p.versionCode);
      apps.add(app);
    }
    return apps;
  }
}

The code contains two interesting blocks. The first one is the final block which starts at line 45. It displays the usage of the PackageManager in order to retrieve the installed packages. I then create a new instance of an App bean and store the most interesting information about each installed package.

The other interesting block starts at line 25 and contains the code that is necessary to launch a selected app. It uses the application’s package name to find its launch intent. If that intent can be retrieved it is executed. Note that our activity is implementing the OnItemClickListener and sets the listener on the list view on line 16.

That is all the magic. Thanks to the PackageManager class it is very easy to retrieve the list of installed apps on a phone!

The result

The following screenshot shows how this app looks like on my emulator:

As always you can download the source code to this tutorial:

DownloadDownload now.zip (55.7 KB)

In a future tutorial I will show you how to add the application’s icon as well as version information to the list.

One Comment

  1. Hello i know this thread is old but i got an “unknow method ‘getTitle’ error” when i try to edit this code on my eeepad transformer with AIDE

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>