Ch5 Listings

satya - Thursday, June 11, 2009 3:58:15 PM

Listing 5-1: Signature for the onCreateOptionsMenu Method


@Override
public boolean onCreateOptionsMenu(Menu menu)
{
   // populate menu items
   ...
   ...return true;
}

satya - Thursday, June 11, 2009 4:00:54 PM

Listing 5-2: Adding Menu Items


@Override
public boolean onCreateOptionsMenu(Menu menu)
{
   //call the base class to include system menus
   super.onCreateOptionsMenu(menu);
   menu.add(0 // Group
         ,1 // item id
         ,0 //order
         ,"append"); // title
         
   menu.add(0,2,1,"item2");
   menu.add(0,3,2,"clear");
   
   //It is important to return true to see the menu
   return true;
}

satya - Thursday, June 11, 2009 4:02:21 PM

Listing 5-3. Using Group IDs to Create Menu Groups


@Override
public boolean onCreateOptionsMenu(Menu menu)
{
   //Group 1
   int group1 = 1;
   menu.add(group1,1,1,"g1.item1");
   menu.add(group1,2,2,"g1.item2");
   
   //Group 2
   int group2 = 2;
   menu.add(group2,3,3,"g2.item1");
   menu.add(group2,4,4,"g2.item2");
   
   return true; // it is important to return true
}

satya - Thursday, June 11, 2009 4:03:58 PM

Listing 5-4. Signature and Body of the onOptionsItemSelected Method


@Override
public boolean onOptionsItemSelected(MenuItem item)
{
   switch(item.getItemId()) 
   {
     ......
   }
   //for items handled
   return true;
   
   //for the rest
   ...return super.onOptionsItemSelected(item);
}

satya - Thursday, June 11, 2009 4:06:29 PM

Listing 5-5. Using a Listener as a Callback for a Menu-Item Click


//Step 1
public class MyResponse implements OnMenuClickListener
{
   //some local variable to work on
   //...
   //Some constructors
   @override
   boolean onMenuItemClick(MenuItem item)
   {
      //do your thing
      return true;
   }
}

//Step 2
MyResponse myResponse = new MyResponse(...);
menuItem.setOnMenuItemClickListener(myResponse);
...

satya - Thursday, June 11, 2009 4:08:28 PM

Listing 5-6. XML Layout File for the Test Harness


<?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"
   >
<TextView android:id="@+id/textViewId"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="Debugging Scratch Pad"
   />
</LinearLayout>

satya - Thursday, June 11, 2009 4:12:34 PM

Listing 5-7. Menu Test Harness Activity Class


public class SampleMenusActivity extends Activity 
{
   //Initialize this in onCreateOptions
   Menu myMenu = null;
   @Override
   public void onCreate(Bundle savedInstanceState) 
   {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);
   }
   //....other code
}

satya - Thursday, June 11, 2009 4:13:30 PM

Listing 5-8. Setting Up the Menu Programatically


@Override
public boolean onCreateOptionsMenu(Menu menu)
{
   //call the parent to attach any system level menus
   super.onCreateOptionsMenu(menu);
   this.myMenu = menu;
   
   //add a few normal menus
   addRegularMenuItems(menu);
   
   //add a few secondary menus
   add5SecondaryMenuItems(menu);
   
   //it must return true to show the menu
   //if it is false menu won't show
   return true;
}

satya - Thursday, June 11, 2009 4:18:09 PM

Listing 5-9. The addRegularMenuItems Function


private void addRegularMenuItems(Menu menu)
{
   int base=Menu.FIRST; // value is 1

   menu.add(base,base,base,"append");
   menu.add(base,base+1,base+1,"item 2");
   menu.add(base,base+2,base+2,"clear");

   menu.add(base,base+3,base+3,"hide secondary");
   menu.add(base,base+4,base+4,"show secondary");

   menu.add(base,base+5,base+5,"enable secondary");
   menu.add(base,base+6,base+6,"disable secondary");

   menu.add(base,base+7,base+7,"check secondary");
   menu.add(base,base+8,base+8,"uncheck secondary");
}

satya - Thursday, June 11, 2009 4:20:34 PM

Listing 5-10. Adding Secondary Menu Items


private void add5SecondaryMenuItems(Menu menu)
{
   //Secondary items are shown just like everything else
   int base=Menu.CATEGORY_SECONDARY;
   
   menu.add(base,base+1,base+1,"sec. item 1");
   menu.add(base,base+2,base+2,"sec. item 2");
   menu.add(base,base+3,base+3,"sec. item 3");
   menu.add(base,base+3,base+3,"sec. item 4");
   menu.add(base,base+4,base+4,"sec. item 5");
}

