summaryrefslogtreecommitdiffstats
path: root/docs/html/guide/topics/appwidgets/index.jd
blob: 7e031d9daaacc423d8b838a49b7b948ecb4c5b88 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
page.title=App Widgets
@jd:body

<div id="qv-wrapper">
  <div id="qv">
    <h2>Quickview</h2>
    <ul>
      <li>App Widgets provide users access to some of your application features
directly from the Home screen (without the need to launch an activity)</li>
      <li>App Widgets are backed by a special kind of broadcast receiver that
handles the App
Widget lifecycle</li>
    </ul>
    
    <h2>In this document</h2>
    <ol>
      <li><a href="#Basics">The Basics</a></li>
      <li><a href="#Manifest">Declaring an App Widget in the Manifest</a></li>
      <li><a href="#MetaData">Adding the AppWidgetProviderInfo Metadata</a></li>
      <li><a href="#CreatingLayout">Creating the App Widget Layout</a></li>
      <li><a href="#AppWidgetProvider">Using the AppWidgetProvider Class</a>
        <ol>
          <li><a href="#ProviderBroadcasts">Receiving App Widget broadcast
Intents</a></li>
        </ol>
      </li>
      <li><a href="#Configuring">Creating an App Widget Configuration
Activity</a>
        <ol>
          <li><a href="#UpdatingFromTheConfiguration">Updating the App Widget
from 
            the configuration Activity</a></li>
        </ol>
      </li>
      <li><a href="#preview">Setting a Preview Image</a></li>
      <li><a href="#collections">Using App Widgets with Collections</a>
        <ol>
          <li><a href="#collection_sample">Sample application</a></li>
          <li><a href="#implementing_collections">Implementing app widgets with
collections
</a></li>
          <li><a href="#fresh">Keeping Collection Data Fresh</a></li>
        </ol>   
      </li>
    </ol>

    <h2>Key classes</h2>
    <ol>
      <li>{@link android.appwidget.AppWidgetProvider}</li>
      <li>{@link android.appwidget.AppWidgetProviderInfo}</li>
      <li>{@link android.appwidget.AppWidgetManager}</li>
    </ol>
    
    <h2>See also</h2>
    <ol>
      <li><a
href="{@docRoot}guide/practices/ui_guidelines/widget_design.html">App Widget
Design 
        Guidelines</a></li>
      <li><a
href="http://android-developers.blogspot.com/2009/04/introducing-home-screen-
widgets-and.html">Introducing
        home screen widgets and the AppWidget framework &raquo;</a></li>
    </ol>
  </div>
</div>


<p>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.</p>

<img src="{@docRoot}images/appwidget.png" alt="" />

<p>This document describes how to publish an App Widget using an App Widget
provider.</p>


<h2 id="Basics">The Basics</h2>

<p>To create an App Widget, you need the following:</p>

<dl>
  <dt>{@link android.appwidget.AppWidgetProviderInfo} object</dt>
  <dd>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.</dd>
  <dt>{@link android.appwidget.AppWidgetProvider} class implementation</dt>
  <dd>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.</dd>
  <dt>View layout</dt>
  <dd>Defines the initial layout for the App Widget, defined in XML.</dd>
</dl>

<p>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.</p>

<p>The following sections describe how to setup each of these components.</p>


<h2 id="Manifest">Declaring an App Widget in the Manifest</h2>

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

<pre style="clear:right">
&lt;receiver android:name="ExampleAppWidgetProvider" >
    &lt;intent-filter>
        &lt;action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    &lt;/intent-filter>
    &lt;meta-data android:name="android.appwidget.provider"
               android:resource="@xml/example_appwidget_info" />
&lt;/receiver>
</pre>

<p>The <code>&lt;receiver&gt;</code> element requires the
<code>android:name</code> 
attribute, which specifies the {@link android.appwidget.AppWidgetProvider} used
by the App Widget.</p>

<p>The <code>&lt;intent-filter&gt;</code> element must include an
<code>&lt;action></code>
element with the <code>android:name</code> 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.</p>

<p>The <code>&lt;meta-data&gt;</code> element specifies the
{@link android.appwidget.AppWidgetProviderInfo} resource and requires the 
following attributes:</p>
<ul>
  <li><code>android:name</code> - Specifies the metadata name. Use
<code>android.appwidget.provider</code>
    to identify the data as the {@link android.appwidget.AppWidgetProviderInfo}
descriptor.</li>
  <li><code>android:resource</code> - Specifies the {@link
android.appwidget.AppWidgetProviderInfo} 
    resource location.</li>
</ul>


<h2 id="MetaData">Adding the AppWidgetProviderInfo Metadata</h2>

<p>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
<code>&lt;appwidget-provider></code> element and save it in the project's
<code>res/xml/</code> 
folder.</p>

<p>For example:</p>

<pre>
&lt;appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
    android:minWidth="294dp"
    android:minHeight="72dp"
    android:updatePeriodMillis="86400000"
    android:previewImage="@drawable/preview"
    android:initialLayout="@layout/example_appwidget"
    android:configure="com.example.android.ExampleAppWidgetConfigure" 
    android:resizeMode="horizontal|vertical">
&lt;/appwidget-provider>
</pre>

