• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.appwidget;
18 
19 import android.annotation.NonNull;
20 import android.content.Context;
21 import android.content.pm.ActivityInfo;
22 import android.content.pm.PackageManager;
23 import android.content.res.ResourceId;
24 import android.content.res.Resources;
25 import android.graphics.drawable.Drawable;
26 import android.os.Parcel;
27 import android.os.Parcelable;
28 import android.content.ComponentName;
29 import android.os.UserHandle;
30 import android.util.DisplayMetrics;
31 import android.util.TypedValue;
32 
33 /**
34  * Describes the meta data for an installed AppWidget provider.  The fields in this class
35  * correspond to the fields in the <code>&lt;appwidget-provider&gt;</code> xml tag.
36  */
37 public class AppWidgetProviderInfo implements Parcelable {
38 
39     /**
40      * Widget is not resizable.
41      */
42     public static final int RESIZE_NONE             = 0;
43     /**
44      * Widget is resizable in the horizontal axis only.
45      */
46     public static final int RESIZE_HORIZONTAL       = 1;
47     /**
48      * Widget is resizable in the vertical axis only.
49      */
50     public static final int RESIZE_VERTICAL         = 2;
51     /**
52      * Widget is resizable in both the horizontal and vertical axes.
53      */
54     public static final int RESIZE_BOTH = RESIZE_HORIZONTAL | RESIZE_VERTICAL;
55 
56     /**
57      * Indicates that the widget can be displayed on the home screen. This is the default value.
58      */
59     public static final int WIDGET_CATEGORY_HOME_SCREEN = 1;
60 
61     /**
62      * Indicates that the widget can be displayed on the keyguard.
63      */
64     public static final int WIDGET_CATEGORY_KEYGUARD = 2;
65 
66     /**
67      * Indicates that the widget can be displayed within a space reserved for the search box.
68      */
69     public static final int WIDGET_CATEGORY_SEARCHBOX = 4;
70 
71     /**
72      * Identity of this AppWidget component.  This component should be a {@link
73      * android.content.BroadcastReceiver}, and it will be sent the AppWidget intents
74      * {@link android.appwidget as described in the AppWidget package documentation}.
75      *
76      * <p>This field corresponds to the <code>android:name</code> attribute in
77      * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
78      */
79     public ComponentName provider;
80 
81     /**
82      * The default height of the widget when added to a host, in dp. The widget will get
83      * at least this width, and will often be given more, depending on the host.
84      *
85      * <p>This field corresponds to the <code>android:minWidth</code> attribute in
86      * the AppWidget meta-data file.
87      */
88     public int minWidth;
89 
90     /**
91      * The default height of the widget when added to a host, in dp. The widget will get
92      * at least this height, and will often be given more, depending on the host.
93      *
94      * <p>This field corresponds to the <code>android:minHeight</code> attribute in
95      * the AppWidget meta-data file.
96      */
97     public int minHeight;
98 
99     /**
100      * Minimum width (in dp) which the widget can be resized to. This field has no effect if it
101      * is greater than minWidth or if horizontal resizing isn't enabled (see {@link #resizeMode}).
102      *
103      * <p>This field corresponds to the <code>android:minResizeWidth</code> attribute in
104      * the AppWidget meta-data file.
105      */
106     public int minResizeWidth;
107 
108     /**
109      * Minimum height (in dp) which the widget can be resized to. This field has no effect if it
110      * is greater than minHeight or if vertical resizing isn't enabled (see {@link #resizeMode}).
111      *
112      * <p>This field corresponds to the <code>android:minResizeHeight</code> attribute in
113      * the AppWidget meta-data file.
114      */
115     public int minResizeHeight;
116 
117     /**
118      * How often, in milliseconds, that this AppWidget wants to be updated.
119      * The AppWidget manager may place a limit on how often a AppWidget is updated.
120      *
121      * <p>This field corresponds to the <code>android:updatePeriodMillis</code> attribute in
122      * the AppWidget meta-data file.
123      *
124      * <p class="note"><b>Note:</b> Updates requested with <code>updatePeriodMillis</code>
125      * will not be delivered more than once every 30 minutes.</p>
126      */
127     public int updatePeriodMillis;
128 
129     /**
130      * The resource id of the initial layout for this AppWidget.  This should be
131      * displayed until the RemoteViews for the AppWidget is available.
132      *
133      * <p>This field corresponds to the <code>android:initialLayout</code> attribute in
134      * the AppWidget meta-data file.
135      */
136     public int initialLayout;
137 
138     /**
139      * The resource id of the initial layout for this AppWidget when it is displayed on keyguard.
140      * This parameter only needs to be provided if the widget can be displayed on the keyguard,
141      * see {@link #widgetCategory}.
142      *
143      * <p>This field corresponds to the <code>android:initialKeyguardLayout</code> attribute in
144      * the AppWidget meta-data file.
145      */
146     public int initialKeyguardLayout;
147 
148     /**
149      * The activity to launch that will configure the AppWidget.
150      *
151      * <p>This class name of field corresponds to the <code>android:configure</code> attribute in
152      * the AppWidget meta-data file.  The package name always corresponds to the package containing
153      * the AppWidget provider.
154      */
155     public ComponentName configure;
156 
157     /**
158      * The label to display to the user in the AppWidget picker.
159      *
160      * @deprecated Use {@link #loadLabel(android.content.pm.PackageManager)}.
161      */
162     @Deprecated
163     public String label;
164 
165     /**
166      * The icon to display for this AppWidget in the AppWidget picker. If not supplied in the
167      * xml, the application icon will be used.
168      *
169      * <p>This field corresponds to the <code>android:icon</code> attribute in
170      * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
171      */
172     public int icon;
173 
174     /**
175      * The view id of the AppWidget subview which should be auto-advanced by the widget's host.
176      *
177      * <p>This field corresponds to the <code>android:autoAdvanceViewId</code> attribute in
178      * the AppWidget meta-data file.
179      */
180     public int autoAdvanceViewId;
181 
182     /**
183      * A preview of what the AppWidget will look like after it's configured.
184      * If not supplied, the AppWidget's icon will be used.
185      *
186      * <p>This field corresponds to the <code>android:previewImage</code> attribute in
187      * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
188      */
189     public int previewImage;
190 
191     /**
192      * The rules by which a widget can be resized. See {@link #RESIZE_NONE},
193      * {@link #RESIZE_NONE}, {@link #RESIZE_HORIZONTAL},
194      * {@link #RESIZE_VERTICAL}, {@link #RESIZE_BOTH}.
195      *
196      * <p>This field corresponds to the <code>android:resizeMode</code> attribute in
197      * the AppWidget meta-data file.
198      */
199     public int resizeMode;
200 
201     /**
202      * Determines whether this widget can be displayed on the home screen, the keyguard, or both.
203      * A widget which is displayed on both needs to ensure that it follows the design guidelines
204      * for both widget classes. This can be achieved by querying the AppWidget options in its
205      * widget provider's update method.
206      *
207      * <p>This field corresponds to the <code>widgetCategory</code> attribute in
208      * the AppWidget meta-data file.
209      */
210     public int widgetCategory;
211 
212     /** @hide */
213     public ActivityInfo providerInfo;
214 
AppWidgetProviderInfo()215     public AppWidgetProviderInfo() {
216 
217     }
218 
219     /**
220      * Unflatten the AppWidgetProviderInfo from a parcel.
221      */
222     @SuppressWarnings("deprecation")
AppWidgetProviderInfo(Parcel in)223     public AppWidgetProviderInfo(Parcel in) {
224         if (0 != in.readInt()) {
225             this.provider = new ComponentName(in);
226         }
227         this.minWidth = in.readInt();
228         this.minHeight = in.readInt();
229         this.minResizeWidth = in.readInt();
230         this.minResizeHeight = in.readInt();
231         this.updatePeriodMillis = in.readInt();
232         this.initialLayout = in.readInt();
233         this.initialKeyguardLayout = in.readInt();
234         if (0 != in.readInt()) {
235             this.configure = new ComponentName(in);
236         }
237         this.label = in.readString();
238         this.icon = in.readInt();
239         this.previewImage = in.readInt();
240         this.autoAdvanceViewId = in.readInt();
241         this.resizeMode = in.readInt();
242         this.widgetCategory = in.readInt();
243         this.providerInfo = in.readParcelable(null);
244     }
245 
246     /**
247      * Loads the localized label to display to the user in the AppWidget picker.
248      *
249      * @param packageManager Package manager instance for loading resources.
250      * @return The label for the current locale.
251      */
loadLabel(PackageManager packageManager)252     public final String loadLabel(PackageManager packageManager) {
253         CharSequence label = providerInfo.loadLabel(packageManager);
254         if (label != null) {
255             return label.toString().trim();
256         }
257         return null;
258     }
259 
260     /**
261      * Loads the icon to display for this AppWidget in the AppWidget picker. If not
262      * supplied in the xml, the application icon will be used. A client can optionally
263      * provide a desired density such as {@link android.util.DisplayMetrics#DENSITY_LOW}
264      * {@link android.util.DisplayMetrics#DENSITY_MEDIUM}, etc. If no density is
265      * provided, the density of the current display will be used.
266      * <p>
267      * The loaded icon corresponds to the <code>android:icon</code> attribute in
268      * the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
269      * </p>
270      *
271      * @param context Context for accessing resources.
272      * @param density The optional desired density as per
273      *         {@link android.util.DisplayMetrics#densityDpi}.
274      * @return The provider icon.
275      */
loadIcon(@onNull Context context, int density)276     public final Drawable loadIcon(@NonNull Context context, int density) {
277         return loadDrawable(context, density, providerInfo.getIconResource(), true);
278     }
279 
280     /**
281      * Loads a preview of what the AppWidget will look like after it's configured.
282      * A client can optionally provide a desired density such as
283      * {@link android.util.DisplayMetrics#DENSITY_LOW}
284      * {@link android.util.DisplayMetrics#DENSITY_MEDIUM}, etc. If no density is
285      * provided, the density of the current display will be used.
286      * <p>
287      * The loaded image corresponds to the <code>android:previewImage</code> attribute
288      * in the <code>&lt;receiver&gt;</code> element in the AndroidManifest.xml file.
289      * </p>
290      *
291      * @param context Context for accessing resources.
292      * @param density The optional desired density as per
293      *         {@link android.util.DisplayMetrics#densityDpi}.
294      * @return The widget preview image or null if preview image is not available.
295      */
loadPreviewImage(@onNull Context context, int density)296     public final Drawable loadPreviewImage(@NonNull Context context, int density) {
297         return loadDrawable(context, density, previewImage, false);
298     }
299 
300     /**
301      * Gets the user profile in which the provider resides.
302      *
303      * @return The hosting user profile.
304      */
getProfile()305     public final UserHandle getProfile() {
306         return new UserHandle(UserHandle.getUserId(providerInfo.applicationInfo.uid));
307     }
308 
309     @Override
310     @SuppressWarnings("deprecation")
writeToParcel(android.os.Parcel out, int flags)311     public void writeToParcel(android.os.Parcel out, int flags) {
312         if (this.provider != null) {
313             out.writeInt(1);
314             this.provider.writeToParcel(out, flags);
315         } else {
316             out.writeInt(0);
317         }
318         out.writeInt(this.minWidth);
319         out.writeInt(this.minHeight);
320         out.writeInt(this.minResizeWidth);
321         out.writeInt(this.minResizeHeight);
322         out.writeInt(this.updatePeriodMillis);
323         out.writeInt(this.initialLayout);
324         out.writeInt(this.initialKeyguardLayout);
325         if (this.configure != null) {
326             out.writeInt(1);
327             this.configure.writeToParcel(out, flags);
328         } else {
329             out.writeInt(0);
330         }
331         out.writeString(this.label);
332         out.writeInt(this.icon);
333         out.writeInt(this.previewImage);
334         out.writeInt(this.autoAdvanceViewId);
335         out.writeInt(this.resizeMode);
336         out.writeInt(this.widgetCategory);
337         out.writeParcelable(this.providerInfo, flags);
338     }
339 
340     @Override
341     @SuppressWarnings("deprecation")
clone()342     public AppWidgetProviderInfo clone() {
343         AppWidgetProviderInfo that = new AppWidgetProviderInfo();
344         that.provider = this.provider == null ? null : this.provider.clone();
345         that.minWidth = this.minWidth;
346         that.minHeight = this.minHeight;
347         that.minResizeWidth = this.minResizeHeight;
348         that.minResizeHeight = this.minResizeHeight;
349         that.updatePeriodMillis = this.updatePeriodMillis;
350         that.initialLayout = this.initialLayout;
351         that.initialKeyguardLayout = this.initialKeyguardLayout;
352         that.configure = this.configure == null ? null : this.configure.clone();
353         that.label = this.label == null ? null : this.label.substring(0);
354         that.icon = this.icon;
355         that.previewImage = this.previewImage;
356         that.autoAdvanceViewId = this.autoAdvanceViewId;
357         that.resizeMode = this.resizeMode;
358         that.widgetCategory = this.widgetCategory;
359         that.providerInfo = this.providerInfo;
360         return that;
361     }
362 
describeContents()363     public int describeContents() {
364         return 0;
365     }
366 
loadDrawable(Context context, int density, int resourceId, boolean loadDefaultIcon)367     private Drawable loadDrawable(Context context, int density, int resourceId,
368             boolean loadDefaultIcon) {
369         try {
370             Resources resources = context.getPackageManager().getResourcesForApplication(
371                     providerInfo.applicationInfo);
372             if (ResourceId.isValid(resourceId)) {
373                 if (density < 0) {
374                     density = 0;
375                 }
376                 return resources.getDrawableForDensity(resourceId, density, null);
377             }
378         } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
379             /* ignore */
380         }
381         return loadDefaultIcon ? providerInfo.loadIcon(context.getPackageManager()) : null;
382     }
383 
384     /**
385      * @hide
386      */
updateDimensions(DisplayMetrics displayMetrics)387     public void updateDimensions(DisplayMetrics displayMetrics) {
388         // Converting complex to dp.
389         minWidth = TypedValue.complexToDimensionPixelSize(minWidth, displayMetrics);
390         minHeight = TypedValue.complexToDimensionPixelSize(minHeight, displayMetrics);
391         minResizeWidth = TypedValue.complexToDimensionPixelSize(minResizeWidth, displayMetrics);
392         minResizeHeight = TypedValue.complexToDimensionPixelSize(minResizeHeight, displayMetrics);
393     }
394 
395     /**
396      * Parcelable.Creator that instantiates AppWidgetProviderInfo objects
397      */
398     public static final Parcelable.Creator<AppWidgetProviderInfo> CREATOR
399             = new Parcelable.Creator<AppWidgetProviderInfo>()
400     {
401         public AppWidgetProviderInfo createFromParcel(Parcel parcel)
402         {
403             return new AppWidgetProviderInfo(parcel);
404         }
405 
406         public AppWidgetProviderInfo[] newArray(int size)
407         {
408             return new AppWidgetProviderInfo[size];
409         }
410     };
411 
toString()412     public String toString() {
413         return "AppWidgetProviderInfo(" + getProfile() + '/' + provider + ')';
414     }
415 }
416