satya - Thursday, June 11, 2009 4:28:29 PM

Listing 5-11. Responding to Menu-Item Clicks


@Override
public boolean onOptionsItemSelected(MenuItem item) 
{
   if (item.getItemId() == 1) {
   appendText("\nhello");
   }
   else if (item.getItemId() == 2) {
   appendText("\nitem2");
   }
   else if (item.getItemId() == 3) {
   emptyText();
   }
   else if (item.getItemId() == 4) {
   //hide secondary
   this.appendMenuItemText(item);
   this.myMenu.setGroupVisible(Menu.CATEGORY_SECONDARY,false);
   }
   else if (item.getItemId() == 5) {
   //show secondary
   this.appendMenuItemText(item);
   this.myMenu.setGroupVisible(Menu.CATEGORY_SECONDARY,true);
   }
   else if (item.getItemId() == 6) {
   //enable secondary
   this.appendMenuItemText(item);
   this.myMenu.setGroupEnabled(Menu.CATEGORY_SECONDARY,true);
   }
   else if (item.getItemId() == 7) {
   //disable secondary
   this.appendMenuItemText(item);
   this.myMenu.setGroupEnabled(Menu.CATEGORY_SECONDARY,false);
   }
   else if (item.getItemId() == 8) {
   //check secondary
   this.appendMenuItemText(item);
   myMenu.setGroupCheckable(Menu.CATEGORY_SECONDARY,true,false);
   }
   else if (item.getItemId() == 9) {
   //uncheck secondary
   this.appendMenuItemText(item);
   myMenu.setGroupCheckable(Menu.CATEGORY_SECONDARY,false,false);
   }
   else {
   this.appendMenuItemText(item);
   }
   //should return true if the menu item
   //is handled
   return true;
}

satya - Thursday, June 11, 2009 4:30:51 PM

Listing 5-12. Utility Functions to Write to the Debug TextView


//Given a string of text append it to the TextView
private void appendText(String text) 
{
   TextView tv = (TextView)this.findViewById(R.id.textViewId);
   tv.setText(tv.getText() + text);
}

//Given a menu item append its title to the TextView
private void appendMenuItemText(MenuItem menuItem) 
{
   String title = menuItem.getTitle().toString();
   TextView tv = (TextView)this.findViewById(R.id.textViewId);
   tv.setText(tv.getText() + "\n" + title);
}

//Empty the TextView of its contents
private void emptyText() 
{
   TextView tv = (TextView)this.findViewById(R.id.textViewId);
   tv.setText("");
}

satya - Thursday, June 11, 2009 4:38:41 PM

Listing 5-13. The AndroidManifest.xml File for the Test Harness


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
   package="your-package-name-goes-here "
   android:versionCode="1"
   android:versionName="1.0.0">
   <application android:icon="@drawable/icon" android:label="Sample Menus">
      <activity android:name=".SampleMenusActivity"
                android:label="Sample Menus Application">
         <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
         </intent-filter>
      </activity>
   </application>
</manifest>

satya - Thursday, June 11, 2009 4:43:20 PM

Listing 5-14. Adding Submenus


private void addSubMenu(Menu menu)
{
   //Secondary items are shown just like everything else
   int base=Menu.FIRST + 100;

   SubMenu sm = menu.addSubMenu(base,base+1,Menu.NONE,"submenu");
   sm.add(base,base+2,base+2,"sub item1");
   sm.add(base,base+3,base+3, "sub item2");
   sm.add(base,base+4,base+4, "sub item3");

   //submenu item icons are not supported
   item1.setIcon(R.drawable.icon48x48_2);

   //the following is ok however
   sm.setIcon(R.drawable.icon48x48_1);

   //This will result in a runtime exception
   //sm.addSubMenu("try this");
}

satya - Thursday, June 11, 2009 4:45:47 PM

Listing 5-15. Registering a TextView for a Context Menu


@Override
public void onCreate(Bundle savedInstanceState) 
{
   super.onCreate(savedInstanceState);
   setContentView(R.layout.main);
   
   TextView tv = (TextView)this.findViewById(R.id.textViewId);
   registerForContextMenu(this.getTextView());
}

satya - Thursday, June 11, 2009 4:49:39 PM

Listing 5-16. The onCreateContextMenu() Method


@Override
public void onCreateContextMenu(ContextMenu menu, 
                                View v, 
                                ContextMenuInfo menuInfo)
{
   menu.setHeaderTitle("Sample Context Menu");
   menu.add(200, 200, 200, "item1");
}

