diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2017-08-16 04:59:08 -0700 |
---|---|---|
committer | Sunny Goyal <sunnygoyal@google.com> | 2017-09-13 14:04:35 -0700 |
commit | 952e63d0065d79d2bd9557ed7f28e96adb39ca9a (patch) | |
tree | 3f07803d9731a9c56ee7c0d707385b0272966e6b /src/com/android/launcher3/widget | |
parent | be213def874f580a58b2ee4a94ba503a6d7e3f15 (diff) | |
download | android_packages_apps_Trebuchet-952e63d0065d79d2bd9557ed7f28e96adb39ca9a.tar.gz android_packages_apps_Trebuchet-952e63d0065d79d2bd9557ed7f28e96adb39ca9a.tar.bz2 android_packages_apps_Trebuchet-952e63d0065d79d2bd9557ed7f28e96adb39ca9a.zip |
Fixing custom widgets support:
> Moving the definitions to xml so that it is easier to override in derivative projects
> Fixing verious bind and save logic for custom widgets
> Adding feature flag to easily disable custom widgets
Change-Id: I0e278bc7dd415713029364060ef10842da990be9
Diffstat (limited to 'src/com/android/launcher3/widget')
4 files changed, 248 insertions, 3 deletions
diff --git a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java index ad05ce917..bc404842e 100644 --- a/src/com/android/launcher3/widget/PendingAddWidgetInfo.java +++ b/src/com/android/launcher3/widget/PendingAddWidgetInfo.java @@ -35,13 +35,13 @@ public class PendingAddWidgetInfo extends PendingAddItemInfo { public Bundle bindOptions = null; public PendingAddWidgetInfo(LauncherAppWidgetProviderInfo i) { - if (i.isCustomWidget) { + if (i.isCustomWidget()) { itemType = LauncherSettings.Favorites.ITEM_TYPE_CUSTOM_APPWIDGET; } else { itemType = LauncherSettings.Favorites.ITEM_TYPE_APPWIDGET; } this.info = i; - user = i.getUser(); + user = i.getProfile(); componentName = i.provider; previewImage = i.previewImage; icon = i.icon; diff --git a/src/com/android/launcher3/widget/WidgetHostViewLoader.java b/src/com/android/launcher3/widget/WidgetHostViewLoader.java index 5eeea44b8..e6f8bb68f 100644 --- a/src/com/android/launcher3/widget/WidgetHostViewLoader.java +++ b/src/com/android/launcher3/widget/WidgetHostViewLoader.java @@ -85,7 +85,7 @@ public class WidgetHostViewLoader implements DragController.DragListener { private boolean preloadWidget() { final LauncherAppWidgetProviderInfo pInfo = mInfo.info; - if (pInfo.isCustomWidget) { + if (pInfo.isCustomWidget()) { return false; } final Bundle options = getDefaultOptionsForWidget(mLauncher, mInfo); diff --git a/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java b/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java new file mode 100644 index 000000000..1086987f8 --- /dev/null +++ b/src/com/android/launcher3/widget/custom/CustomAppWidgetProviderInfo.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.launcher3.widget.custom; + +import android.content.ComponentName; +import android.content.Context; +import android.content.pm.PackageManager; +import android.os.Parcel; +import android.os.Parcelable; + +import com.android.launcher3.LauncherAppWidgetProviderInfo; +import com.android.launcher3.Utilities; + +/** + * Custom app widget provider info that can be used as a widget, but provide extra functionality + * by allowing custom code and views. + */ +public class CustomAppWidgetProviderInfo extends LauncherAppWidgetProviderInfo + implements Parcelable { + + public final int providerId; + + protected CustomAppWidgetProviderInfo(Parcel parcel, boolean readSelf, int providerId) { + super(parcel); + if (readSelf) { + this.providerId = parcel.readInt(); + + provider = new ComponentName(parcel.readString(), CLS_CUSTOM_WIDGET_PREFIX + providerId); + + label = parcel.readString(); + initialLayout = parcel.readInt(); + icon = parcel.readInt(); + previewImage = parcel.readInt(); + + resizeMode = parcel.readInt(); + spanX = parcel.readInt(); + spanY = parcel.readInt(); + minSpanX = parcel.readInt(); + minSpanY = parcel.readInt(); + } else { + this.providerId = providerId; + } + } + + @Override + public void initSpans(Context context) { } + + @Override + public String getLabel(PackageManager packageManager) { + return Utilities.trim(label); + } + + @Override + public String toString() { + return "WidgetProviderInfo(" + provider + ")"; + } + + @Override + public void writeToParcel(Parcel out, int flags) { + super.writeToParcel(out, flags); + out.writeInt(providerId); + out.writeString(provider.getPackageName()); + + out.writeString(label); + out.writeInt(initialLayout); + out.writeInt(icon); + out.writeInt(previewImage); + + out.writeInt(resizeMode); + out.writeInt(spanX); + out.writeInt(spanY); + out.writeInt(minSpanX); + out.writeInt(minSpanY); + } + + public static final Parcelable.Creator<CustomAppWidgetProviderInfo> CREATOR + = new Parcelable.Creator<CustomAppWidgetProviderInfo>() { + + @Override + public CustomAppWidgetProviderInfo createFromParcel(Parcel parcel) { + return new CustomAppWidgetProviderInfo(parcel, true, 0); + } + + @Override + public CustomAppWidgetProviderInfo[] newArray(int size) { + return new CustomAppWidgetProviderInfo[size]; + } + }; +} diff --git a/src/com/android/launcher3/widget/custom/CustomWidgetParser.java b/src/com/android/launcher3/widget/custom/CustomWidgetParser.java new file mode 100644 index 000000000..00720c449 --- /dev/null +++ b/src/com/android/launcher3/widget/custom/CustomWidgetParser.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.widget.custom; + +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProviderInfo; +import android.content.ComponentName; +import android.content.Context; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; +import android.os.Parcel; +import android.os.Process; +import android.util.SparseArray; +import android.util.Xml; + +import com.android.launcher3.LauncherAppWidgetInfo; +import com.android.launcher3.LauncherAppWidgetProviderInfo; +import com.android.launcher3.R; + +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import static com.android.launcher3.LauncherAppWidgetProviderInfo.CLS_CUSTOM_WIDGET_PREFIX; + +/** + * Utility class to parse {@ink CustomAppWidgetProviderInfo} definitions from xml + */ +public class CustomWidgetParser { + + private static List<LauncherAppWidgetProviderInfo> sCustomWidgets; + private static SparseArray<ComponentName> sWidgetsIdMap; + + public static List<LauncherAppWidgetProviderInfo> getCustomWidgets(Context context) { + if (sCustomWidgets == null) { + // Synchronization not needed as it it safe to load multiple times + parseCustomWidgets(context); + } + + return sCustomWidgets; + } + + public static int getWidgetIdForCustomProvider(Context context, ComponentName provider) { + if (sWidgetsIdMap == null) { + parseCustomWidgets(context); + } + int index = sWidgetsIdMap.indexOfValue(provider); + if (index >= 0) { + return LauncherAppWidgetInfo.CUSTOM_WIDGET_ID - sWidgetsIdMap.keyAt(index); + } else { + return AppWidgetManager.INVALID_APPWIDGET_ID; + } + } + + public static LauncherAppWidgetProviderInfo getWidgetProvider(Context context, int widgetId) { + if (sWidgetsIdMap == null || sCustomWidgets == null) { + parseCustomWidgets(context); + } + ComponentName cn = sWidgetsIdMap.get(LauncherAppWidgetInfo.CUSTOM_WIDGET_ID - widgetId); + for (LauncherAppWidgetProviderInfo info : sCustomWidgets) { + if (info.provider.equals(cn)) { + return info; + } + } + return null; + } + + private static void parseCustomWidgets(Context context) { + ArrayList<LauncherAppWidgetProviderInfo> widgets = new ArrayList<>(); + SparseArray<ComponentName> idMap = new SparseArray<>(); + + List<AppWidgetProviderInfo> providers = AppWidgetManager.getInstance(context) + .getInstalledProvidersForProfile(Process.myUserHandle()); + if (providers.isEmpty()) { + sCustomWidgets = widgets; + sWidgetsIdMap = idMap; + return; + } + + Parcel parcel = Parcel.obtain(); + providers.get(0).writeToParcel(parcel, 0); + + try (XmlResourceParser parser = context.getResources().getXml(R.xml.custom_widgets)) { + final int depth = parser.getDepth(); + int type; + + while (((type = parser.next()) != XmlPullParser.END_TAG || + parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) { + if ((type == XmlPullParser.START_TAG) && "widget".equals(parser.getName())) { + TypedArray a = context.obtainStyledAttributes( + Xml.asAttributeSet(parser), R.styleable.CustomAppWidgetProviderInfo); + + parcel.setDataPosition(0); + CustomAppWidgetProviderInfo info = newInfo(a, parcel, context); + widgets.add(info); + a.recycle(); + + idMap.put(info.providerId, info.provider); + } + } + } catch (IOException | XmlPullParserException e) { + throw new RuntimeException(e); + } + parcel.recycle(); + sCustomWidgets = widgets; + sWidgetsIdMap = idMap; + } + + private static CustomAppWidgetProviderInfo newInfo(TypedArray a, Parcel parcel, Context context) { + int providerId = a.getInt(R.styleable.CustomAppWidgetProviderInfo_providerId, 0); + CustomAppWidgetProviderInfo info = new CustomAppWidgetProviderInfo(parcel, false, providerId); + info.provider = new ComponentName(context.getPackageName(), CLS_CUSTOM_WIDGET_PREFIX + providerId); + + info.label = a.getString(R.styleable.CustomAppWidgetProviderInfo_android_label); + info.initialLayout = a.getResourceId(R.styleable.CustomAppWidgetProviderInfo_android_initialLayout, 0); + info.icon = a.getResourceId(R.styleable.CustomAppWidgetProviderInfo_android_icon, 0); + info.previewImage = a.getResourceId(R.styleable.CustomAppWidgetProviderInfo_android_previewImage, 0); + info.resizeMode = a.getInt(R.styleable.CustomAppWidgetProviderInfo_android_resizeMode, 0); + + info.spanX = a.getInt(R.styleable.CustomAppWidgetProviderInfo_numColumns, 1); + info.spanY = a.getInt(R.styleable.CustomAppWidgetProviderInfo_numRows, 1); + info.minSpanX = a.getInt(R.styleable.CustomAppWidgetProviderInfo_numMinColumns, 1); + info.minSpanY = a.getInt(R.styleable.CustomAppWidgetProviderInfo_numMinRows, 1); + return info; + } +} |