Getting Started with Android Library Projects, Part 2

Share this article

Google offers Android library projects as a way to manage reusable code. In the first part of this three-part series on Android library projects, I introduced you to library project fundamentals.

In this article, I move from theory to practicality by presenting a reusable about dialog box library project as a useful example.

I used Android SDK Release 20 along with the Android 2.3.3 (API Level 10) and Android 4.1 (API Level 16) platforms to develop and test this article’s code.

About Dialog Box Android Library Project

An about (also known as info) dialog box is a good example of reusable code that can be stored in an Android library project. About dialog boxes typically identify apps (names, version numbers, icons) and their authors, provide email addresses and other links for obtaining support and visiting app author websites, offer license/disclaimer information, and so on.

Before I started to develop this library, I pondered various architectural questions. What is the library’s minimum API level and package name? What classes and other reference types are part of the library? Do I instantiate the classes or treat them as singletons? What is each type’s public interface? Do I store resources as well as code? If so, what kind(s) of resources will be stored? I concluded with the following answers:

  • The minimum API level is 10 so that the library can be used by Android 2.3.3 and above. The package name will be ca.tutortutor.about.
  • The library will consist of a single class named About.
  • About will serve as a singleton (also known as a utility class). I won’t instantiate this class, but will invoke static methods. After all, apps typically present one about dialog box.
  • About will expose a single public static void show(Activity activity, String aboutText, String okButtonText) method. This method will use Android’s package manager to obtain the app’s version number, icon, and name.
  • About is associated with a layout resource; there are no other resources. I decided to not include string resources to simplify localization. I’d rather not have to keep updating the library project to support additional locales. Instead, I believe that localization should occur at the app level; the app should pass localized text to the about dialog box.

Exploring Source Code and Resources

The about dialog box library project consists of a single source file (About.java) and a single resource file (ca_tutortutor_about.xml). Listing 1 presents About.java.

package ca.tutortutor.about;

import android.app.Activity;
import android.app.AlertDialog;

import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;

import android.graphics.drawable.Drawable;

import android.text.Html;

import android.text.method.LinkMovementMethod;

import android.view.InflateException;
import android.view.LayoutInflater;
import android.view.View;

import android.widget.TextView;

public class About
{
   public static void show(Activity activity, String aboutText, 
                           String okButtonText)
   {
      String versionNumber = "unknown";
      Drawable icon = null;
      String appName = "unknown";
      try 
      {
         PackageManager pm = activity.getPackageManager();
         versionNumber = pm.getPackageInfo(activity.getPackageName(), 0)
                           .versionName;
         icon = pm.getApplicationIcon(activity.getPackageName());
         ApplicationInfo ai = pm.getApplicationInfo(activity.getPackageName(), 
                                                    0);
         appName = (String) pm.getApplicationLabel(ai);
         if (appName == null)
            appName = "unknown";
      } 
      catch (NameNotFoundException e)
      {
      }
      View about;
      TextView tvAbout;
      try 
      {
         LayoutInflater inflater = activity.getLayoutInflater();
         about = inflater.inflate(R.layout.ca_tutortutor_about, null);
         tvAbout = (TextView) about.findViewById(R.id.ca_tutortutor_aboutText);
      } 
      catch(InflateException e) 
      {
         about = tvAbout = new TextView(activity);
      }
      tvAbout.setText(Html.fromHtml(aboutText));
      tvAbout.setMovementMethod(LinkMovementMethod.getInstance());
      new AlertDialog.Builder(activity)
                     .setTitle(appName+" "+versionNumber)
                     .setIcon(icon)
                     .setPositiveButton(okButtonText, null)
                     .setView(about)
                     .show();
   }
}

Listing 1: About.java

Listing 1 reveals an About class with its solitary public static void show(Activity activity, String aboutText, String okButtonText) class method:

  • activity contains a reference to the calling activity, which typically is the main activity.
  • aboutText contains the about dialog box’s text, which can include HTML tags such as <b> (bold), <i> (italics), <u> (underline), and <p> (paragraph). Here is where you identify your website for obtaining support, present license/disclaimer information, and so on.
  • okButtonText contains the text that appears on the button that closes the dialog box.

This method first obtains the package manager for accessing the app’s version number, icon, and name. The package manager is described by the PackageManager class, which is accessed by calling Activity‘s inherited PackageManager getPackageManager() method.

PackageManager declares a PackageInfo getPackageInfo(String packageName, int flags) method for obtaining information from the app’s package. The package is obtained by invoking Activity‘s inherited String getPackageName() method.

The returned PackageInfo object provides access to package information via its fields. For example, versionName contains the string-based version name of this package (such as 1.0), as specified by androidmanifest.xml‘s <manifest> tag’s versionName attribute.