satya - Thursday, June 11, 2009 4:50:53 PM

Listing 5-17. Responding to Context Menus


@Override
public boolean onContextItemSelected(MenuItem item)
{
   if (item.itemId() = some-menu-item-id)
   {
      //handle this menu item
      return true;
   }
   //... other exception processing
}

satya - Thursday, June 11, 2009 4:54:45 PM

Listing 5-18. Populating a Menu with Alternative Menu Items


// Search for, and populate the menu with matching Activities.
menu.addIntentOptions(
   Menu.CATEGORY_ALTERNATIVE,    // Group
   Menu.CATEGORY_ALTERNATIVE,    // Any unique IDs we might care to add.
   Menu.CATEGORY_ALTERNATIVE,    // order
   getComponentName(),           // Name of the class displaying
   //the menu--here, it's this class.
   null,                         // No specifics.
   criteriaIntent,               // Previously created intent that
   // describes our requirements.
   0,                            // No flags.
   null);                        // returned menu items

satya - Thursday, June 11, 2009 5:07:19 PM

Listing 5-19. MenuBuilder.addIntentOptions Method


public int addIntentOptions(int group, int id, int categoryOrder,
                     ComponentName caller,
                     Intent[] specifics,
                     Intent intent, int flags,
                     MenuItem[] outSpecificItems)
{
   PackageManager pm = mContext.getPackageManager();
   final List<ResolveInfo> lri =
      pm.queryIntentActivityOptions(caller, specifics, intent, 0);
      
   final int N = lri != null ? lri.size() : 0;
   
   if ((flags & FLAG_APPEND_TO_GROUP) == 0) 
   {
      removeGroup(group);
   }
   
   for (int i=0; i<N; i++) 
   {
      final ResolveInfo ri = lri.get(i);
      Intent rintent = new Intent(
              ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]);
            
      rintent.setComponent(new ComponentName(
                  ri.activityInfo.applicationInfo.packageName,
                  ri.activityInfo.name));
                  
      final MenuItem item = add(group, id, categoryOrder, ri.loadLabel(pm));
      
      item.setIntent(rintent);
      if (outSpecificItems != null && ri.specificIndex >= 0) 
      {
         outSpecificItems[ri.specificIndex] = item;
      }
   }
   return N;
}

satya - Thursday, June 11, 2009 5:09:52 PM

Listing 5-20. An XML File with Menu Definitions


<menu xmlns:android="http://schemas.android.com/apk/res/android">
   <!-- This group uses the default category. -->
   <group android:id="@+id/menuGroup_Main">
      <item android:id="@+id/menu_testPick"
         android:orderInCategory="5"
         android:title="Test Pick" />
      <item android:id="@+id/menu_testGetContent"
         android:orderInCategory="5"
         android:title="Test Get Content" />
      <item android:id="@+id/menu_clear"
         android:orderInCategory="10"
         android:title="clear" />
      <item android:id="@+id/menu_dial"
         android:orderInCategory="7"
         android:title="dial" />
      <item android:id="@+id/menu_test"
         android:orderInCategory="4"
         android:title="@+string/test" />
      <item android:id="@+id/menu_show_browser"
         android:orderInCategory="5"
         android:title="show browser" />
   </group>
</menu>

satya - Thursday, June 11, 2009 5:14:43 PM

Listing 5-21. Building and Displaying an Alert Dialog


public class Alerts
{
   public static void showAlert(String message, Context ctx)
   {
      //Create a builder
      AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
      builder.setTitle("Alert Window");

      //add buttons and listener
      PromptListener pl = new EmptyListener();
      builder.setPositiveButton("OK", pl);

      //Create the dialog
      AlertDialog ad = builder.create();

      //show
      ad.show();
   }
}

public class EmptyListener
implements android.content.DialogInterface.OnClickListener 
{
   public void onClick(DialogInterface v, int buttonId)
   {
   }
}

satya - Thursday, June 11, 2009 11:16:51 PM

Listing 5-22. The prompt_layout.xml File


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:orientation="vertical">

   <TextView
      android:id="@+id/promptmessage"
      android:layout_height="wrap_content"
      android:layout_width="wrap_content"
      android:layout_marginLeft="20dip"
      android:layout_marginRight="20dip"
      android:text="Your text goes here"
      android:gravity="left"
      android:textAppearance="?android:attr/textAppearanceMedium" />

   <EditText
      android:id="@+id/editText_prompt"
      android:layout_height="wrap_content"
      android:layout_width="fill_parent"
      android:layout_marginLeft="20dip"
      android:layout_marginRight="20dip"
      android:scrollHorizontally="true"
      android:autoText="false"
      android:capitalize="none"
      android:gravity="fill_horizontal"
      android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>

