From 04c72b47d877c9f3b45caa1ddc7f640b02e7be4c Mon Sep 17 00:00:00 2001 From: Scott Main Date: Wed, 13 May 2009 16:48:13 -0700 Subject: AI 148812: revise the AppWidget developer guide documentation BUG=1827433 Automated import of CL 148812 --- docs/html/guide/guide_toc.cs | 4 +- docs/html/guide/topics/appwidgets/index.jd | 487 +++++++++++++++++++++++------ 2 files changed, 400 insertions(+), 91 deletions(-) (limited to 'docs/html/guide') diff --git a/docs/html/guide/guide_toc.cs b/docs/html/guide/guide_toc.cs index 5367cb2..a044cea 100644 --- a/docs/html/guide/guide_toc.cs +++ b/docs/html/guide/guide_toc.cs @@ -95,7 +95,7 @@ --> -
  • AppWidgets
  • +
  • App Widgets
  • @@ -146,7 +146,7 @@
  • UI Guidelines
  • Designing for Performance
  • diff --git a/docs/html/guide/topics/appwidgets/index.jd b/docs/html/guide/topics/appwidgets/index.jd index f9db356..01a9648 100644 --- a/docs/html/guide/topics/appwidgets/index.jd +++ b/docs/html/guide/topics/appwidgets/index.jd @@ -1,4 +1,4 @@ -page.title=AppWidgets +page.title=App Widgets @jd:body
    @@ -6,131 +6,338 @@ page.title=AppWidgets

    Key classes

    1. {@link android.appwidget.AppWidgetProvider}
    2. -
    3. {@link android.appwidget.AppWidgetHost}
    4. +
    5. {@link android.appwidget.AppWidgetProviderInfo}
    6. +
    7. {@link android.appwidget.AppWidgetManager}

    In this document

      -
    1. AppWidget Providers +
    2. The Basics
    3. +
    4. Declaring an App Widget in the Manifest
    5. +
    6. Adding the AppWidgetProviderInfo Metadata
    7. +
    8. Creating the App Widget Layout
    9. +
    10. Using the AppWidgetProvider Class
        -
      1. Declaring a widget in the AndroidManifest
      2. -
      3. Adding the AppWidgetProviderInfo meta-data
      4. -
      5. Using the AppWidgetProvider class
      6. -
      7. AppWidget Configuration UI
      8. -
      9. AppWidget Broadcast Intents
      10. +
      11. Receiving App Widget broadcast Intents
      12. +
      +
    11. +
    12. Creating an App Widget Configuration Activity +
        +
      1. Updating the App Widget from + the configuration Activity
    13. -
    14. AppWidget Hosts

    See also

      +
    1. App Widget Design + Guidelines
    2. Introducing - home screen widgets and the AppWidget framework »
    3. + home screen widgets and the AppWidget framework »
    -

    AppWidgets are miniature application views that can be embedded in other applications -(e.g., the Home). These views are called "widgets" and you can publish one with -an "AppWidget provider." An application component that is able to hold other widgets is -called an "AppWidget host."

    +

    App Widgets are miniature application views that can be embedded in other applications +(such as the Home screen) and receive periodic updates. These views are referred +to as Widgets in the user interface, +and you can publish one with an App Widget provider. An application component that is +able to hold other App Widgets is called an App Widget host. The screenshot below shows +the Music App Widget.

    + +

    This document describes how to publish an App Widget using an App Widget provider.

    -

    AppWidget Providers

    -

    Any application can publish widgets. All an application needs to do to publish a widget is -to have a {@link android.content.BroadcastReceiver} that receives the {@link -android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE AppWidgetManager.ACTION_APPWIDGET_UPDATE} intent, -and provide some meta-data about the widget. Android provides the -{@link android.appwidget.AppWidgetProvider} class, which extends BroadcastReceiver, as a convenience -class to aid in handling the broadcasts. +

    The Basics

    -

    Declaring a widget in the AndroidManifest

    +

    To create an App Widget, you need the following:

    -

    First, declare the {@link android.content.BroadcastReceiver} in your application's -AndroidManifest.xml file. +

    +
    {@link android.appwidget.AppWidgetProviderInfo} object
    +
    Describes the metadata for an App Widget, such as the App Widget's layout, update frequency, + and the AppWidgetProvider class. This should be defined in XML.
    +
    {@link android.appwidget.AppWidgetProvider} class implementation
    +
    Defines the basic methods that allow you to programmatically interface with the App Widget, + based on broadcast events. Through it, you will receive broadcasts when the App Widget is updated, + enabled, disabled and deleted.
    +
    View layout
    +
    Defines the initial layout for the App Widget, defined in XML.
    +
    -{@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/AndroidManifest.xml AppWidgetProvider} +

    Additionally, you can implement an App Widget configuration Activity. This is an optional +{@link android.app.Activity} that launches when the user adds your App Widget and allows him or her +to modify App Widget settings at create-time.

    -

    -The <receiver> element has the following attributes: -

    +

    The following sections describe how to setup each of these components.

    + + +

    Declaring an App Widget in the Manifest

    + +

    First, declare the {@link android.appwidget.AppWidgetProvider} class in your application's +AndroidManifest.xml file. For example:

    -

    -The <intent-filter> element tells the {@link android.content.pm.PackageManager} -that this {@link android.content.BroadcastReceiver} receives the {@link -android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE AppWidgetManager.ACTION_APPWIDGET_UPDATE} broadcast. -The widget manager will send other broadcasts directly to your widget provider as required. -It is only necessary to explicitly declare that you accept the {@link -android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE AppWidgetManager.ACTION_APPWIDGET_UPDATE} broadcast. - -

    -The <meta-data> element tells the widget manager which xml resource to -read to find the {@link android.appwidget.AppWidgetProviderInfo} for your widget provider. It has the following -attributes: +

    +<receiver android:name="ExampleAppWidgetProvider" >
    +    <intent-filter>
    +        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    +    </intent-filter>
    +    <meta-data android:name="android.appwidget.provider"
    +               android:resource="@xml/example_appwidget_info" />
    +</receiver>
    +
    + +

    The <receiver> element requires the android:name +attribute, which specifies the {@link android.appwidget.AppWidgetProvider} used +by the App Widget.

    + +

    The <intent-filter> element must include an <action> +element with the android:name attribute. This attribute specifies +that the {@link android.appwidget.AppWidgetProvider} accepts the {@link +android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE ACTION_APPWIDGET_UPDATE} broadcast. +This is the only broadcast that you must explicitly declare. The {@link android.appwidget.AppWidgetManager} +automatically sends all other App Widget broadcasts to the AppWidgetProvider as necessary.

    + +

    The <meta-data> element specifies the +{@link android.appwidget.AppWidgetProviderInfo} resource and requires the +following attributes:

    -

    Adding the AppWidgetProviderInfo meta-data

    +

    Adding the AppWidgetProviderInfo Metadata

    -

    For a widget, the values in the {@link android.appwidget.AppWidgetProviderInfo} structure are supplied -in an XML resource. In the example above, the xml resource is referenced with -android:resource="@xml/appwidget_info". That XML file would go in your application's -directory at res/xml/appwidget_info.xml. Here is a simple example. +

    The {@link android.appwidget.AppWidgetProviderInfo} defines the essential +qualities of an App Widget, such as its minimum layout dimensions, its initial layout resource, +how often to update the App Widget, and (optionally) a configuration Activity to launch at create-time. +Define the AppWidgetProviderInfo object in an XML resource using a single +<appwidget-provider> element and save it in the project's res/xml/ +folder.

    -{@sample frameworks/base/tests/appwidgets/AppWidgetHostTest/res/xml/appwidget_info.xml AppWidgetProviderInfo} +

    For example:

    -

    The attributes are as documented in the -{@link android.appwidget.AppWidgetProviderInfo} class. +

    +<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    +    android:minWidth="294dp" <!-- density-independent pixels -->
    +    android:minHeight="72dp"
    +    android:updatePeriodMillis="86400000" <!-- once per day -->
    +    android:initialLayout="@layout/example_appwidget"
    +    android:configure="com.example.android.ExampleAppWidgetConfigure" >
    +</appwidget-provider>
    +
    +

    Here's a summary of the <appwidget-provider> attributes:

    + -

    Using the AppWidgetProvider class

    +

    See the {@link android.appwidget.AppWidgetProviderInfo} class for more information on the +attributes accepted by the <appwidget-provider> element.

    -

    The AppWidgetProvider class is the easiest way to handle the widget provider intent broadcasts. -See the src/com/example/android/apis/appwidget/ExampleAppWidgetProvider.java -sample class in ApiDemos for an example. -

    Keep in mind that since the the AppWidgetProvider is a BroadcastReceiver, -your process is not guaranteed to keep running after the callback methods return. See -Application Fundamentals > -Broadcast Receiver Lifecycle for more information. +

    Creating the App Widget Layout

    +

    You must define an initial layout for your App Widget in XML and save it in the project's +res/layout/ directory. You can design your App Widget using the View objects listed +below, but before you begin designing your App Widget, please read and understand the +App Widget Design +Guidelines.

    +

    Creating the App Widget layout is simple if you're +familiar with Declaring Layout in XML. +However, you must be aware that App Widget layouts are based on {@link android.widget.RemoteViews}, +which do not support every kind of layout or view widget.

    -

    AppWidget Configuration UI

    +

    A RemoteViews object (and, consequently, an App Widget) can support the +following layout classes:

    -

    -Widget hosts have the ability to start a configuration activity when a widget is instantiated. -The activity should be declared as normal in AndroidManifest.xml, and it should be listed in -the AppWidgetProviderInfo XML file in the android:configure attribute. +

    -

    The activity you specified will be launched with the {@link -android.appwidget.AppWidgetManager#ACTION_APPWIDGET_CONFIGURE} action. See the documentation for that -action for more info. +

    And the following widget classes:

    + -

    See the src/com/example/android/apis/appwidget/ExampleAppWidgetConfigure.java -sample class in ApiDemos for an example. +

    Descendants of these classes are not supported.

    +

    Using the AppWidgetProvider Class

    -

    AppWidget Broadcast Intents

    + + +

    The {@link android.appwidget.AppWidgetProvider} class extends BroadcastReceiver as a convenience +class to handle the App Widget broadcasts. The AppWidgetProvider receives only the event broadcasts that +are relevant to the App Widget, such as when the App Widget is updated, deleted, enabled, and disabled. +When these broadcast events occur, the AppWidgetProvider receives the following method calls:

    + +
    +
    {@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[])}
    +
    This is called to update the App Widget at intervals defined by the updatePeriodMillis + attribute in the AppWidgetProviderInfo (see Adding the + AppWidgetProviderInfo Metadata above). This method is also called + when the user adds the App Widget, so it should perform the essential setup, + such as define event handlers for Views and start a temporary + {@link android.app.Service}, if necessary. However, if you have declared a configuration + Activity, this method is not called when the user adds the App Widget, + but is called for the subsequent updates. It is the responsibility of the + configuration Activity to perform the first update when configuration is done. + (See Creating an App Widget Configuration Activity below.)
    +
    {@link android.appwidget.AppWidgetProvider#onDeleted(Context,int[])}
    +
    This is called every time an App Widget is deleted from the App Widget host.
    +
    {@link android.appwidget.AppWidgetProvider#onEnabled(Context)}
    +
    This is called when an instance the App Widget is created for the first time. For example, if the user + adds two instances of your App Widget, this is only called the first time. + If you need to open a new database or perform other setup that only needs to occur once + for all App Widget instances, then this is a good place to do it.
    +
    {@link android.appwidget.AppWidgetProvider#onDisabled(Context)}
    +
    This is called when the last instance of your App Widget is deleted from the App Widget host. + This is where you should clean up any work done in + {@link android.appwidget.AppWidgetProvider#onEnabled(Context)}, + such as delete a temporary database.
    +
    {@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent)}
    +
    This is called for every broadcast and before each of the above callback methods. + You normally don't need to implement this method because the default AppWidgetProvider + implementation filters all App Widget broadcasts and calls the above + methods as appropriate.
    +
    + +

    Note: In Android 1.5, there is a known issue in which the +onDeleted() method will not be called when it should be. To work around this issue, +you can implement {@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent) +onReceive()} as described in this +Group post +to receive the onDeleted() callback. +

    + +

    The most important AppWidgetProvider callback is +{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) +onUpdated()} because it is called when each App Widget is added to a host (unless you use +a configuration Activity). If your App Widget accepts any +user interaction events, then you need to register the event handlers in this callback. +If your App Widget doesn't create temporary +files or databases, or perform other work that requires clean-up, then +{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) +onUpdated()} may be the only callback method you need to define. For example, if you want an App Widget +with a button that launches an Activity when clicked, you could use the following +implementation of AppWidgetProvider:

    + +
    +public class ExampleAppWidgetProvider extends AppWidgetProvider {
    +
    +    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    +        final int N = appWidgetIds.length;
    +
    +        // Perform this loop procedure for each App Widget that belongs to this provider
    +        for (int i=0; i<N; i++) {
    +            int appWidgetId = appWidgetIds[i];
    +
    +            // Create an Intent to launch ExampleActivity
    +            Intent intent = new Intent(context, ExampleActivity.class);
    +            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
    +
    +            // Get the layout for the App Widget and attach an on-click listener to the button
    +            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
    +            views.setOnClickPendingIntent(R.id.button, pendingIntent);
    +
    +            // Tell the AppWidgetManager to perform an update on the current App Widget
    +            appWidgetManager.updateAppWidget(appWidgetId, views);
    +        }
    +    }
    +}
    +
    + +

    This AppWidgetProvider defines only the +{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) +onUpdated()} method for the purpose +of defining a {@link android.app.PendingIntent} that launches an {@link android.app.Activity} +and attaching it to the App Widget's button +with {@link android.widget.RemoteViews#setOnClickPendingIntent(int,PendingIntent)}. +Notice that it includes a loop that iterates through each entry in appWidgetIds, which +is an array of IDs that identify each App Widget created by this provider. +In this way, if the user creates more than one instance of the App Widget, then they are +all updated simultaneously. However, only one updatePeriodMillis schedule will be +managed for all instances of the App Widget. For example, if the update schedule is defined +to be every two hours, and a second instance +of the App Widget is added one hour after the first one, then they will both be updated +on the period defined by the first one and the second update period will be ignored +(they'll both be updated every two hours, not every hour).

    + +

    Note: Because the AppWidgetProvider is a BroadcastReceiver, +your process is not guaranteed to keep running after the callback methods return (see +Application Fundamentals > +Broadcast Receiver Lifecycle for more information). If your App Widget setup process can take several +seconds (perhaps while performing web requests) and you require that your process continues, +consider starting a {@link android.app.Service} +in the {@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) +onUpdated()} method. From within the Service, you can perform your own updates to the App Widget +without worrying about the AppWidgetProvider closing down due to an +Application Not Responding +(ANR) error. See the +Wiktionary +sample's AppWidgetProvider for an example of an App Widget running a {@link android.app.Service}.

    + +

    Also see the +ExampleAppWidgetProvider.java sample class.

    + + +

    Receiving App Widget broadcast Intents

    {@link android.appwidget.AppWidgetProvider} is just a convenience class. If you would like -to receive the widget broadcasts directly, you can. The four intents you need to care about are: +to receive the App Widget broadcasts directly, you can implement your own +{@link android.content.BroadcastReceiver} or override the +{@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent)} callback. +The four Intents you need to care about are:

    -

    By way of example, the implementation of -{@link android.appwidget.AppWidgetProvider#onReceive} is quite simple:

    -{@sample frameworks/base/core/java/android/appwidget/AppWidgetProvider.java onReceive} + +

    Creating an App Widget Configuration Activity

    + +

    If you would like the user to configure settings when he or she adds a new App Widget, +you can create an App Widget configuration Activity. This {@link android.app.Activity} +will be automatically launched by the App Widget host and allows the user to configure +available settings for the App Widget at create-time, such as the App Widget color, size, +update period or other functionality settings.

    + +

    The configuration Activity should be declared as a normal Activity in the Android manifest file. +However, it will be launched by the App Widget host with the {@link +android.appwidget.AppWidgetManager#ACTION_APPWIDGET_CONFIGURE ACTION_APPWIDGET_CONFIGURE} action, +so the Activity needs to accept this Intent. For example:

    + +
    +<activity android:name=".ExampleAppWidgetConfigure">
    +    <intent-filter>
    +        <action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
    +    </intent-filter>
    +</activity>
    +
    + +

    Also, the Activity must be declared in the AppWidgetProviderInfo XML file, with the +android:configure attribute (see Adding +the AppWidgetProvierInfo Metadata above). For example, the configuration Activity +can be declared like this:

    + +
    +<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    +    ...
    +    android:configure="com.example.android.ExampleAppWidgetConfigure" 
    +    ... >
    +</appwidget-provider>
    +
    + +

    Notice that the Activity is declared with a fully-qualified namespace, because +it will be referenced from outside your package scope.

    + +

    That's all you need to get started with a configuration Activity. Now all you need is the actual +Activity. There are, however, two important things to remember when you implement the Activity:

    + + +

    See the code snippets in the following section for an example of how to return a result +from the configuration and update the App Widget.

    + + +

    Updating the App Widget from the configuration Activity

    + +

    When an App Widget uses a configuration Activity, it is the responsibility of the Activity +to update the App Widget when configuration is complete. +You can do so by requesting an update directly from the +{@link android.appwidget.AppWidgetManager}.

    + +

    Here's a summary of the procedure to properly update the App Widget and close +the configuration Activity:

    + +
      +
    1. First, get the App Widget ID from the Intent that launched the Activity: +
      +Intent intent = getIntent();
      +Bundle extras = intent.getExtras();
      +if (extras != null) {
      +    mAppWidgetId = extras.getInt(
      +            AppWidgetManager.EXTRA_APPWIDGET_ID, 
      +            AppWidgetManager.INVALID_APPWIDGET_ID);
      +}
      +
      +
    2. +
    3. Perform your App Widget configuration.
    4. +
    5. When the configuration is complete, get an instance of the AppWidgetManager by calling + {@link android.appwidget.AppWidgetManager#getInstance(Context)}: +
      +AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
      +
      +
    6. +
    7. Update the App Widget with a {@link android.widget.RemoteViews} layout by calling + {@link android.appwidget.AppWidgetManager#updateAppWidget(int,RemoteViews)}: +
      +RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget);
      +appWidgetManager.updateAppWidget(mAppWidgetId, views);
      +
      +
    8. +
    9. Finally, create the return Intent, set it with the Activity result, and finish the Activity:
    10. +
      +Intent resultValue = new Intent();
      +resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId);
      +setResult(RESULT_OK, resultValue);
      +finish();
      +
      + +
    + +

    Tip: When your configuration Activity first opens, set +the Activity result to RESULT_CANCELED. This way, if the user backs-out of the Activity before +reaching the end, the App Widget host is notified that the configuration was cancelled and the +App Widget will not be added.

    + +

    See the +ExampleAppWidgetConfigure.java sample class in ApiDemos for an example.

    -

    AppWidget Hosts

    -

    Widget hosts are the containers in which widgets can be placed. Most of the look and feel -details are left up to the widget hosts. For example, the home screen has one way of viewing -widgets, but the lock screen could also contain widgets, and it would have a different way of -adding, removing and otherwise managing widgets.

    -

    For more information on implementing your own widget host, see the -{@link android.appwidget.AppWidgetHost AppWidgetHost} class.

    -- cgit v1.1