<p>Here's a summary of the <code>&lt;appwidget-provider></code> attributes:</p>
<ul>
  <li>The values for the <code>minWidth</code> and <code>minHeight</code>
    attributes specify the minimum amount of space the App Widget consumes
    <em>by default</em>. The default Home screen positions App Widgets in its
    window based on a grid of cells that have a defined height and width. If
    the values for an App Widget's minimum width or height don't match the
    dimensions of the cells, then the App Widget dimensions round
    <em>up</em> to the nearest cell size.
    <p>See the <a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html#anatomy_determining_size">
    App Widget Design Guidelines</a> for more information on sizing your App
    Widgets.</p>

    <p class="note"><strong>Note:</strong> To make your app widget portable
    across devices, your app widget's minimum size should never be larger
    than 4 x 4 cells.</p>
  </li>

  <li>The <code>minResizeWidth</code> and <code>minResizeHeight</code> attributes
    specify the App Widget's absolute minimum size. These values should specify
    the size below which the App Widget would be illegible or otherwise unusable.
    Using these attributes allows the user to resize the widget to a size that
    may be smaller than the default widget size defined by the
    <code>minWidth</code> and <code>minHeight</code> attributes.
    Introduced in Android 3.1.

    <p>See the <a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html#anatomy_determining_size">
    App Widget Design Guidelines</a> for more information on sizing your App
    Widgets.</p>
  </li>

  <li>The <code>updatePeriodMillis</code> attribute defines how often the App
Widget framework should request an update from the {@link
android.appwidget.AppWidgetProvider} by calling the 
{@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,android.appwidget.AppWidgetManager,int[]) onUpdate()} 
callback method. The actual update
is not guaranteed to occur exactly on time with this value and we suggest
updating as infrequently as possible&mdash;perhaps no more than once an hour to
conserve the battery. You might also allow the user to adjust the frequency in a
configuration&mdash;some people might want a stock ticker to update every 15
minutes, or maybe only four times a day. 
    	<p class="note"><strong>Note:</strong> If the device is asleep when it
is time for an update 
    	(as defined by <code>updatePeriodMillis</code>), then the device will
wake up in order 
    	to perform the update. If you don't update more than once per hour, this
probably won't 
    	cause significant problems for the battery life. If, however, you need
to update more 
    	frequently and/or you do not need to update while the device is asleep,
then you can instead 
    	perform updates based on an alarm that will not wake the device. To do
so, set an alarm with 
    	an Intent that your AppWidgetProvider receives, using the	{@link
android.app.AlarmManager}. 
    	Set the alarm type to either {@link
android.app.AlarmManager#ELAPSED_REALTIME} or 
    	{@link android.app.AlarmManager#RTC}, which will only
    	deliver the alarm when the device is awake. Then set
<code>updatePeriodMillis</code> to 
    	zero (<code>"0"</code>).</p>
  </li>
  <li>The <code>initialLayout</code> attribute points to the layout resource
that defines the
    App Widget layout.</li>
  <li>The <code>configure</code> attribute defines the {@link
android.app.Activity} to launch when
    the user adds the App Widget, in order for him or her to configure App
Widget properties. This is optional
    (read <a href="#Configuring">Creating an App Widget Configuration
Activity</a> below).</li>
    
   <li>The <code>previewImage</code> attribute specifies a preview of what the
app widget will look like after it's configured, which the user sees when
selecting the app widget. If not supplied, the user instead sees your
application's launcher icon. This field corresponds to the
<code>android:previewImage</code> attribute in the <code>&lt;receiver&gt;</code>
element in the <code>AndroidManifest.xml</code> file. For more discussion of
using <code>previewImage</code>, see <a href="#preview">Setting a Preview
Image</a>. Introduced in Android 3.0.</li>

   <li>The <code>autoAdvanceViewId</code> attribute specifies the view ID of the
app widget subview that should be auto-advanced by the widget's host. Introduced in Android 3.0.</li> 

<li>The <code>resizeMode</code> attribute specifies the rules by which a widget
can be resized. You use this attribute to make homescreen widgets
resizeable&mdash;horizontally, vertically, or on both axes. Users touch-hold a
widget to show its resize handles, then drag the horizontal and/or vertical
handles to change the size on the layout grid. Values for the
<code>resizeMode</code> attribute include "horizontal", "vertical", and "none".
To declare a widget as resizeable horizontally and vertically, supply the value
"horizontal|vertical". Introduced in Android 3.1.</li> </ul>

<p>See the {@link android.appwidget.AppWidgetProviderInfo} class for more
information on the
attributes accepted by the <code>&lt;appwidget-provider></code> element.</p>


<h2 id="CreatingLayout">Creating the App Widget Layout</h2>

<p>You must define an initial layout for your App Widget in XML and save it in
the project's
<code>res/layout/</code> 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
<a href="{@docRoot}guide/practices/ui_guidelines/widget_design.html">App Widget
Design 
Guidelines</a>.</p>

<p>Creating the App Widget layout is simple if you're
familiar with <a
href="{@docRoot}guide/topics/ui/declaring-layout.html">Layouts</a>.
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.</p>

<p>A RemoteViews object (and, consequently, an App Widget) can support the 
following layout classes:</p>

<ul class="nolist">
  <li>{@link android.widget.FrameLayout}</li>
  <li>{@link android.widget.LinearLayout}</li>
  <li>{@link android.widget.RelativeLayout}</li>
  <li>{@link android.widget.GridLayout}</li>
</ul>

<p>And the following widget classes:</p>
<ul class="nolist">
  <li>{@link android.widget.AnalogClock}</li>
  <li>{@link android.widget.Button}</li>
  <li>{@link android.widget.Chronometer}</li>
  <li>{@link android.widget.ImageButton}</li>
  <li>{@link android.widget.ImageView}</li>
  <li>{@link android.widget.ProgressBar}</li>
  <li>{@link android.widget.TextView}</li>
  <li>{@link android.widget.ViewFlipper}</li>
  <li>{@link android.widget.ListView}</li>
  <li>{@link android.widget.GridView}</li>
  <li>{@link android.widget.StackView}</li>
  <li>{@link android.widget.AdapterViewFlipper}</li>
</ul>

<p>Descendants of these classes are not supported.</p>

<p>RemoteViews also supports {@link android.view.ViewStub}, which is an invisible, zero-sized View you can use 
to lazily inflate layout resources at runtime.</p>


<h3 id="AddingMargins">Adding margins to App Widgets</h3>

<p>Widgets should not generally extend to screen edges and should not visually be flush with other widgets, so you should add margins on all sides around your widget frame.</p>

<p>As of Android 4.0, app widgets are automatically given padding between the widget frame and the app widget's bounding box to provide better alignment with other widgets and icons on the user's home screen. To take advantage of this strongly recommended behavior, set your application's <a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html">targetSdkVersion</a> to 14 or greater.</p>

<p>It's easy to write a single layout that has custom margins applied for earlier versions of the platform, and has no extra margins for Android 4.0 and greater:</p>

<ol>
  <li>Set your application's <code>targetSdkVersion</code> to 14 or greater.</li>
  <li>Create a layout such as the one below, that references a <a href="{@docRoot}guide/topics/resources/more-resources.html#Dimension">dimension resource</a> for its margins:

<pre>
&lt;FrameLayout
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  <strong>android:padding="@dimen/widget_margin"&gt;</strong>

  &lt;LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:background="@drawable/my_widget_background"&gt;
    &hellip;
  &lt;/LinearLayout&gt;

&lt;/FrameLayout&gt;
</pre>

  </li>
  <li>Create two dimensions resources, one in <code>res/values/</code> to provide the pre-Android 4.0 custom margins, and one in <code>res/values-v14/</code> to provide no extra padding for Android 4.0 widgets:

    <p><strong>res/values/dimens.xml</strong>:<br>
    <pre>&lt;dimen name="widget_margin"&gt;8dp&lt;/dimen&gt;</pre></p>

    <p><strong>res/values-v14/dimens.xml</strong>:<br>
    <pre>&lt;dimen name="widget_margin"&gt;0dp&lt;/dimen&gt;</pre></p>
  </li>
</ol>

<p>Another option is to simply build extra margins into your <a href="{@docRoot}guide/topics/graphics/2d-graphics.html#nine-patch">nine-patch</a> background assets by default, and provide different nine-patches with no margins for API level 14 or later.</p>


<h2 id="AppWidgetProvider">Using the AppWidgetProvider Class</h2>

<div class="sidebox-wrapper">
<div class="sidebox">
    <p>You must declare your AppWidgetProvider class implementation as a
broadcast receiver 
    using the <code>&lt;receiver></code> element in the AndroidManifest (see
    <a href="#Manifest">Declaring an App Widget in the Manifest</a> above).</p>
  </div>
</div>

<p>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:</p>

<dl>
  <dt>
  {@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,android.appwidget.AppWidgetManager,int[]) onUpdate()} 
</dt>
    <dd>This is called to update the App Widget at intervals defined by the
<code>updatePeriodMillis</code>
    attribute in the AppWidgetProviderInfo (see <a href="#MetaData">Adding the 
    AppWidgetProviderInfo Metadata</a> 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, <strong>this method is not called</strong> 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 <a href="#Configuring">Creating an App Widget Configuration
Activity</a> below.)</dd> 

<dt>
  {@link android.appwidget.AppWidgetProvider#onAppWidgetOptionsChanged onAppWidgetOptionsChanged()} 
</dt>
<dd>
This is called when the widget is first placed and any time the widget is resized. You can use this callback to show or hide content based on the widget's size ranges. You get the size ranges by calling {@link android.appwidget.AppWidgetManager#getAppWidgetOptions getAppWidgetOptions()}, which returns a  {@link android.os.Bundle} that includes the following:<br /><br />
<ul>
  <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MIN_WIDTH}&mdash;Contains 
the lower bound on the current width, in dp units, of a widget instance.</li>
  <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MIN_HEIGHT}&mdash;Contains 
