Honeycomb home screen widgets

satya - Thursday, February 24, 2011 1:27:05 PM

samples

samples

satya - Thursday, February 24, 2011 1:29:31 PM

stack view widget sample

stack view widget sample

satya - Thursday, February 24, 2011 1:30:31 PM

a weather widget sample

a weather widget sample

satya - Saturday, February 26, 2011 9:41:37 AM

previous notes

previous notes

satya - Saturday, February 26, 2011 9:44:02 AM

Do I ever need to override onReceive?

A widget provider is essentially a receiver. So anyone can send a broadcase message to it.

Typically this is done by explicitly creating an intent with that receriver classname and sending it with a custom action.

when this is done the custom action needs to be dealt with in the onReceive method.

when you overload the onReceive() you also need to call the super so that it can move the default actions to the respective derived methods.

satya - Sunday, February 27, 2011 10:32:46 AM

new method: notifyAppWidgetViewChanged

what does this do?

Tell a view that it needs to refresh its data.

what call backs will it call?

satya - Sunday, February 27, 2011 10:44:18 AM

The content providers need to change data and tell views

tellt he widget managr to tellt heir views tor refresh.

satya - Sunday, February 27, 2011 10:49:00 AM

As a result....

you will need to register a content observer against the provider and then tell the widget manager that the view has changed.

You will need to set this up in the "enable" of the widget.

satya - Sunday, February 27, 2011 11:07:08 AM

Nature of onupdate for listview

setup the remoteviews that contains lists

set the adapters for the remote views

set the call backs for buttons so that they issue more broadcast intents to self

override onreceive to respond to callbacks

In onreceive tell the views that they changed their data

set the remoteviews that it is going to get its adapter through a remote service

satya - Monday, February 28, 2011 10:43:54 AM

An example listview widget layout from google

An example listview widget layout from google

satya - Monday, February 28, 2011 10:48:23 AM

essence of that layout


<FrameLayout...>
  <ListView id="@+id/somelistviewid" ..../>
  <TextView id="@+id/emptylistviewid"..../>
</FrameLayout>

satya - Monday, February 28, 2011 10:52:18 AM

How is this layout loaded


final RemoteViews rv = 
new RemoteViews(context.getPackageName(), R.layout.widget_layout);

rv.setRemoteAdapter(appWidgetIds[i], R.id.weather_list, intent);

Ofcourse the layout id R.layout.widget_layout belongs to the entire layout of the widget where as the R.id.weather_list belongs to just the id of the list view similar to the one above.

satya - Monday, February 28, 2011 11:02:49 AM

The way you construct a remoteview is much like before.


RemoteViews views = 
new RemoteViews
(context.getPackageName(), R.layout.bday_widget);

satya - Monday, February 28, 2011 11:05:50 AM

A configure activity, if present, is responsible for an explcit update...

A configur activity, if present, must do very similar things that an "onUpdate" method does.

However the "onUpdate" method should watch out to see if configure activity is not finished (if the update is too frequent). (I think...)

satya - Monday, February 28, 2011 11:07:42 AM

Here is an example of a common update chore

Code/strategy similar to the following can be used both by the configure activity and the onupdate method.


public static void updateAppWidget(Context context, 
        AppWidgetManager appWidgetManager,
        BDayWidgetModel widgetModel) 
{
    RemoteViews views = 
    new RemoteViews(context.getPackageName(), 
                  R.layout.bday_widget);
    
    views.setTextViewText(R.id.bdw_w_name
        , widgetModel.getName() + ":" + widgetModel.iid);
    
    views.setTextViewText(R.id.bdw_w_date
            , widgetModel.getBday());
    
    //update the name
    views.setTextViewText(R.id.bdw_w_days,
            Long.toString(widgetModel.howManyDays()));
    
    Intent defineIntent = new Intent(Intent.ACTION_VIEW, 
            Uri.parse("http://www.google.com"));
            
    PendingIntent pendingIntent = 
        PendingIntent.getActivity(context,
                    0 /* no requestCode */, 
                    defineIntent, 
                    0 /* no flags */);
    views.setOnClickPendingIntent(R.id.bdw_w_button_buy, pendingIntent);
    
    // Tell the widget manager
    appWidgetManager.updateAppWidget(widgetModel.iid, views);
}