satya - Thursday, June 11, 2009 11:19:23 PM

Listing 5-23. Inflating a Layout into a Dialog


LayoutInflater li = LayoutInflater.from(ctx);
View view = li.inflate(R.layout.promptdialog, null);

//get a builder and set the view
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.setTitle("Prompt");
builder.setView(view);

satya - Thursday, June 11, 2009 11:22:48 PM

Listing 5-24. Setting Up OK and Cancel Buttons


//add buttons and listener
PromptListener pl = new PromptListener(view,ctx);
builder.setPositiveButton("OK", pl);
builder.setNegativeButton("Cancel", pl);

satya - Thursday, June 11, 2009 11:23:52 PM

Listing 5-25. Telling the Alert-Dialog Builder to Create the Dialog


//get the dialog
AlertDialog ad = builder.create();
ad.show();

//return the prompt
return pl.getPromptReply();

satya - Thursday, June 11, 2009 11:28:54 PM

Listing 5-26. PromptListener, the Listener Callback Class


public class PromptListener
implements android.content.DialogInterface.OnClickListener
{
   // local variable to return the prompt reply value
   private String promptReply = null;
   //Keep a variable for the view to retrieve the prompt value
   View promptDialogView = null;

   //Take in the view in the constructor
   public PromptListener(View inDialogView) 
   {
      promptDialogView = inDialogView;
   }

   //Call back method from dialogs
   public void onClick(DialogInterface v, int buttonId) 
   {
      if (buttonId == DialogInterface.BUTTON1) 
      {
         //ok button
         promptReply = getPromptText();
      }
      else 
      {
         //cancel button
         promptValue = null;
      }
   }
   
   //Just an access method for what is in the edit box
   private String getPromptText() 
   {
      EditText et = (EditText)
      promptDialogView.findViewById(R.id.promptEditTextControlId);
      return et.getText().toString();
   }

   public String getPromptReply() { return promptReply; }
}

satya - Thursday, June 11, 2009 11:32:34 PM

Listing 5-27. Code to Test the Prompt Dialog


public class Alerts
{
   public static String prompt(String message, Context ctx)
   {
      //load some kind of a view
      LayoutInflater li = LayoutInflater.from(ctx);
      View view = li.inflate(R.layout.promptdialog, null);

      //get a builder and set the view
      AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
      builder.setTitle("Prompt");
      builder.setView(view);

      //add buttons and listener
      PromptListener pl = new PromptListener(view,ctx);
      builder.setPositiveButton("OK", pl);
      builder.setNegativeButton("Cancel", pl);

      //get the dialog
      AlertDialog ad = builder.create();

      //show
      ad.show();
      return pl.getPromptReply();
   }
}

satya - Thursday, June 11, 2009 11:38:28 PM

Listing 5-28. The Abstraction of the Managed-Dialog Protocol


public class MainActivity extends ManagedDialogsActivity
{
   //dialog 1
   private GenericManagedAlertDialog gmad =
   new GenericManagedAlertDialog(this,1,"InitialValue");

   //dialog 2
   private GenericPromptDialog gmpd =
   new GenericPromptDialog(this,2,"InitialValue");

   //menu items to start the dialogs
   else if (item.getItemId() == R.id.menu_simple_alert)
   {
      gmad.show();
   }
   else if (item.getItemId() == R.id.menu_simple_prompt)
   {
      gmpd.show();
   }
   
   //dealing with call backs
   public void dialogFinished(ManagedActivityDialog dialog, int buttonId)
   {
      if (dialog.getDialogId() == gmpd.getDialogId())
      {
         String replyString = gmpd.getReplyString();
      }
   }
}

satya - Thursday, June 11, 2009 11:41:52 PM

Listing 5-29. The ManagedActivityDialog Class


public abstract class ManagedActivityDialog implements IDialogProtocol
   ,android.content.DialogInterface.OnClickListener
{
   private ManagedDialogsActivity mActivity;
   private int mDialogId;

   public ManagedActivityDialog(ManagedDialogsActivity a, int dialogId)
   {
      mActivity = a;
      mDialogId = dialogId;
   }

   public int getDialogId()
   {
      return mDialogId;
   }

   public void show()
   {
      mActivity.showDialog(mDialogId);
   }

   public void onClick(DialogInterface v, int buttonId)
   {
      onClickHook(buttonId);
      this.mActivity.dialogFinished(this, buttonId);
   }
}

satya - Thursday, June 11, 2009 11:45:28 PM

Listing 5-30. The DialogRegistry Class