the lower bound on the current height, in dp units, of a widget instance.</li>
  <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MAX_WIDTH}&mdash;Contains
 the upper bound on the current width, in dp units, of a widget instance.</li>
  <li>{@link android.appwidget.AppWidgetManager#OPTION_APPWIDGET_MAX_HEIGHT}&mdash;Contains 
the upper bound on the current width, in dp units, of a widget instance.</li>
</ul>

This callback was introduced in API Level 16 (Android 4.1). If you implement this callback, make sure that your app doesn't depend on it since it won't be called on older devices.
</dd>
  <dt>{@link android.appwidget.AppWidgetProvider#onDeleted(Context,int[])}</dt>
    <dd>This is called every time an App Widget is deleted from the App Widget
host.</dd>
  <dt>{@link android.appwidget.AppWidgetProvider#onEnabled(Context)}</dt>
    <dd>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.</dd> 
  <dt>{@link android.appwidget.AppWidgetProvider#onDisabled(Context)}</dt>
    <dd>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.</dd> 
  <dt>{@link android.appwidget.AppWidgetProvider#onReceive(Context,Intent)}</dt>
    <dd>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.</dd> 
</dl>

<p class="warning"><strong>Note:</strong> In Android 1.5, there is a known issue
in which the
<code>onDeleted()</code> 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 
<a
href="http://groups.google.com/group/android-developers/msg/e405ca19df2170e2">
Group post</a>
to receive the <code>onDeleted()</code> callback.
</p>

<p>The most important AppWidgetProvider callback is 
{@link android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()} 
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(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()} 
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:</p>

<pre>
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&lt;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);
        }
    }
}
</pre>

<p>This AppWidgetProvider defines only the 
{@link
android.appwidget.AppWidgetProvider#onUpdate(android.content.Context, android.appwidget.AppWidgetManager, int[]) onUpdate()} 
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
<code>appWidgetIds</code>, 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 <code>updatePeriodMillis</code> 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).</p>

<p class="note"><strong>Note:</strong> Because {@link
android.appwidget.AppWidgetProvider} is an extension of {@link
android.content.BroadcastReceiver}, your process is not guaranteed to keep
running after the callback methods return (see {@link
android.content.BroadcastReceiver} for information about the broadcast
lifecycle). 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[]) onUpdate()} 
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 <a href="{@docRoot}guide/practices/responsiveness.html">Application
Not Responding</a> (ANR) error. See the <a
href="http://code.google.com/p/wiktionary-android/source/browse/trunk/Wiktionary/src/com/example/android/wiktionary/WordWidget.java">Wiktionary sample's AppWidgetProvider</a> for an example of an App Widget running a {@link
android.app.Service}.</p>