satya - Tuesday, March 01, 2011 9:01:54 AM

whats new in widgets in honeycomb

Quoting from Google

Home screen widgets are popular with users because they offer fast access to application-specific data directly from the home screen. Android 3.0 lets developers take home screen widgets to the next level, offering more types of content and new modes of interaction with users. Developers can now use more standard UI widget types home screen widgets, including widgets that let users flip through collections of content as 3D stacks, grids, or lists. Users can interact with the home screen widgets in new ways, such as by using touch gestures to scroll and flip the content displayed in a widget

satya - Tuesday, March 01, 2011 9:03:00 AM

explicitly stated new widgets


3d stack
grids
lists

satya - Tuesday, March 01, 2011 9:27:47 AM

RemoteViews.RemoteView

RemoteViews.RemoteView

Search for: RemoteViews.RemoteView

satya - Tuesday, March 01, 2011 9:34:29 AM

As of 2.3 the allowed remote views are

As of 2.3 the allowed remote views are

Go to android.widget.RemoteViews.Remoteview
click "use"

satya - Tuesday, March 01, 2011 9:36:23 AM

as of 2.3 these are


absolutelayout
framelayout
linearlayout
relativelayout

analogclock
button
chronometer
datetimeview
imagebutton
iamgeview
progressbar
textview
viewflipper

satya - Tuesday, March 01, 2011 9:57:56 AM

You can also do this with eclipse


highlight RemoteView
References
in Project

satya - Tuesday, March 01, 2011 9:59:44 AM

The allowed views that are remote are


absolutelayout
framelayout
linearlayout
relativelayout

analogclock
button
chronometer
imagebutton
progressbar

Gridview
stackview
textview
datetimeview
iamgeview

AdapterViewFlipper
viewflipper

satya - Friday, March 04, 2011 1:50:13 PM

A List RemoteView: wiget provider responsiblities


//basic setup
load the layout with the list view in it
identify the list view with an id
set a remote adapter factory for the list view id

//setup an onclick callback with an action
Configure an intent to self invoke
create a pending intent out of this intent
  pending intent needs to be be uniquie for this widget id
call setOnClickPendingIntentTemplate
  set this pending intent for any list item click

//provide a custom onreceive
override onreceive to get this special pendign intent
define a special action for this pending intent
for all other actions call the base onreceive

satya - Friday, March 04, 2011 1:50:43 PM

A List RemoteView: list view factory responsiblities


provide a list item view 
  this view goes inside the list
create an intent with extras pointing to this row
pass the intent through setOnClickFillIntent
  this row information will then be attached
  to the previous pending intent template

satya - Friday, March 04, 2011 1:51:14 PM

working with custom actions in the widget provider


//Define an action string in your provider
public static final String ACTION_LIST_CLICK = 
    "com.androidbook.homewidgets.listclick";

//Override your onReceive to specialize it    
@Override
public void onReceive(Context context, Intent intent) 
{
    if (intent.getAction().equals(BDayWidgetProvider.ACTION_LIST_CLICK))
    {
        //this action is not one widget actions
        //this is a specific action that is directed here
        dealwithListAction(context,intent);
        return;
    }
    
    //make sure you call this 
    super.onReceive(context, intent);
}
public void dealwithListAction(Context context, Intent  intent)
{
    Toast t = Toast.makeText(context,"Clicked",Toast.LENGTH_SHORT);
    t.show();
}

satya - Friday, March 04, 2011 1:51:46 PM

Setting up a list remoteveiw onclick to trigger a custom event


