Friday, May 21, 2010

Android Menus part 4: Alternative menus

Android offers a third type of menus: Alternative menus which allow multiple applications to use each other. An application menu can contain menu items that point to other applications that deal with a certain data type that is passed from the application by an intent.

This functionality is related to the concept of Content Providers which is in brief the ability of an application to expose its data (stored in a database or a file) by defining a MIME type to it and through a content URI to be accessed by any other application through this URI.

For example if an application name Employees has some data of employees stored within this application context, and another application wants to access this data; then Employees application should declare a content provider  to expose its data, with a MIME type:

vnd.android.cursor.item/mina.android.Employees so any other application can access the employees data by calling the Uri content://employees/All to access all employees or the Uri content://employees/1 to access a single employee instance (for example).

Back to our Alternative menus issue, suppose this Scenario: We have two applications:
  1. Application A: deals with the employees data.
  2. Application B: receives the content Uri of the employees and do some calculations on it.
Now we want to add an alternative menu item in an activity in Application A so that when clicked passes a URI of employees and launches an activity in Application B (that manipulates the employees data according to the URI received).

So to add the alternative menu item in the activity of Application A, we write the following in onCreateOptionsMenu method:
public boolean onCreateOptionsMenu(Menu menu) {

//adds a regular menu item
menu.add("Regular item");
//create the intent with the Uri of the employees content provider
Intent targetIntent=
new Intent(Intent.ACTION_VIEW, Uri.parse("content://employees/All"));
targetIntent.addCategory(Intent.CATEGORY_ALTERNATIVE);
menu.addIntentOptions(Menu.CATEGORY_ALTERNATIVE, //item group
Menu.CATEGORY_ALTERNATIVE,  //item id
Menu.CATEGORY_ALTERNATIVE,  //item order
this.getComponentName(), //our activity class name
null, //no specific menu items required
targetIntent, // the intent to handle
0, //no flags
null); //Optional array in which to place the menu
//items that were generated for each of
//the specifics that were requested

return true;
}
Here's what we did:
  • Create an intent with the desired action (Intent.ACTION_VIEW) on the specified content provider Uri (content://employees/All).
  • Call addIntentOptions method with the specified parameters.
The above code adds a menu item that launches all possible activities in all applications on the device that can deal with the action Intent.ACTION_VIEW on the Uri content://employees/All.

Now in Application B, if we want it to handle such an intent we have to do the following.

Define an activity in the application and specify in the AndroidManifest.xml file that this activity can handle the requests of the employees content provider like this:
<activity android:name=".ContentProvidersDemo" android:label="@string/app_name">

<intent-filter android:label="Access Employees">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.ALTERNATIVE" />
<data android:mimeType="vnd.android.cursor.item/mina.android.Employees" />
</intent-filter>
</activity>
The above IntentFilter means that this activity will respond t0 any implicit intent from any application with the following parameters:
  1. Action: Intent.ACTION_VIEW.
  2. Category: android.intent.category.ALTERNATIVE.
  3. Data of MIME type:vnd.android.cursor.item/mina.android.Employees.
So in Application A when you press on the menu button, you'll see a menu like this:



When you press on the Access Employees menu item, the activity in Application B will be launched.


No comments:

Post a Comment