<p>Also see the <a 
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetProvider.html">ExampleAppWidgetProvider.java</a>
sample class.</p>


<h3 id="ProviderBroadcasts">Receiving App Widget broadcast Intents</h3>

<p>{@link android.appwidget.AppWidgetProvider} is just a convenience class.  If
you would like
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 Intents you need to care about are as follows:</p>
<ul>
  <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_UPDATE}</li>
  <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_DELETED}</li>
  <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_ENABLED}</li>
  <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_DISABLED}</li>
  <li>{@link android.appwidget.AppWidgetManager#ACTION_APPWIDGET_OPTIONS_CHANGED}</li>
</ul>



<h2 id="Configuring">Creating an App Widget Configuration Activity</h2>

<p>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.</p>

<p>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:</p>

<pre>
&lt;activity android:name=".ExampleAppWidgetConfigure">
    &lt;intent-filter>
        &lt;action android:name="android.appwidget.action.APPWIDGET_CONFIGURE"/>
    &lt;/intent-filter>
&lt;/activity>
</pre>

<p>Also, the Activity must be declared in the AppWidgetProviderInfo XML file,
with the 
<code>android:configure</code> attribute (see <a href="#MetaData">Adding 
the AppWidgetProviderInfo Metadata</a> above). For example, the configuration
Activity
can be declared like this:</p>

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

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

<p>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:</p>
<ul>
  <li>The App Widget host calls the configuration Activity and the configuration
Activity should always 
    return a result. The result should include the App Widget ID
    passed by the Intent that launched the Activity (saved in the Intent extras
as
    {@link android.appwidget.AppWidgetManager#EXTRA_APPWIDGET_ID}).</li>
  <li>The 
  {@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()} 
    method <strong>will not be called</strong> when the App Widget
is created
    (the system will not send the ACTION_APPWIDGET_UPDATE broadcast when a
configuration Activity
    is launched). It is the responsibility of the configuration Activity to
request an update from the 
    AppWidgetManager when the App Widget is first created. However, 
{@link android.appwidget.AppWidgetProvider#onUpdate(Context,AppWidgetManager,int[]) onUpdate()} 
    will be called for subsequent updates&mdash;it is only skipped
the first time.</li>
</ul>

<p>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.</p>


<h3 id="UpdatingFromTheConfiguration">Updating the App Widget from the
configuration Activity</h3>

<p>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}.</p>

<p>Here's a summary of the procedure to properly update the App Widget and close
the configuration Activity:</p>

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

<p class="note"><strong>Tip:</strong> 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.</p>

<p>See the <a 
href="{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/appwidget/ExampleAppWidgetConfigure.html">ExampleAppWidgetConfigure.java</a>
sample class in ApiDemos for an example.</p>

<h2 id="preview">Setting a Preview Image</h2>

<p>Android 3.0 introduces the {@link


android.appwidget.AppWidgetProviderInfo#previewImage} field, which specifies a
preview of what the app widget looks like. This preview is shown to the user from the
widget picker. If this field is not supplied, the app widget's icon is used for
the preview.</p> 

<p>This is how you specify this setting in XML:</p>

<pre>&lt;appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
  ...
  android:previewImage="@drawable/preview">
&lt;/appwidget-provider></pre>

<p>To help create a preview image for your app widget (to specify in the {@link
android.appwidget.AppWidgetProviderInfo#previewImage} field), the Android
emulator includes an application called &quot;Widget Preview.&quot; To create a
preview image, launch this application, select the app widget for your
application and set it up how you'd like your preview image to appear, then save
it and place it in your application's drawable resources.</p>

<h2 id="collections">Using App Widgets with Collections</h2>

<p>Android 3.0 introduces App Widgets with collections. These kinds of App
Widgets use the {@link android.widget.RemoteViewsService} to display collections
that are backed by remote data, such as from a <a
href="{@docRoot}guide/topics/providers/content-providers.html">content
provider</a>. The data provided by the {@link android.widget.RemoteViewsService}
is presented in the App Widget using one of the following view types, which
we’ll refer to as “collection views:”</p>

<dl>
  <dt>{@link android.widget.ListView}</dt>
  <dd>A view that shows items in a
vertically scrolling
list. For an example, see the Gmail app widget. </dd>
<dt>{@link android.widget.GridView}</dt>
<dd>A view that shows items in
two-dimensional scrolling grid. For an example, see the Bookmarks app
widget.</dd> 
<dt>{@link android.widget.StackView}</dt>
<dd>A
stacked card view (kind of like a rolodex), where the user can flick the  front
card up/down to see the previous/next card, respectively.  Examples include
the YouTube and Books app widgets. </dd> 
<dt>{@link android.widget.AdapterViewFlipper}</dt>
<dd>An adapter-backed simple
{@link
android.widget.ViewAnimator} that  animates between two or more views. Only one
child is shown at a time.  </dd>
</dl>

<p>As stated above, these collection views display collections backed by remote
data. This means that they use an {@link android.widget.Adapter} to bind their
user interface to their data. An {@link android.widget.Adapter} binds individual
items from a set of data into individual {@link android.view.View} objects.
Because these collection views are backed by adapters, the Android framework
must include extra architecture to support their use in app widgets. In the
context of an app widget, the {@link android.widget.Adapter} is replaced by a
{@link android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory},
which is simply a thin wrapper around  the {@link android.widget.Adapter}
interface. 
 When
requested for a specific item in the collection, the {@link
android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} creates
and returns the item for the collection as a {@link android.widget.RemoteViews}
object.
In order to include a collection view in your app widget, you
must implement {@link android.widget.RemoteViewsService} and {@link
android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}.</p>

<p> {@link android.widget.RemoteViewsService} is a service that allows a remote
adapter to request {@link
android.widget.RemoteViews} objects. {@link
android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} is an
interface for an adapter between a collection view (such as {@link
android.widget.ListView}, {@link android.widget.GridView}, and so on) and the
underlying data for that view. From the  <a
href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
sample</a>, here is an example of the boilerplate code you use to implement 
this service and interface:
</p>

<pre>
public class StackWidgetService extends RemoteViewsService {
    &#64;Override
    public RemoteViewsFactory onGetViewFactory(Intent intent) {
        return new StackRemoteViewsFactory(this.getApplicationContext(), intent);
    }
}

class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {

//... include adapter-like methods here. See the StackView Widget sample.

}
</pre>

<h3 id="collection_sample">Sample application</h3>

<p>The code excerpts in this section are drawn from the <a
href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
sample</a>:</p>

<p>
<img src="{@docRoot}resources/images/StackWidget.png" alt="" />
</p>

<p>This sample consists of a stack of 10 views, which  display the values
<code>&quot;0!&quot;</code> through <code>&quot;9!&quot;</code> The sample
app widget has these primary behaviors:</p> 

<ul>

  <li>The user can vertically fling the top view in the
app widget to display the next or previous view. This is a built-in StackView
behavior.</li> 

  <li>Without any user interaction, the app widget automatically advances
through
its views in sequence, like a slide show. This is due to the setting
<code>android:autoAdvanceViewId=&quot;@id/stack_view&quot;</code> in the
<code>res/xml/stackwidgetinfo.xml</code> file. This setting applies to the view
ID,
which in this case is the view ID of the stack view.</li>
  
  <li>If the user touches the top view, the app widget displays the {@link
android.widget.Toast} message &quot;Touched view <em>n</em>,&quot; where
<em>n</em> is the index (position) of the touched view. For more discussion of
how this is implemented, see  
<a href="#behavior">Adding behavior to individual items</a>.</li>

</ul>
<h3 id="implementing_collections">Implementing app widgets with collections</h3>

<p>To implement an App Widget with collections, you follow the same basic steps 
you would use to implement any app widget. The following sections  describe the
additional steps you need to perform to implement an App Widget with
collections.</p>

<h4>Manifest for app widgets with collections</h4>

<p> In addition to the requirements listed in <a href="#Manifest">Declaring an
App Widget in the Manifest</a>, to make it possible for App Widgets with
collections to bind to your {@link android.widget.RemoteViewsService}, you must
declare the service in your manifest file with the permission {@link
android.Manifest.permission#BIND_REMOTEVIEWS}. This prevents other applications
from freely accessing your app widget's data. For example, when creating an App
Widget that uses {@link android.widget.RemoteViewsService} to populate a
collection view, the manifest entry may look like this:</p>

<pre>&lt;service android:name=&quot;MyWidgetService&quot;
...
android:permission=&quot;android.permission.BIND_REMOTEVIEWS&quot; /&gt;</pre>

<p>The line <code>android:name=&quot;MyWidgetService&quot;</code>
refers to your subclass of {@link android.widget.RemoteViewsService}. </p>

<h4>Layout for app widgets with collections</h4>

<p>The main requirement for your app widget layout XML file is that it
include one of the collection views: {@link android.widget.ListView},
{@link android.widget.GridView}, {@link android.widget.StackView}, or
{@link android.widget.AdapterViewFlipper}. Here is the
<code>widget_layout.xml</code> for
the <a href="{@docRoot}resources/samples/StackWidget/index.html">StackView
Widget sample</a>:</p>

<pre>&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;

&lt;FrameLayout xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
    android:layout_width=&quot;match_parent&quot;
    android:layout_height=&quot;match_parent&quot;&gt;
    &lt;StackView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
        android:id=&quot;&#64;+id/stack_view&quot;
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot;
        android:gravity=&quot;center&quot;
        android:loopViews=&quot;true&quot; /&gt;
    &lt;TextView xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;
        android:id=&quot;&#64;+id/empty_view&quot;
        android:layout_width=&quot;match_parent&quot;
        android:layout_height=&quot;match_parent&quot;
        android:gravity=&quot;center&quot;
        android:background=&quot;&#64;drawable/widget_item_background&quot;
        android:textColor=&quot;#ffffff&quot;
        android:textStyle=&quot;bold&quot;
        android:text=&quot;&#64;string/empty_view_text&quot;
        android:textSize=&quot;20sp&quot; /&gt;
&lt;/FrameLayout&gt;</pre>

<p> Note that empty views must be siblings of the collection view for which the
empty view represents empty state. </p>

<p>In addition to the layout file for your entire app widget, you must create
another layout file that defines the layout for each item in the collection (for
example, a layout for each book in a collection of books). For example, the <a
href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
sample</a> only has one layout file, <code>widget_item.xml</code>, since all
items use the same layout. But the <a
href="{@docRoot}resources/samples/WeatherListWidget/index.html">
WeatherListWidget sample</a> has two layout files:
<code>dark_widget_item.xml</code> and <code>light_widget_item.xml</code>.</p>



<h4 id="AppWidgetProvider-collections">AppWidgetProvider class for app widgets with collections</h4>

<p>As with a regular app widget, the bulk of your code in your {@link
android.appwidget.AppWidgetProvider} subclass typically goes in {@link
android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,
android.appwidget.AppWidgetManager, int[]) onUpdate()}. The major difference in
your implementation for {@link
android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,
android.appwidget.AppWidgetManager, int[]) onUpdate()} when creating an app
widget with collections is that you must call {@link
android.widget.RemoteViews#setRemoteAdapter setRemoteAdapter()}. This tells the
collection view where to get its data. The {@link
android.widget.RemoteViewsService} can then return your implementation of {@link
android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}, and
the widget can serve up the appropriate data. When you call this method, you
must pass an intent that  points to your implementation of {@link
android.widget.RemoteViewsService} and the App Widget ID that specifies the app
widget to update.</p>


<p>For example, here's how the StackView Widget sample implements the {@link
android.appwidget.AppWidgetProvider#onUpdate(android.content.Context,
android.appwidget.AppWidgetManager, int[]) onUpdate()} callback method to set
the {@link
android.widget.RemoteViewsService} as the remote adapter for the app widget
collection:</p>

<pre>public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
    // update each of the app widgets with the remote adapter
    for (int i = 0; i &lt; appWidgetIds.length; ++i) {
        
        // Set up the intent that starts the StackViewService, which will
        // provide the views for this collection.
        Intent intent = new Intent(context, StackWidgetService.class);
        // Add the app widget ID to the intent extras.
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
        intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
        // Instantiate the RemoteViews object for the App Widget layout.
        RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
        // Set up the RemoteViews object to use a RemoteViews adapter. 
        // This adapter connects
        // to a RemoteViewsService  through the specified intent.
        // This is how you populate the data.
        rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent);
        
        // The empty view is displayed when the collection has no items. 
        // It should be in the same layout used to instantiate the RemoteViews
        // object above.
        rv.setEmptyView(R.id.stack_view, R.id.empty_view);

        //
        // Do additional processing specific to this app widget...
        //
        
        appWidgetManager.updateAppWidget(appWidgetIds[i], rv);   
    }
    super.onUpdate(context, appWidgetManager, appWidgetIds);
}</pre>
            
<h4>RemoteViewsService class</h4>

<div class="sidebox-wrapper">
<div class="sidebox">
<h3>Persisting data</h3>
   <p>You can’t rely on a single instance of your service, or any data it
contains, to persist. You should therefore not store any data in your {@link
android.widget.RemoteViewsService} (unless it is static). If you want your
app widget’s data to persist, the best approach is to use a {@link
android.content.ContentProvider} whose data persists beyond the process
lifecycle.</p> </div>
</div>

<p>As described above, your {@link android.widget.RemoteViewsService} subclass
provides the {@link android.widget.RemoteViewsService.RemoteViewsFactory
RemoteViewsFactory} used to  populate the remote collection view.</p> 

<p>Specifically, you need to
perform these steps:</p>

<ol>
  <li>Subclass {@link android.widget.RemoteViewsService}. {@link
android.widget.RemoteViewsService} is the service through which
a remote adapter can request {@link android.widget.RemoteViews}.  </li>
  
  <li>In your {@link android.widget.RemoteViewsService} subclass, include a
class that implements the {@link
android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
interface. {@link android.widget.RemoteViewsService.RemoteViewsFactory
RemoteViewsFactory} is an interface for an adapter between a remote collection
view (such as {@link android.widget.ListView}, {@link android.widget.GridView},
and so on) and  the underlying data for that view.  Your implementation is
responsible for making a {@link android.widget.RemoteViews} object  for each
item in the data set. This interface is a thin wrapper around {@link
android.widget.Adapter}.</li>
</ol>

<p>The primary contents of the {@link android.widget.RemoteViewsService}
implementation is its {@link
android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory},
described below.</p>

<h4>RemoteViewsFactory interface</h4>

<p>Your custom class that implements the {@link
android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
interface provides the app widget with the data for the items in its collection.
To
do this, it combines your app widget item XML layout file with a source of data.
This source of data could be anything from a database to a simple array. In the
<a href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
sample</a>, the data source is an array of <code>WidgetItems</code>. The {@link
android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
functions as an adapter to glue the data to the remote collection view.</p>

<p>The two most important methods you need to implement for your

{@link android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
subclass are 
{@link android.widget.RemoteViewsService.RemoteViewsFactory#onCreate()
onCreate()} and
{@link android.widget.RemoteViewsService.RemoteViewsFactory#getViewAt(int)
getViewAt()}
.</p> 

<p>The system calls {@link
android.widget.RemoteViewsService.RemoteViewsFactory#onCreate() onCreate()} when
creating your factory for the first time. This is where you set up any
connections and/or cursors to your data source. For example, the <a
href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
sample</a> uses {@link
android.widget.RemoteViewsService.RemoteViewsFactory#onCreate() onCreate()} to
initialize an array of <code>WidgetItem</code> objects. When your app widget is
active, the system accesses these objects using their index position in the
array and the text they contain is displayed  </p>

<p>Here is an excerpt from the the <a
href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget</a>
sample's 
{@link android.widget.RemoteViewsService.RemoteViewsFactory
RemoteViewsFactory} implementation that shows portions of the {@link
android.widget.RemoteViewsService.RemoteViewsFactory#onCreate() onCreate()}
method:</p>

<pre>class StackRemoteViewsFactory implements
RemoteViewsService.RemoteViewsFactory {
    private static final int mCount = 10;
    private List&lt;WidgetItem&gt; mWidgetItems = new ArrayList&lt;WidgetItem&gt;();
    private Context mContext;
    private int mAppWidgetId;

    public StackRemoteViewsFactory(Context context, Intent intent) {
        mContext = context;
        mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                AppWidgetManager.INVALID_APPWIDGET_ID);
    }

    public void onCreate() {
        // In onCreate() you setup any connections / cursors to your data source. Heavy lifting,
        // for example downloading or creating content etc, should be deferred to onDataSetChanged()
        // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR.
        for (int i = 0; i &lt; mCount; i++) {
            mWidgetItems.add(new WidgetItem(i + &quot;!&quot;));
        }
        ...
    }
...</pre>

<p>The {@link android.widget.RemoteViewsService.RemoteViewsFactory
RemoteViewsFactory} method {@link
android.widget.RemoteViewsService.RemoteViewsFactory#getViewAt(int) getViewAt()}
returns a {@link android.widget.RemoteViews} object corresponding to the data at
the specified <code>position</code> in the data set. Here is an excerpt from 
the <a
href="http://developer.android.com/resources/samples/StackWidget/index.html">
StackView Widget</a> sample's {@link
android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}
implementation:</p>

<pre>public RemoteViews getViewAt(int position) {
   
    // Construct a remote views item based on the app widget item XML file, 
    // and set the text based on the position.
    RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
    rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);

    ...
    // Return the remote views object.
    return rv;
}</pre>

<h4 id="behavior">Adding behavior to individual items</h4>

<p>The above sections show you how to bind your data to your app widget
collection. But what if you want to add dynamic behavior to the individual items
in your collection view?</p> 

<p> As described in <a href="#AppWidgetProvider">Using the AppWidgetProvider
Class</a>, you  normally use {@link
android.widget.RemoteViews#setOnClickPendingIntent(int,
android.app.PendingIntent) setOnClickPendingIntent()} to set an object's click
behavior&mdash;such as to cause a button to launch an {@link
android.app.Activity}. But this approach is not allowed for child views in an
individual collection item (to clarify, you could use {@link
android.widget.RemoteViews#setOnClickPendingIntent(int,
android.app.PendingIntent) setOnClickPendingIntent()} to set up a global button
in the Gmail app widget that launches the app, for example, but not on the
individual list items). Instead, to add click behavior to individual items in a
collection, you  use {@link
android.widget.RemoteViews#setOnClickFillInIntent(int, android.content.Intent)
setOnClickFillInIntent()}. This entails setting up up a pending intent template
for your collection view, and then setting a fill-in intent on each item in the
collection via your {@link android.widget.RemoteViewsService.RemoteViewsFactory
RemoteViewsFactory}.</p> 
<p>This section uses the <a
href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
sample</a> to describe how to add behavior to individual items. In the <a
href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
sample</a>, if the user touches the top view, the app widget displays the {@link
android.widget.Toast} message &quot;Touched view <em>n</em>,&quot; where
<em>n</em> is the index (position) of the touched view. This is how it
works:</p>

<ul>
  <li>The <code>StackWidgetProvider</code> (an {@link
android.appwidget.AppWidgetProvider} subclass) creates a pending intent that has
a custom action called <code>TOAST_ACTION</code>.</li>
  <li>When the user touches a view, the intent is fired and it broadcasts
<code>TOAST_ACTION</code>.</li>
  
  <li>This broadcast is intercepted by the <code>StackWidgetProvider</code>'s
{@link android.appwidget.AppWidgetProvider#onReceive(android.content.Context,
android.content.Intent) onReceive()} method, and the app widget displays the
{@link
android.widget.Toast} message for the touched view. The data for the collection
items is provided by the {@link
android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}, via
the {@link android.widget.RemoteViewsService}.</li>
</ul>

<p class="note"><strong>Note:</strong> The <a
href="{@docRoot}resources/samples/StackWidget/index.html">StackView Widget
sample</a> uses a broadcast, but typically an app widget would simply launch an
activity in a scenario like this one.</p>

<h5>Setting up the pending intent template</h5> 

<p>The <code>StackWidgetProvider</code> ({@link
android.appwidget.AppWidgetProvider} subclass) sets up a pending intent.
Individuals items of a collection cannot set up their own pending intents.
Instead, the collection as a whole sets up a pending intent template, and the
individual items set a fill-in intent to create unique behavior on an
item-by-item
basis.</p> 

<p>This class  also receives the broadcast that is sent when the user touches a
view. It processes this event in its {@link
android.appwidget.AppWidgetProvider#onReceive(android.content.Context,
android.content.Intent) onReceive()} method. If the intent's action is
<code>TOAST_ACTION</code>, the app widget displays a {@link
android.widget.Toast}
message for the current view.</p>

<pre>public class StackWidgetProvider extends AppWidgetProvider {
    public static final String TOAST_ACTION = &quot;com.example.android.stackwidget.TOAST_ACTION&quot;;
    public static final String EXTRA_ITEM = &quot;com.example.android.stackwidget.EXTRA_ITEM&quot;;

    ...

    // Called when the BroadcastReceiver receives an Intent broadcast.
    // Checks to see whether the intent's action is TOAST_ACTION. If it is, the app widget 
    // displays a Toast message for the current item.
    &#64;Override
    public void onReceive(Context context, Intent intent) {
        AppWidgetManager mgr = AppWidgetManager.getInstance(context);
        if (intent.getAction().equals(TOAST_ACTION)) {
            int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                AppWidgetManager.INVALID_APPWIDGET_ID);
            int viewIndex = intent.getIntExtra(EXTRA_ITEM, 0);
            Toast.makeText(context, &quot;Touched view &quot; + viewIndex, Toast.LENGTH_SHORT).show();
        }
        super.onReceive(context, intent);
    }
    
    &#64;Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // update each of the app widgets with the remote adapter
        for (int i = 0; i &lt; appWidgetIds.length; ++i) {
    
            // Sets up the intent that points to the StackViewService that will
            // provide the views for this collection.
            Intent intent = new Intent(context, StackWidgetService.class);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
            // When intents are compared, the extras are ignored, so we need to embed the extras
            // into the data so that the extras will not be ignored.
            intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
            RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
            rv.setRemoteAdapter(appWidgetIds[i], R.id.stack_view, intent);
    
            // The empty view is displayed when the collection has no items. It should be a sibling
            // of the collection view.
            rv.setEmptyView(R.id.stack_view, R.id.empty_view);

            // This section makes it possible for items to have individualized behavior.
            // It does this by setting up a pending intent template. Individuals items of a collection
            // cannot set up their own pending intents. Instead, the collection as a whole sets
            // up a pending intent template, and the individual items set a fillInIntent
            // to create unique behavior on an item-by-item basis.
            Intent toastIntent = new Intent(context, StackWidgetProvider.class);
            // Set the action for the intent.
            // When the user touches a particular view, it will have the effect of
            // broadcasting TOAST_ACTION.
            toastIntent.setAction(StackWidgetProvider.TOAST_ACTION);
            toastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetIds[i]);
            intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
            PendingIntent toastPendingIntent = PendingIntent.getBroadcast(context, 0, toastIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);
            rv.setPendingIntentTemplate(R.id.stack_view, toastPendingIntent);
            
            appWidgetManager.updateAppWidget(appWidgetIds[i], rv);
        }
    super.onUpdate(context, appWidgetManager, appWidgetIds);
    }
}</pre>
            
<h5><strong>Setting the fill-in Intent</strong></h5>

<p>Your {@link android.widget.RemoteViewsService.RemoteViewsFactory
RemoteViewsFactory} must set a fill-in intent on each item in the collection.
This makes it possible to distinguish the individual on-click action of a given
item. The fill-in intent is then combined with the {@link
android.app.PendingIntent} template in order to determine the final intent that
will be executed when the item is clicked. </p>

<pre>
public class StackWidgetService extends RemoteViewsService {
    &#64;Override
    public RemoteViewsFactory onGetViewFactory(Intent intent) {
        return new StackRemoteViewsFactory(this.getApplicationContext(), intent);
    }
}

class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
    private static final int mCount = 10;
    private List&lt;WidgetItem&gt; mWidgetItems = new ArrayList&lt;WidgetItem&gt;();
    private Context mContext;
    private int mAppWidgetId;

    public StackRemoteViewsFactory(Context context, Intent intent) {
        mContext = context;
        mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
                AppWidgetManager.INVALID_APPWIDGET_ID);
    }

    // Initialize the data set.
        public void onCreate() {
            // In onCreate() you set up any connections / cursors to your data source. Heavy lifting,
            // for example downloading or creating content etc, should be deferred to onDataSetChanged()
            // or getViewAt(). Taking more than 20 seconds in this call will result in an ANR.
            for (int i = 0; i &lt; mCount; i++) {
                mWidgetItems.add(new WidgetItem(i + &quot;!&quot;));
            }
           ...
        }
        ...
    
        // Given the position (index) of a WidgetItem in the array, use the item's text value in 
        // combination with the app widget item XML file to construct a RemoteViews object.
        public RemoteViews getViewAt(int position) {
            // position will always range from 0 to getCount() - 1.
    
            // Construct a RemoteViews item based on the app widget item XML file, and set the
            // text based on the position.
            RemoteViews rv = new RemoteViews(mContext.getPackageName(), R.layout.widget_item);
            rv.setTextViewText(R.id.widget_item, mWidgetItems.get(position).text);
    
            // Next, set a fill-intent, which will be used to fill in the pending intent template
            // that is set on the collection view in StackWidgetProvider.
            Bundle extras = new Bundle();
            extras.putInt(StackWidgetProvider.EXTRA_ITEM, position);
            Intent fillInIntent = new Intent();
            fillInIntent.putExtras(extras);
            // Make it possible to distinguish the individual on-click
            // action of a given item
            rv.setOnClickFillInIntent(R.id.widget_item, fillInIntent);
        
            ...
        
            // Return the RemoteViews object.
            return rv;
        }
    ...
    }</pre>

