List all installed apps in style

Posted by on May 22, 2011 in Android | 8 comments

List all installed apps in style

In the previous tutorial List all installed apps I showed you how to list the apps that are currently installed on the phone. The displayed information was rather sparse: we showed the title of the app and started it upon clicking on it.

In this tutorial we will enhance the demo program by adding an application icon next to each title and also display some information about the app when clicking on it. The user can then choose to start the app or return to the list.

Layout changes

We will only adapt the layout of a row in the list by adding an ImageView next to the TextView which holds the app’s title. Since we will need to update the image programmatically we assign an id to it.

<?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">
  <ImageView
    android:id="@+id/appicon"
    android:scaleType="fitCenter"
    android:layout_width="40dp"
    android:layout_height="40dp"
    android:layout_marginRight="6dip"
    android:layout_marginLeft="2dip"
    android:layout_marginTop="2dip"
    android:layout_marginBottom="2dip"
    android:src="@drawable/icon"
    android:layout_gravity="center_vertical" />
  <TextView
    android:id="@+id/apptitle"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:textSize="20dip"
    android:layout_gravity="center_vertical" />
</LinearLayout>

Code adaptations

We will first need to modify our custom list adpater class AppListAdapter. The class will get a map containing the app’s package names mapped to the respective icon images. We also need to provide a getter and setter for this field. We will also add a default image which is shown before the icons are loaded and when no icon could be found for a particular app.

Last but not least we will update our ViewHolder object to also hold an ImageView for the current row. This view is retrieved through the id we gave it in the layout earlier. The icon will be taken from the map that we just defined.

public class AppListAdapter extends BaseAdapter {
  // ...

  // a map which maps the package name of an app to its icon drawable
  private Map<String, Drawable> mIcons;
  // default icon for each app until the actual icon is loaded
  private Drawable mStdImg;

  /**
   * Constructor.
   *
   * @param context the application context for the layout inflater
   */
  public AppListAdapter(Context context) {
    // ...

    // set the default icon until the actual icon is loaded for an app
    mStdImg = context.getResources().getDrawable(R.drawable.icon);
  } 

  // ...

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

    AppViewHolder holder;
    if (convertView == null) {
      convertView = mInflater.inflate(R.layout.row, null);
      holder = new AppViewHolder();
      holder.mTitle = (TextView) convertView.findViewById(R.id.apptitle);
      holder.mIcon = (ImageView) convertView.findViewById(R.id.appicon);
      convertView.setTag(holder);
    } else {
      holder = (AppViewHolder) convertView.getTag();
    }

    App app = mApps.get(position);

    holder.setTitle(app.getTitle());
    if (mIcons == null || mIcons.get(app.getPackageName()) == null) {
      holder.setIcon(mStdImg);
    } else {
      holder.setIcon(mIcons.get(app.getPackageName()));
    }

    return convertView;
  }

  // ...

  /**
    * Sets the map containing the icons for each displayed app.
    *
    * @param icons the map which maps the app's package name to its icon
    */
  public void setIcons(Map<String, Drawable> icons) {
    this.mIcons = icons;
  }

  /**
   * Returns the map containing the icons for each displayed app.
   *
   * @return a map with a mapping of package names to icon drawables
   */
  public Map<String, Drawable> getIcons() {
    return mIcons;
  }

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

    // ...

    private ImageView mIcon;

    // ...

    /**
     * Sets the icon to be shown next to the app's title
     *
     * @param img the icon drawable to be displayed
     */
    public void setIcon(Drawable img) {
      if (img != null) {
        mIcon.setImageDrawable(img);
      }
    }
  }
}

Please refer to the first tutorial for the parts of the code which are left out for brevity.

Using an asynchroneous task to load the icons

Since it can take quite a while to load all the icon images for all installed applications and we don’t want our app to be unresonsive I decided to first display the list of installed apps and then load the images asynchroneously. This is done using an AsyncTask which makes multi-threading really easy. All you have to do is create a class which extends AsyncTask and override its doInBackground(...) method to perform all the work there is to do and which should not happen on the UI thread as it would block the process of painting the elements on the screen.

Once we are finished loading the images, we signalize that the dataset of the list has changed. This is done in the onPostExecute(...) method:

