Skip to content

Commit 0aa2d42

Browse files
author
Adam Cohen
committed
Adding notion of keyguard widgets
-> Persisting certain appwidget options -> Adding ability to specify appwidget options on bind so as to avoid AppWidgetProvider update call with no options. Change-Id: I5631039f19f1822b8e123b559b6353c880c0192e
1 parent ce3ef0a commit 0aa2d42

File tree

9 files changed

+257
-21
lines changed

9 files changed

+257
-21
lines changed

api/current.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ package android {
555555
field public static final int indicatorRight = 16843022; // 0x101010e
556556
field public static final int inflatedId = 16842995; // 0x10100f3
557557
field public static final int initOrder = 16842778; // 0x101001a
558+
field public static final int initialKeyguardLayout = 16843714; // 0x10103c2
558559
field public static final int initialLayout = 16843345; // 0x1010251
559560
field public static final int innerRadius = 16843359; // 0x101025f
560561
field public static final int innerRadiusRatio = 16843163; // 0x101019b
@@ -1120,6 +1121,7 @@ package android {
11201121
field public static final int weekNumberColor = 16843589; // 0x1010345
11211122
field public static final int weekSeparatorLineColor = 16843590; // 0x1010346
11221123
field public static final int weightSum = 16843048; // 0x1010128
1124+
field public static final int widgetFeatures = 16843715; // 0x10103c3
11231125
field public static final int widgetLayout = 16843243; // 0x10101eb
11241126
field public static final int width = 16843097; // 0x1010159
11251127
field public static final int windowActionBar = 16843469; // 0x10102cd
@@ -4399,6 +4401,7 @@ package android.appwidget {
43994401

44004402
public class AppWidgetManager {
44014403
method public boolean bindAppWidgetIdIfAllowed(int, android.content.ComponentName);
4404+
method public boolean bindAppWidgetIdIfAllowed(int, android.content.ComponentName, android.os.Bundle);
44024405
method public int[] getAppWidgetIds(android.content.ComponentName);
44034406
method public android.appwidget.AppWidgetProviderInfo getAppWidgetInfo(int);
44044407
method public android.os.Bundle getAppWidgetOptions(int);
@@ -4428,6 +4431,7 @@ package android.appwidget {
44284431
field public static final java.lang.String EXTRA_CUSTOM_INFO = "customInfo";
44294432
field public static final int INVALID_APPWIDGET_ID = 0; // 0x0
44304433
field public static final java.lang.String META_DATA_APPWIDGET_PROVIDER = "android.appwidget.provider";
4434+
field public static final java.lang.String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory";
44314435
field public static final java.lang.String OPTION_APPWIDGET_MAX_HEIGHT = "appWidgetMaxHeight";
44324436
field public static final java.lang.String OPTION_APPWIDGET_MAX_WIDTH = "appWidgetMaxWidth";
44334437
field public static final java.lang.String OPTION_APPWIDGET_MIN_HEIGHT = "appWidgetMinHeight";
@@ -4454,9 +4458,15 @@ package android.appwidget {
44544458
field public static final int RESIZE_HORIZONTAL = 1; // 0x1
44554459
field public static final int RESIZE_NONE = 0; // 0x0
44564460
field public static final int RESIZE_VERTICAL = 2; // 0x2
4461+
field public static final int WIDGET_CATEGORY_HOME_SCREEN = 1; // 0x1
4462+
field public static final int WIDGET_CATEGORY_KEYGUARD = 2; // 0x2
4463+
field public static final int WIDGET_FEATURES_CLOCK = 1; // 0x1
4464+
field public static final int WIDGET_FEATURES_NONE = 0; // 0x0
4465+
field public static final int WIDGET_FEATURES_STATUS = 2; // 0x2
44574466
field public int autoAdvanceViewId;
44584467
field public android.content.ComponentName configure;
44594468
field public int icon;
4469+
field public int initialKeyguardLayout;
44604470
field public int initialLayout;
44614471
field public java.lang.String label;
44624472
field public int minHeight;
@@ -4467,6 +4477,8 @@ package android.appwidget {
44674477
field public android.content.ComponentName provider;
44684478
field public int resizeMode;
44694479
field public int updatePeriodMillis;
4480+
field public int widgetCategory;
4481+
field public int widgetFeatures;
44704482
}
44714483

44724484
}

core/java/android/appwidget/AppWidgetHostView.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,17 @@ protected View getDefaultView() {
513513
theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
514514
inflater = inflater.cloneInContext(theirContext);
515515
inflater.setFilter(sInflaterFilter);
516-
defaultView = inflater.inflate(mInfo.initialLayout, this, false);
516+
AppWidgetManager manager = AppWidgetManager.getInstance(mContext);
517+
Bundle options = manager.getAppWidgetOptions(mAppWidgetId);
518+
519+
int layoutId = mInfo.initialLayout;
520+
if (options.containsKey(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY)) {
521+
int category = options.getInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY);
522+
if (category == AppWidgetProviderInfo.WIDGET_CATEGORY_KEYGUARD) {
523+
layoutId = mInfo.initialKeyguardLayout;
524+
}
525+
}
526+
defaultView = inflater.inflate(layoutId, this, false);
517527
} else {
518528
Log.w(TAG, "can't inflate defaultView because mInfo is missing");
519529
}

core/java/android/appwidget/AppWidgetManager.java

Lines changed: 68 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,25 +150,33 @@ public class AppWidgetManager {
150150
public static final String EXTRA_APPWIDGET_ID = "appWidgetId";
151151

152152
/**
153-
* An bundle extra that contains the lower bound on the current width, in dips, of a widget instance.
153+
* A bundle extra that contains the lower bound on the current width, in dips, of a widget instance.
154154
*/
155155
public static final String OPTION_APPWIDGET_MIN_WIDTH = "appWidgetMinWidth";
156156

157157
/**
158-
* An bundle extra that contains the lower bound on the current height, in dips, of a widget instance.
158+
* A bundle extra that contains the lower bound on the current height, in dips, of a widget instance.
159159
*/
160160
public static final String OPTION_APPWIDGET_MIN_HEIGHT = "appWidgetMinHeight";
161161

162162
/**
163-
* An bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
163+
* A bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
164164
*/
165165
public static final String OPTION_APPWIDGET_MAX_WIDTH = "appWidgetMaxWidth";
166166

167167
/**
168-
* An bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
168+
* A bundle extra that contains the upper bound on the current width, in dips, of a widget instance.
169169
*/
170170
public static final String OPTION_APPWIDGET_MAX_HEIGHT = "appWidgetMaxHeight";
171171

172+
/**
173+
* A bundle extra that hints to the AppWidgetProvider the category of host that owns this
174+
* this widget. Can have the value {@link
175+
* AppWidgetProviderInfo#WIDGET_CATEGORY_HOME_SCREEN} or {@link
176+
* AppWidgetProviderInfo#WIDGET_CATEGORY_KEYGUARD}.
177+
*/
178+
public static final String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory";
179+
172180
/**
173181
* An intent extra which points to a bundle of extra information for a particular widget id.
174182
* In particular this bundle can contain EXTRA_APPWIDGET_WIDTH and EXTRA_APPWIDGET_HEIGHT.
@@ -568,7 +576,31 @@ public AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId) {
568576
*/
569577
public void bindAppWidgetId(int appWidgetId, ComponentName provider) {
570578
try {
571-
sService.bindAppWidgetId(appWidgetId, provider);
579+
sService.bindAppWidgetId(appWidgetId, provider, null);
580+
}
581+
catch (RemoteException e) {
582+
throw new RuntimeException("system server dead?", e);
583+
}
584+
}
585+
586+
/**
587+
* Set the component for a given appWidgetId.
588+
*
589+
* <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
590+
* widgets always for your component. This method is used by the AppWidget picker and
591+
* should not be used by other apps.
592+
*
593+
* @param appWidgetId The AppWidget instance for which to set the RemoteViews.
594+
* @param provider The {@link android.content.BroadcastReceiver} that will be the AppWidget
595+
* provider for this AppWidget.
596+
* @param options Bundle containing options for the AppWidget. See also
597+
* {@link #updateAppWidgetOptions(int, Bundle)}
598+
*
599+
* @hide
600+
*/
601+
public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options) {
602+
try {
603+
sService.bindAppWidgetId(appWidgetId, provider, options);
572604
}
573605
catch (RemoteException e) {
574606
throw new RuntimeException("system server dead?", e);
@@ -594,7 +626,37 @@ public boolean bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider)
594626
}
595627
try {
596628
return sService.bindAppWidgetIdIfAllowed(
597-
mContext.getPackageName(), appWidgetId, provider);
629+
mContext.getPackageName(), appWidgetId, provider, null);
630+
}
631+
catch (RemoteException e) {
632+
throw new RuntimeException("system server dead?", e);
633+
}
634+
}
635+
636+
/**
637+
* Set the component for a given appWidgetId.
638+
*
639+
* <p class="note">You need the BIND_APPWIDGET permission or the user must have enabled binding
640+
* widgets always for your component. Should be used by apps that host widgets; if this
641+
* method returns false, call {@link #ACTION_APPWIDGET_BIND} to request permission to
642+
* bind
643+
*
644+
* @param appWidgetId The AppWidget instance for which to set the RemoteViews.
645+
* @param provider The {@link android.content.BroadcastReceiver} that will be the AppWidget
646+
* provider for this AppWidget.
647+
* @param options Bundle containing options for the AppWidget. See also
648+
* {@link #updateAppWidgetOptions(int, Bundle)}
649+
*
650+
* @return true if this component has permission to bind the AppWidget
651+
*/
652+
public boolean bindAppWidgetIdIfAllowed(int appWidgetId, ComponentName provider,
653+
Bundle options) {
654+
if (mContext == null) {
655+
return false;
656+
}
657+
try {
658+
return sService.bindAppWidgetIdIfAllowed(
659+
mContext.getPackageName(), appWidgetId, provider, options);
598660
}
599661
catch (RemoteException e) {
600662
throw new RuntimeException("system server dead?", e);

core/java/android/appwidget/AppWidgetProviderInfo.java

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,34 @@ public class AppWidgetProviderInfo implements Parcelable {
4343
*/
4444
public static final int RESIZE_BOTH = RESIZE_HORIZONTAL | RESIZE_VERTICAL;
4545

46+
/**
47+
* Indicates that the widget can be displayed on the home screen. This is the default value.
48+
*/
49+
public static final int WIDGET_CATEGORY_HOME_SCREEN = 1;
50+
51+
/**
52+
* Indicates that the widget can be displayed on the keyguard.
53+
*/
54+
public static final int WIDGET_CATEGORY_KEYGUARD = 2;
55+
56+
/**
57+
* Indicates that the widget supports no special features.
58+
*/
59+
public static final int WIDGET_FEATURES_NONE = 0;
60+
61+
/**
62+
* Indicates that the widget displays the current time. The host may use this as a hint to not
63+
* display the time in other places.
64+
*/
65+
public static final int WIDGET_FEATURES_CLOCK = 1;
66+
67+
/**
68+
* Indicates that the widget is output only, ie. has nothing clickable. This may be enforced by
69+
* the host. Presently, this flag is used by the keyguard to indicate that it can be placed
70+
* in the first position.
71+
*/
72+
public static final int WIDGET_FEATURES_STATUS = 2;
73+
4674
/**
4775
* Identity of this AppWidget component. This component should be a {@link
4876
* android.content.BroadcastReceiver}, and it will be sent the AppWidget intents
@@ -110,6 +138,16 @@ public class AppWidgetProviderInfo implements Parcelable {
110138
*/
111139
public int initialLayout;
112140

141+
/**
142+
* The resource id of the initial layout for this AppWidget when it is displayed on keyguard.
143+
* This parameter only needs to be provided if the widget can be displayed on the keyguard,
144+
* see {@link #widgetCategory}.
145+
*
146+
* <p>This field corresponds to the <code>android:initialKeyguardLayout</code> attribute in
147+
* the AppWidget meta-data file.
148+
*/
149+
public int initialKeyguardLayout;
150+
113151
/**
114152
* The activity to launch that will configure the AppWidget.
115153
*
@@ -164,6 +202,27 @@ public class AppWidgetProviderInfo implements Parcelable {
164202
*/
165203
public int resizeMode;
166204

205+
/**
206+
* Determines whether this widget can be displayed on the home screen, the keyguard, or both.
207+
* A widget which is displayed on both needs to ensure that it follows the design guidelines
208+
* for both widget classes. This can be achieved by querying the AppWidget options in its
209+
* widget provider's update method.
210+
*
211+
* <p>This field corresponds to the <code>widgetCategory</code> attribute in
212+
* the AppWidget meta-data file.
213+
*/
214+
public int widgetCategory;
215+
216+
/**
217+
* A field which specifies any special features that this widget supports. See
218+
* {@link #WIDGET_FEATURES_NONE}, {@link #WIDGET_FEATURES_CLOCK},
219+
* {@link #WIDGET_FEATURES_STATUS}.
220+
*
221+
* <p>This field corresponds to the <code>widgetFeatures</code> attribute in
222+
* the AppWidget meta-data file.
223+
*/
224+
public int widgetFeatures;
225+
167226
public AppWidgetProviderInfo() {
168227
}
169228

@@ -180,6 +239,7 @@ public AppWidgetProviderInfo(Parcel in) {
180239
this.minResizeHeight = in.readInt();
181240
this.updatePeriodMillis = in.readInt();
182241
this.initialLayout = in.readInt();
242+
this.initialKeyguardLayout = in.readInt();
183243
if (0 != in.readInt()) {
184244
this.configure = new ComponentName(in);
185245
}
@@ -188,6 +248,8 @@ public AppWidgetProviderInfo(Parcel in) {
188248
this.previewImage = in.readInt();
189249
this.autoAdvanceViewId = in.readInt();
190250
this.resizeMode = in.readInt();
251+
this.widgetCategory = in.readInt();
252+
this.widgetFeatures = in.readInt();
191253
}
192254

193255
public void writeToParcel(android.os.Parcel out, int flags) {
@@ -203,6 +265,7 @@ public void writeToParcel(android.os.Parcel out, int flags) {
203265
out.writeInt(this.minResizeHeight);
204266
out.writeInt(this.updatePeriodMillis);
205267
out.writeInt(this.initialLayout);
268+
out.writeInt(this.initialKeyguardLayout);
206269
if (this.configure != null) {
207270
out.writeInt(1);
208271
this.configure.writeToParcel(out, flags);
@@ -214,6 +277,8 @@ public void writeToParcel(android.os.Parcel out, int flags) {
214277
out.writeInt(this.previewImage);
215278
out.writeInt(this.autoAdvanceViewId);
216279
out.writeInt(this.resizeMode);
280+
out.writeInt(this.widgetCategory);
281+
out.writeInt(this.widgetFeatures);
217282
}
218283

219284
public int describeContents() {

core/java/com/android/internal/appwidget/IAppWidgetService.aidl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,9 @@ interface IAppWidgetService {
5252
AppWidgetProviderInfo getAppWidgetInfo(int appWidgetId);
5353
boolean hasBindAppWidgetPermission(in String packageName);
5454
void setBindAppWidgetPermission(in String packageName, in boolean permission);
55-
void bindAppWidgetId(int appWidgetId, in ComponentName provider);
55+
void bindAppWidgetId(int appWidgetId, in ComponentName provider, in Bundle options);
5656
boolean bindAppWidgetIdIfAllowed(
57-
in String packageName, int appWidgetId, in ComponentName provider);
57+
in String packageName, int appWidgetId, in ComponentName provider, in Bundle options);
5858
void bindRemoteViewsService(int appWidgetId, in Intent intent, in IBinder connection);
5959
void unbindRemoteViewsService(int appWidgetId, in Intent intent);
6060
int[] getAppWidgetIds(in ComponentName provider);

core/res/res/values/attrs.xml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5180,6 +5180,8 @@
51805180
<attr name="updatePeriodMillis" format="integer" />
51815181
<!-- A resource id of a layout. -->
51825182
<attr name="initialLayout" format="reference" />
5183+
<!-- A resource id of a layout. -->
5184+
<attr name="initialKeyguardLayout" format="reference" />
51835185
<!-- A class name in the AppWidget's package to be launched to configure.
51845186
If not supplied, then no activity will be launched. -->
51855187
<attr name="configure" format="string" />
@@ -5190,12 +5192,26 @@
51905192
by the widget's host. -->
51915193
<attr name="autoAdvanceViewId" format="reference" />
51925194
<!-- Optional parameter which indicates if and how this widget can be
5193-
resized. -->
5195+
resized. Supports combined values using | operator. -->
51945196
<attr name="resizeMode" format="integer">
51955197
<flag name="none" value="0x0" />
51965198
<flag name="horizontal" value="0x1" />
51975199
<flag name="vertical" value="0x2" />
51985200
</attr>
5201+
<!-- Optional parameter which indicates where this widget can be shown,
5202+
ie. home screen, keyguard or both.
5203+
resized. Supports combined values using | operator. -->
5204+
<attr name="widgetCategory" format="integer">
5205+
<flag name="home_screen" value="0x1" />
5206+
<flag name="keyguard" value="0x2" />
5207+
</attr>
5208+
<!-- Optional parameter which indicates any feature(s) that this widget
5209+
supports. Supports combined values using | operator. -->
5210+
<attr name="widgetFeatures" format="integer">
5211+
<flag name="none" value="0x0" />
5212+
<flag name="clock" value="0x1" />
5213+
<flag name="status" value="0x2" />
5214+
</attr>
51995215
</declare-styleable>
52005216

52015217
<!-- =============================== -->

core/res/res/values/public.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3782,5 +3782,8 @@
37823782
<public type="attr" name="singleUser" />
37833783
<public type="attr" name="presentationTheme" />
37843784
<public type="attr" name="subtypeId"/>
3785+
<public type="attr" name="initialKeyguardLayout" />
3786+
<public type="attr" name="widgetFeatures" />
3787+
<public type="attr" name="widgetCategory" />
37853788

37863789
</resources>

services/java/com/android/server/AppWidgetService.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,18 @@ public void deleteAllHosts() throws RemoteException {
215215
}
216216

217217
@Override
218-
public void bindAppWidgetId(int appWidgetId, ComponentName provider) throws RemoteException {
219-
getImplForUser(UserHandle.getCallingUserId()).bindAppWidgetId(appWidgetId, provider);
218+
public void bindAppWidgetId(int appWidgetId, ComponentName provider, Bundle options)
219+
throws RemoteException {
220+
getImplForUser(UserHandle.getCallingUserId()).bindAppWidgetId(appWidgetId, provider,
221+
options);
220222
}
221223

222224
@Override
223225
public boolean bindAppWidgetIdIfAllowed(
224-
String packageName, int appWidgetId, ComponentName provider) throws RemoteException {
226+
String packageName, int appWidgetId, ComponentName provider, Bundle options)
227+
throws RemoteException {
225228
return getImplForUser(UserHandle.getCallingUserId()).bindAppWidgetIdIfAllowed(
226-
packageName, appWidgetId, provider);
229+
packageName, appWidgetId, provider, options);
227230
}
228231

229232
@Override

0 commit comments

Comments
 (0)