<h3 id="fresh">Keeping Collection Data Fresh</h3>

<p>The following figure illustrates the flow that occurs in an App Widget that
uses
collections when updates occur. It shows how the App Widget code interacts with
the  {@link android.widget.RemoteViewsService.RemoteViewsFactory
RemoteViewsFactory}, and how you can trigger updates:</p>

<img src="{@docRoot}images/appwidget_collections.png" alt="" />

<p>One feature of App Widgets that use collections is the ability to provide
users with up-to-date content. For example, consider the Android 3.0 Gmail
app widget, which provides users with a snapshot of their inbox. To make this
possible, you need to be able to trigger your {@link
android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory} and
collection view to fetch and display new data. You achieve this with the {@link
android.appwidget.AppWidgetManager} call {@link
android.appwidget.AppWidgetManager#notifyAppWidgetViewDataChanged(int, int)
notifyAppWidgetViewDataChanged()}. This call results in a callback to your
<code>RemoteViewsFactory</code>’s {@link
android.widget.RemoteViewsService.RemoteViewsFactory#onDataSetChanged()
onDataSetChanged()} method, which gives you the opportunity to fetch any new
data. Note that you can perform
processing-intensive operations synchronously within the  {@link
android.widget.RemoteViewsService.RemoteViewsFactory#onDataSetChanged()
onDataSetChanged()} callback. You are guaranteed that this call will be
completed before the metadata or view data is fetched from the {@link
android.widget.RemoteViewsService.RemoteViewsFactory RemoteViewsFactory}. In
addition, you can perform processing-intensive operations within the {@link
android.widget.RemoteViewsService.RemoteViewsFactory#getViewAt(int) getViewAt()}
method. If this call takes a long time, the loading view (specified by the
<code>RemoteViewsFactory</code>’s  {@link
android.widget.RemoteViewsService.RemoteViewsFactory#getLoadingView()} method)
will be displayed in the corresponding position of the collection view until it
returns.</p>