private class LoadIconsTask extends AsyncTask<App, Void, Void> {
  @Override
  protected Void doInBackground(App... apps) {

    Map<String, Drawable> icons = new HashMap<String, Drawable>();
    PackageManager manager = getApplicationContext().getPackageManager();

    for (App app : apps) {
      String pkgName = app.getPackageName();
      Drawable ico = null;
      try {
        Intent i = manager.getLaunchIntentForPackage(pkgName);
        if (i != null) {
          ico = manager.getActivityIcon(i);
        }
      } catch (NameNotFoundException e) {
        Log.e("ERROR", "Unable to find icon for package '" + pkgName);
      }
      icons.put(app.getPackageName(), ico);
    }
    mAdapter.setIcons(icons);

    return null;
  }

  @Override
  protected void onPostExecute(Void result) {
    mAdapter.notifyDataSetChanged();
  }
}

Showing additional information about the selected app

Finally, we will extend our original demo program by showing an informative dialog whenever an entry is selected in the list. We offer the user the possibility to launch the selected app or abort and get back to the app list.

@Override
public void onItemClick(AdapterView<?> p, View view, int pos, long id) {

  final App app = (App) parent.getItemAtPosition(pos);
  String pkg = app.getPackageName();

  AlertDialog.Builder builder = new AlertDialog.Builder(this);

  String msg = app.getTitle() + "\n\nVersion " + app.getVersionName() +
    " (" + app.getVersionCode() + ")\n\n" +
    (app.getDescription() != null ? app.getDescription() : "");

    builder.setMessage(msg)
      .setCancelable(true)
      .setTitle(app.getTitle())
      .setIcon(mAdapter.getIcons().get(pkg))
      .setPositiveButton("Launch",new DialogInterface.OnClickListener(){
        public void onClick(DialogInterface dialog, int id) {
          // start the app by invoking its launch intent
          Intent i = getPackageManager().getLaunchIntentForPackage(pkg);
          try {
            if (i != null) {
              startActivity(i);
            }
          } catch (ActivityNotFoundException err) {
            Toast.makeText(ListInstalledApps.this, "App launch failed!",
              Toast.LENGTH_SHORT).show();
          }
        }
      })
      .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
        public void onClick(DialogInterface dialog, int id) {
          dialog.cancel();
        }
      });
  AlertDialog dialog = builder.create();
  dialog.show();
}

You can download the sample application containing all source code and layout resource files:

DownloadDownload now.zip (66.8 KB)

8 Comments

  1. Its very useful code.

  2. It’s very slow to populate the list. How do I make it display a ProgressDialog? Do I do it inside the ListAdapter?

    • I am aware of the fact that the list still takes a long time to be loaded. A future update of this tutorial will show you how to display a loading indicator whilst the list is getting populated.

  3. Hi again.

    I just noticed something. I’m running Cyanogenmod 7.1 and the versionName for system apps is not null, so even if includeSysApps is set to false, it lists all apps.

    I did the following instead:

    for(int i=0; i < packs.size(); i++) {
    PackageInfo p = packs.get(i);
    ApplicationInfo a = p.applicationInfo;
    // skip system apps if they shall not be included
    if ((!includeSysApps) && ((a.flags & ApplicationInfo.FLAG_SYSTEM) == 1)) {
    continue;
    }

    • Thank you for this hint! I’ve corrected the code samples to use your method of determing whether or not an installed app is a system app or not.

  4. Would be helpful if they were loaded alphabetically how could that be done?

    Thanks for the great tutorial really helped a lot

    • This can easily be achieved. Simply store the entries inside the loadInstalledApps() method in a TreeSet which is instantiated with a custom Comparator. This Comparator class has to override the compare method in which the name of the entries are compared to each other.

  5. Figured out the sorting! Just needed to add the piece of code given below after the loop in loadInstalledApps(). Never knew how to use a comparator before the author suggested it: so I’m glad I listened. ^^ Anyways, here’s the code:-

    Collections.sort(apps, new Comparator()
    {
    public int compare(App lhs, App rhs) {
    return (lhs.getTitle()).compareToIgnoreCase(rhs.getTitle());
    }
    });
    return apps;

Trackbacks/Pingbacks

  1. Android get install location with packagename | Android Development tutorial | Android Development tutorial - [...] code from this tutorial to list all of the installed applications in an app i’m working on. http://impressive-artworx.de/2011/list-all-installed-apps-in-style/I changed ...
  2. Open Android installed applications screen programmatically : Android Community - For Application Development - [...] http://impressive-artworx.de/2011/list-all-installed-apps-in-style/ [...]

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>