public class DialogRegistry
{
   SparseArray<IDialogProtocol> idsToDialogs
                     = new SparseArray();
                     
   public void registerDialog(IDialogProtocol dialog)
   {
      idsToDialogs.put(dialog.getDialogId(),dialog);
   }

   public Dialog create(int id)
   {
      IDialogProtocol dp = idsToDialogs.get(id);
      if (dp == null) return null;
      return dp.create();
   }

   public void prepare(Dialog dialog, int id)
   {
      IDialogProtocol dp = idsToDialogs.get(id);
      if (dp == null)
      {
         throw new RuntimeException("Dialog id is not registered:" + id);
      }
      dp.prepare(dialog);
   }
}

satya - Thursday, June 11, 2009 11:49:13 PM

Listing 5-31. The ManagedDialogsActivity Class


public class ManagedDialogsActivity extends Activity
   implements IDialogFinishedCallBack
{
   //A registry for managed dialogs
   private DialogRegistry dr = new DialogRegistry();

   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      this.registerDialogs();
   }

   protected void registerDialogs()
   {
      // does nothing
      // have the derived classes override this method
      // to register their dialogs
      // example:
      // registerDialog(this.DIALOG_ALERT_ID_3, gmad);
   }

   public void registerDialog(IDialogProtocol dialog)
   {
      this.dr.registerDialog(dialog);
   }

   @Override
   protected Dialog onCreateDialog(int id) {
      return this.dr.create(id);
   }

   @Override
   protected void onPrepareDialog(int id, Dialog dialog) {
      this.dr.prepare(dialog, id);
   }

   public void dialogFinished(ManagedActivityDialog dialog, int buttonId)
   {
      //nothing to do
      //have derived classes override this
   }
}

satya - Thursday, June 11, 2009 11:51:05 PM

Listing 5-32. The IDialogFinishedCallBack Interface


public interface IDialogFinishedCallBack
{
   public static int OK_BUTTON = -1;
   public static int CANCEL_BUTTON = -2;
   public void dialogFinished(ManagedActivityDialog dialog, int buttonId);
}

satya - Thursday, June 11, 2009 11:53:40 PM

Listing 5-33. The GenericManagedAlertDialog Class


public class GenericManagedAlertDialog extends ManagedActivityDialog
{
   private String alertMessage = null;
   private Context ctx = null;

   public GenericManagedAlertDialog(ManagedDialogsActivity inActivity,
                                    int dialogId,
                                    String initialMessage)
   {
      super(inActivity,dialogId);
      alertMessage = initialMessage;
      ctx = inActivity;
   }
   public Dialog create()
   {
      AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
      builder.setTitle("Alert");
      builder.setMessage(alertMessage);
      builder.setPositiveButton("Ok", this );
      AlertDialog ad = builder.create();
      return ad;
   }
   public void prepare(Dialog dialog)
   {
      AlertDialog ad = (AlertDialog)dialog;
      ad.setMessage(alertMessage);
   }
   public void setAlertMessage(String inAlertMessage)
   {
      alertMessage = inAlertMessage;
   }
   public void onClickHook(int buttonId)
   {
      //nothing to do
      //no local variables to set
   }
}

satya - Thursday, June 11, 2009 11:58:01 PM

Listing 5-34. The GenericPromptDialog Class


public class GenericPromptDialog extends ManagedActivityDialog
{
   private String mPromptMessage = null;
   private View promptView = null;
   String promptValue = null;
   private Context ctx = null;

   public GenericPromptDialog(ManagedDialogsActivity inActivity,
                                 int dialogId,
                                 String promptMessage)
   {
      super(inActivity,dialogId);
      mPromptMessage = promptMessage;
      ctx = inActivity;
   }
   public Dialog create()
   {
      LayoutInflater li = LayoutInflater.from(ctx);
      promptView = li.inflate(R.layout.promptdialog, null);
      AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
      builder.setTitle("prompt");
      builder.setView(promptView);
      builder.setPositiveButton("OK", this);
      builder.setNegativeButton("Cancel", this);
      AlertDialog ad = builder.create();
      return ad;
   }
   public void prepare(Dialog dialog)
   {
      //nothing for now
   }
   public void onClickHook(int buttonId)
   {
      if (buttonId == DialogInterface.BUTTON1)
      {
      //ok button
      String promptValue = getEnteredText();
      }
   }
   private String getEnteredText()
   {
      EditText et =
      (EditText)
      promptView.findViewById(R.id.editText_prompt);

      String enteredText = et.getText().toString();
      Log.d("xx",enteredText);
      return enteredText;
   }
}