PackageManager‘s Drawable getApplicationIcon(String packageName) method lets you obtain the app’s icon, as a Drawable instance. This method is called with the activity’s package name as an argument.

getApplicationIcon() looks for the icon specified by the <application> tag’s icon attribute, returning the default icon when it doesn’t find this attribute.

The app’s name is now obtained. First, PackageManager‘s ApplicationInfo getApplicationInfo (String packageName, int flags) method is called to return an ApplicationInfo object that corresponds to the manifest’s <application> tag. This object is then passed as an argument to PackageManager‘s CharSequence getApplicationLabel(ApplicationInfo info) method, which returns the value of the <application> tag’s label attribute or null when this attribute is missing.

The getPackageInfo() and getApplicationInfo() methods are capable of throwing PackageManager.NameNotFoundException. The former method throws this exception when a package with the given name cannot be found on the system. The latter method throws this exception when an application with the given package name cannot be found on the system. Because of the possibility for this exception, versionName, icon, and appName are initialized to default values before these methods are called.

Listing 1’s next major task is to inflate the contents of ca_tutortutor_about.xml (described shortly) and access its inflated textview widget. It obtains a layout inflator by invoking Activity‘s LayoutInflater getLayoutInflater() method, and uses this method to inflate the XML file into an about view. It then uses about to access this view’s textview widget. Notice the ca_tutortutor_ prefix in each of R.layout.ca_tutortutor_about and R.id.ca_tutortutor_aboutText for avoiding resource conflicts.

The textview widget is now configured. First, aboutText‘s contents are converted from HTML to text by invoking Html‘s Spanned fromHtml(String source) class method, and the result is assigned to the textview for display. Second, a link movement method is assigned to this widget so that pressing on a link causes the user to be taken to the link’s destination. (In the emulator, clicking on an email link results in an Unsupported Action dialog box.)

The final task is to instantiate AlertDialog and configure and show this instance. For convenience, I use AlertDialog‘s nested Builder class to accomplish these tasks.

Listing 2 presents ca_tutortutor_about.xml.

<?xml version="1.0" encoding="utf-8"?>
<scrollview xmlns:android="http://schemas.android.com/apk/res/android"
                  android:id="@+id/ca_tutortutor_aboutView"
                  android:layout_width="fill_parent"
                  android:layout_height="fill_parent">
  <linearlayout android:orientation="horizontal"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:padding="5dp">
    <textview android:id="@+id/ca_tutortutor_aboutText"
              android:layout_width="wrap_content"
              android:layout_height="fill_parent"></textview>
  </linearlayout>
</scrollview>

Listing 2: ca_tutortutor_about.xml

Listing 2 describes a layout consisting of a scrollview that nests a linearlayout that nests a textview. The scrollview is present so that you can specify as much content as you require for the about dialog box and allow the user to access this content via scrolling.

Each of the scrollview and textview is assigned an ID so that it can be accessed from About.java‘s show() method, which you learned about earlier in this article. The ca_tutortutor_ prefixes are necessary for avoiding resource conflicts.

Creating and Initializing About

Let’s create and initialize this library project. The first step is to create the project. I used the following command line to accomplish this task on my Windows platform:

android create lib-project -t 1 -p C:\prj\ap\About -k ca.tutortutor.about

Target 1 identifies Android 2.3.3 on my platform. (Execute android list targets to obtain the equivalent target number on your platform.) I store this project in my C:\prj\ap\About directory. Finally, the project’s package name is ca.tutortutor.about.

Next, I created a ca\tutortutor\about subdirectory hierarchy under About\src and copied an About.java file containing Listing 1’s contents into about. I also copied a ca_tutortutor_about.xml file containing Listing 2’s contents into About\res\layout.

About\res\layout also contains a main.xml file, which is placed in this directory during library project creation. You can erase this file or leave it because your app projects most likely provide their own main.xml files, which override this main.xml.

Similarly, you’ll find an About\res\values directory containing strings.xml. Because erasing this file prevents you from building About (to test any source code changes for bugs), you might as well leave this file alone — it’s overridden by an app project’s strings.xml file.

At this point, you might want to ensure that the library project builds correctly. Accomplish this task by executing the following command:

ant debug

You should observe a BUILD SUCCESSFUL message.

Conclusion

Now that you’ve explored the source code and resources that contribute to the about dialog box library project, and have created and initialized this project, you’ll want to integrate it into your own app projects. In the final part of this series, I present an app project that supports the about dialog box via the options menu.

Jeff FriesenJeff Friesen
View Author

Jeff Friesen is a freelance tutor and software developer with an emphasis on Java and mobile technologies. In addition to writing Java and Android books for Apress, Jeff has written numerous articles on Java and other technologies for SitePoint, InformIT, JavaWorld, java.net, and DevSource.

Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week