//setup a list view call back
//we need a pending intent that is unique for this widget id
//send a message to ourselves which we will catch in OnReceive
Intent onListClickIntent = new Intent(context,BDayWidgetProvider.class);
//set an action so that this receiver can distinguish it
//from other widget related actions
onListClickIntent.setAction(BDayWidgetProvider.ACTION_LIST_CLICK);

//because this receiver serves all instances of this app widget
//we need to know which specific instance this message is targeted for
onListClickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);

//Make this intent unique as we are getting ready
//to create a pending intent with it
//The touri method loads the extras as part of the uri string
//the data of this intent is not used at all except
//to establish this intent as a unique pending intent.
//See intent.filteEquals() method to see how intents are compared
//to see if they are unique.
onListClickIntent.setData(
    Uri.parse(
        onListClickIntent.toUri(Intent.URI_INTENT_SCHEME)));

//we need to deliver this intent later when
//the remote view is clicked as a broadcast intent
//to this same receiver.
final PendingIntent onListClickPendingIntent = 
    PendingIntent.getBroadcast(context, 0,                    
        onListClickIntent, 
        PendingIntent.FLAG_UPDATE_CURRENT); 

//Set this pending intent as a template for
//the list item view.
//Each view in the list will then need to specify
//a set of additional extras to be appended to this template
//and then broadcast the final template.
//See how the remoteviewsfactory() sets up the each item
//in the list remoteview.
//See also docs for RemoteViews.setFillIntent()
rv.setPendingIntentTemplate(R.id.bdw_list_view_id, 
        onListClickPendingIntent);

satya - Friday, March 04, 2011 2:03:46 PM

Loading the list item and preparing it for the on click


public RemoteViews getViewAt(int position) 
{        
    RemoteViews rv = 
    new RemoteViews(this.mContext.getPackageName(),
                          R.layout.item_layout);
                          
    this.loadItemOnClickExtras(rv, position);
    return rv;
}    

private void loadItemOnClickExtras(RemoteViews rv, int position)
{
    Intent ei = new Intent();
    ei.putExtra(BDayWidgetProvider.ACTION_LIST_ITEM_TEXT,
                                           "Hello:" + position);
    rv.setOnClickFillInIntent(R.id.widget_list_item_id, ei);
    return;
}

satya - Friday, March 04, 2011 2:04:31 PM

Here is the view definition for the list item


<?xml version="1.0" encoding="utf-8"?>
<TextView  xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/widget_list_item_id"
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Temporary"
/>

satya - Saturday, March 05, 2011 10:08:01 AM

Bottom line what is new in widgets for 3.0?


There a number of new remoteviews
  Main ones are: 
    ListView
    GridView

There are two classes introduced to support collection views
  RemoteViewService
  RemoteViewsFactory

There are two new methods to support list clciks
  setOnClickPendingIntentTemplate()
  setOnClickFillIntent

satya - Saturday, March 05, 2011 10:17:17 AM

Since API 3 you can choose to cancel the appwidget creation

Since API 3 you can choose to cancel the appwidget creation

you need to return result_cancelled. However if you press back it is not clear if this is deemed as result_cancel. I haven't checked. It should. but not sure.

satya - Saturday, March 05, 2011 10:24:40 AM

Couple of newer apis


notifyAppWidgetViewDataChanged
: The view is a collection view
partiallyUpdateAppWidget
: for thsi call the view state is not restored

satya - Saturday, March 05, 2011 10:26:01 AM

View state of remoteviews

AppWidgetManager will save teh remoteviews and restores them on configuration changes.

satya - Saturday, March 05, 2011 10:36:12 AM

it would be nice to have

a way for a package to explicily list and remove their widgets (essentially a cleanup operation)

Right now I can list the widgets but I have no way of removing them. May be that is a prerogative of the host?? But still as a package I would probably want to know.

satya - Tuesday, December 13, 2011 10:24:29 PM

Read up on RemoteViews service and factory at this link

Read up on RemoteViews service and factory at this link to get a full picture of how list widgets work.