Revert "Revert "Adding support for hiding widgets from the widget tray and reconfiguring widgets""
This reverts commit f502e5faec
.
Reason for revert: Reverting post-build
Change-Id: I09eb292dbbbe37ffaf3abc477aa2ddb5700093b8
This commit is contained in:
parent
f502e5faec
commit
1054d4e8f2
|
@ -15,5 +15,5 @@
|
||||||
-->
|
-->
|
||||||
<com.android.launcher3.graphics.ShadowDrawable
|
<com.android.launcher3.graphics.ShadowDrawable
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:src="@drawable/ic_info_no_shadow"
|
android:src="@drawable/ic_setting"
|
||||||
android:elevation="@dimen/drop_target_shadow_elevation" />
|
android:elevation="@dimen/drop_target_shadow_elevation" />
|
|
@ -17,9 +17,10 @@ Copyright (C) 2016 The Android Open Source Project
|
||||||
android:width="@dimen/options_menu_icon_size"
|
android:width="@dimen/options_menu_icon_size"
|
||||||
android:height="@dimen/options_menu_icon_size"
|
android:height="@dimen/options_menu_icon_size"
|
||||||
android:viewportWidth="48.0"
|
android:viewportWidth="48.0"
|
||||||
android:viewportHeight="48.0">
|
android:viewportHeight="48.0"
|
||||||
|
android:tint="?android:attr/textColorPrimary" >
|
||||||
<path
|
<path
|
||||||
android:fillColor="?android:attr/textColorPrimary"
|
android:fillColor="#FFFFFFFF"
|
||||||
android:pathData="M42.8,28.4l-3.88-2.9c0.06-0.5,0.08-1,0.08-1.52s-0.02-1.02-0.08-1.52l3.88-2.86c0.84-0.62,1.04-1.88,
|
android:pathData="M42.8,28.4l-3.88-2.9c0.06-0.5,0.08-1,0.08-1.52s-0.02-1.02-0.08-1.52l3.88-2.86c0.84-0.62,1.04-1.88,
|
||||||
0.48-2.82l-3.2-5.52c-0.56-0.96-1.76-1.4-2.72-1l-4.28,1.82c-0.96-0.74-2.02-1.36-3.14-1.84l-0.54-4.4C29.28,4.8,28.28,4,
|
0.48-2.82l-3.2-5.52c-0.56-0.96-1.76-1.4-2.72-1l-4.28,1.82c-0.96-0.74-2.02-1.36-3.14-1.84l-0.54-4.4C29.28,4.8,28.28,4,
|
||||||
27.18,4h-6.36c-1.1,0-2.1,0.8-2.22,1.84l-0.52,4.38c-1.14,0.48-2.2,1.1-3.16,1.84l-4.28-1.82c-0.96-0.4-2.16,0.04-2.72,
|
27.18,4h-6.36c-1.1,0-2.1,0.8-2.22,1.84l-0.52,4.38c-1.14,0.48-2.2,1.1-3.16,1.84l-4.28-1.82c-0.96-0.4-2.16,0.04-2.72,
|
||||||
|
|
|
@ -32,18 +32,8 @@
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/remove_drop_target_label" />
|
android:text="@string/remove_drop_target_label" />
|
||||||
|
|
||||||
<!-- App Info -->
|
|
||||||
<com.android.launcher3.InfoDropTarget
|
|
||||||
android:id="@+id/info_target_text"
|
|
||||||
style="@style/DropTargetButton"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:gravity="center"
|
|
||||||
android:text="@string/app_info_drop_target_label" />
|
|
||||||
|
|
||||||
<!-- Uninstall target -->
|
<!-- Uninstall target -->
|
||||||
<com.android.launcher3.UninstallDropTarget
|
<com.android.launcher3.SecondaryDropTarget
|
||||||
android:id="@+id/uninstall_target_text"
|
android:id="@+id/uninstall_target_text"
|
||||||
style="@style/DropTargetButton"
|
style="@style/DropTargetButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|
|
@ -127,7 +127,7 @@
|
||||||
<!-- Accessibility actions -->
|
<!-- Accessibility actions -->
|
||||||
<item type="id" name="action_remove" />
|
<item type="id" name="action_remove" />
|
||||||
<item type="id" name="action_uninstall" />
|
<item type="id" name="action_uninstall" />
|
||||||
<item type="id" name="action_info" />
|
<item type="id" name="action_reconfigure" />
|
||||||
<item type="id" name="action_add_to_workspace" />
|
<item type="id" name="action_add_to_workspace" />
|
||||||
<item type="id" name="action_move" />
|
<item type="id" name="action_move" />
|
||||||
<item type="id" name="action_move_to_workspace" />
|
<item type="id" name="action_move_to_workspace" />
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
-->
|
-->
|
||||||
<resources>
|
<resources>
|
||||||
<drawable name="ic_info_shadow">@drawable/ic_info_no_shadow</drawable>
|
<drawable name="ic_setup_shadow">@drawable/ic_setting</drawable>
|
||||||
<drawable name="ic_remove_shadow">@drawable/ic_remove_no_shadow</drawable>
|
<drawable name="ic_remove_shadow">@drawable/ic_remove_no_shadow</drawable>
|
||||||
<drawable name="ic_uninstall_shadow">@drawable/ic_uninstall_no_shadow</drawable>
|
<drawable name="ic_uninstall_shadow">@drawable/ic_uninstall_no_shadow</drawable>
|
||||||
</resources>
|
</resources>
|
|
@ -108,6 +108,12 @@ public abstract class ButtonDropTarget extends TextView
|
||||||
setContentDescription(mText);
|
setContentDescription(mText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void updateText(int resId) {
|
||||||
|
setText(resId);
|
||||||
|
mText = getText();
|
||||||
|
setContentDescription(mText);
|
||||||
|
}
|
||||||
|
|
||||||
protected void setDrawable(int resId) {
|
protected void setDrawable(int resId) {
|
||||||
// We do not set the drawable in the xml as that inflates two drawables corresponding to
|
// We do not set the drawable in the xml as that inflates two drawables corresponding to
|
||||||
// drawableLeft and drawableStart.
|
// drawableLeft and drawableStart.
|
||||||
|
@ -236,9 +242,7 @@ public abstract class ButtonDropTarget extends TextView
|
||||||
|
|
||||||
protected abstract boolean supportsDrop(ItemInfo info);
|
protected abstract boolean supportsDrop(ItemInfo info);
|
||||||
|
|
||||||
public boolean supportsAccessibilityDrop(ItemInfo info) {
|
public abstract boolean supportsAccessibilityDrop(ItemInfo info, View view);
|
||||||
return supportsDrop(info);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDropEnabled() {
|
public boolean isDropEnabled() {
|
||||||
|
@ -368,4 +372,6 @@ public abstract class ButtonDropTarget extends TextView
|
||||||
TextUtils.TruncateAt.END);
|
TextUtils.TruncateAt.END);
|
||||||
return !mText.equals(displayedText);
|
return !mText.equals(displayedText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract int getControlTypeForLogging();
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import android.view.View;
|
||||||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
||||||
import com.android.launcher3.dragndrop.DragOptions;
|
import com.android.launcher3.dragndrop.DragOptions;
|
||||||
import com.android.launcher3.folder.Folder;
|
import com.android.launcher3.folder.Folder;
|
||||||
|
import com.android.launcher3.userevent.nano.LauncherLogProto.ControlType;
|
||||||
|
|
||||||
public class DeleteDropTarget extends ButtonDropTarget {
|
public class DeleteDropTarget extends ButtonDropTarget {
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@ public class DeleteDropTarget extends ButtonDropTarget {
|
||||||
* @return true for items that should have a "Remove" action in accessibility.
|
* @return true for items that should have a "Remove" action in accessibility.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean supportsAccessibilityDrop(ItemInfo info) {
|
public boolean supportsAccessibilityDrop(ItemInfo info, View view) {
|
||||||
return (info instanceof ShortcutInfo)
|
return (info instanceof ShortcutInfo)
|
||||||
|| (info instanceof LauncherAppWidgetInfo)
|
|| (info instanceof LauncherAppWidgetInfo)
|
||||||
|| (info instanceof FolderInfo);
|
|| (info instanceof FolderInfo);
|
||||||
|
@ -103,4 +104,9 @@ public class DeleteDropTarget extends ButtonDropTarget {
|
||||||
mLauncher.getDragLayer()
|
mLauncher.getDragLayer()
|
||||||
.announceForAccessibility(getContext().getString(R.string.item_removed));
|
.announceForAccessibility(getContext().getString(R.string.item_removed));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getControlTypeForLogging() {
|
||||||
|
return ControlType.REMOVE_TARGET;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2011 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;
|
|
||||||
|
|
||||||
import android.content.ActivityNotFoundException;
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.provider.Settings;
|
|
||||||
import android.util.AttributeSet;
|
|
||||||
import android.util.Log;
|
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
|
||||||
import com.android.launcher3.compat.LauncherAppsCompat;
|
|
||||||
import com.android.launcher3.util.Themes;
|
|
||||||
|
|
||||||
public class InfoDropTarget extends UninstallDropTarget {
|
|
||||||
|
|
||||||
private static final String TAG = "InfoDropTarget";
|
|
||||||
|
|
||||||
public InfoDropTarget(Context context, AttributeSet attrs) {
|
|
||||||
this(context, attrs, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public InfoDropTarget(Context context, AttributeSet attrs, int defStyle) {
|
|
||||||
super(context, attrs, defStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setupUi() {
|
|
||||||
// Get the hover color
|
|
||||||
mHoverColor = Themes.getColorAccent(getContext());
|
|
||||||
setDrawable(R.drawable.ic_info_shadow);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ComponentName performDropAction(ItemInfo item) {
|
|
||||||
return performDropAction(mLauncher, item, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Whether the activity was started.
|
|
||||||
*/
|
|
||||||
public static boolean startDetailsActivityForInfo(
|
|
||||||
ItemInfo info, Launcher launcher, Rect sourceBounds, Bundle opts) {
|
|
||||||
return performDropAction(launcher, info, sourceBounds, opts) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs the drop action and returns the target component for the dragObject or null if
|
|
||||||
* the action was not performed.
|
|
||||||
*/
|
|
||||||
private static ComponentName performDropAction(Context context, ItemInfo info,
|
|
||||||
Rect sourceBounds, Bundle opts) {
|
|
||||||
if (info instanceof PromiseAppInfo) {
|
|
||||||
PromiseAppInfo promiseAppInfo = (PromiseAppInfo) info;
|
|
||||||
context.startActivity(promiseAppInfo.getMarketIntent(context));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ComponentName componentName = null;
|
|
||||||
if (info instanceof AppInfo) {
|
|
||||||
componentName = ((AppInfo) info).componentName;
|
|
||||||
} else if (info instanceof ShortcutInfo) {
|
|
||||||
componentName = info.getTargetComponent();
|
|
||||||
} else if (info instanceof PendingAddItemInfo) {
|
|
||||||
componentName = ((PendingAddItemInfo) info).componentName;
|
|
||||||
} else if (info instanceof LauncherAppWidgetInfo) {
|
|
||||||
componentName = ((LauncherAppWidgetInfo) info).providerName;
|
|
||||||
}
|
|
||||||
if (componentName != null) {
|
|
||||||
try {
|
|
||||||
LauncherAppsCompat.getInstance(context)
|
|
||||||
.showAppDetailsForProfile(componentName, info.user, sourceBounds, opts);
|
|
||||||
return componentName;
|
|
||||||
} catch (SecurityException | ActivityNotFoundException e) {
|
|
||||||
Toast.makeText(context, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
|
|
||||||
Log.e(TAG, "Unable to launch settings", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getAccessibilityAction() {
|
|
||||||
return LauncherAccessibilityDelegate.INFO;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected boolean supportsDrop(ItemInfo info) {
|
|
||||||
// Only show the App Info drop target if developer settings are enabled.
|
|
||||||
boolean developmentSettingsEnabled = Settings.Global.getInt(
|
|
||||||
getContext().getContentResolver(),
|
|
||||||
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0) == 1;
|
|
||||||
if (!developmentSettingsEnabled) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return info.itemType != LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT &&
|
|
||||||
(info instanceof AppInfo ||
|
|
||||||
(info instanceof ShortcutInfo && !((ShortcutInfo) info).isPromise()) ||
|
|
||||||
(info instanceof LauncherAppWidgetInfo &&
|
|
||||||
((LauncherAppWidgetInfo) info).restoreStatus == 0) ||
|
|
||||||
info instanceof PendingAddItemInfo);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -94,4 +94,12 @@ public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo {
|
||||||
public boolean isCustomWidget() {
|
public boolean isCustomWidget() {
|
||||||
return provider.getClassName().startsWith(CLS_CUSTOM_WIDGET_PREFIX);
|
return provider.getClassName().startsWith(CLS_CUSTOM_WIDGET_PREFIX);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getWidgetFeatures() {
|
||||||
|
if (Utilities.ATLEAST_P) {
|
||||||
|
return widgetFeatures;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,19 @@
|
||||||
package com.android.launcher3;
|
package com.android.launcher3;
|
||||||
|
|
||||||
|
import static android.appwidget.AppWidgetManager.INVALID_APPWIDGET_ID;
|
||||||
|
import static android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_RECONFIGURABLE;
|
||||||
|
|
||||||
import static com.android.launcher3.ItemInfoWithIcon.FLAG_SYSTEM_MASK;
|
import static com.android.launcher3.ItemInfoWithIcon.FLAG_SYSTEM_MASK;
|
||||||
import static com.android.launcher3.ItemInfoWithIcon.FLAG_SYSTEM_NO;
|
import static com.android.launcher3.ItemInfoWithIcon.FLAG_SYSTEM_NO;
|
||||||
|
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP;
|
||||||
|
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.RECONFIGURE;
|
||||||
|
import static com.android.launcher3.accessibility.LauncherAccessibilityDelegate.UNINSTALL;
|
||||||
|
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.SETTINGS_BUTTON;
|
||||||
|
import static com.android.launcher3.userevent.nano.LauncherLogProto.ControlType.UNINSTALL_TARGET;
|
||||||
|
|
||||||
|
import android.appwidget.AppWidgetHostView;
|
||||||
|
import android.appwidget.AppWidgetManager;
|
||||||
|
import android.appwidget.AppWidgetProviderInfo;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -20,27 +31,33 @@ import android.view.View;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.android.launcher3.Launcher.OnResumeCallback;
|
import com.android.launcher3.Launcher.OnResumeCallback;
|
||||||
import com.android.launcher3.accessibility.LauncherAccessibilityDelegate;
|
|
||||||
import com.android.launcher3.compat.LauncherAppsCompat;
|
import com.android.launcher3.compat.LauncherAppsCompat;
|
||||||
import com.android.launcher3.dragndrop.DragOptions;
|
import com.android.launcher3.dragndrop.DragOptions;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
|
||||||
|
import com.android.launcher3.util.Themes;
|
||||||
|
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmListener {
|
/**
|
||||||
|
* Drop target which provides a secondary option for an item.
|
||||||
|
* For app targets: shows as uninstall
|
||||||
|
* For configurable widgets: shows as setup
|
||||||
|
*/
|
||||||
|
public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmListener {
|
||||||
|
|
||||||
private static final String TAG = "UninstallDropTarget";
|
private static final String TAG = "SecondaryDropTarget";
|
||||||
|
|
||||||
private static final long CACHE_EXPIRE_TIMEOUT = 5000;
|
private static final long CACHE_EXPIRE_TIMEOUT = 5000;
|
||||||
private final ArrayMap<UserHandle, Boolean> mUninstallDisabledCache = new ArrayMap<>(1);
|
private final ArrayMap<UserHandle, Boolean> mUninstallDisabledCache = new ArrayMap<>(1);
|
||||||
|
|
||||||
private final Alarm mCacheExpireAlarm;
|
private final Alarm mCacheExpireAlarm;
|
||||||
|
|
||||||
public UninstallDropTarget(Context context, AttributeSet attrs) {
|
private int mCurrentAccessibilityAction = -1;
|
||||||
|
public SecondaryDropTarget(Context context, AttributeSet attrs) {
|
||||||
this(context, attrs, 0);
|
this(context, attrs, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public UninstallDropTarget(Context context, AttributeSet attrs, int defStyle) {
|
public SecondaryDropTarget(Context context, AttributeSet attrs, int defStyle) {
|
||||||
super(context, attrs, defStyle);
|
super(context, attrs, defStyle);
|
||||||
|
|
||||||
mCacheExpireAlarm = new Alarm();
|
mCacheExpireAlarm = new Alarm();
|
||||||
|
@ -50,13 +67,24 @@ public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmList
|
||||||
@Override
|
@Override
|
||||||
protected void onFinishInflate() {
|
protected void onFinishInflate() {
|
||||||
super.onFinishInflate();
|
super.onFinishInflate();
|
||||||
setupUi();
|
setupUi(UNINSTALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setupUi() {
|
private void setupUi(int action) {
|
||||||
// Get the hover color
|
if (action == mCurrentAccessibilityAction) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mCurrentAccessibilityAction = action;
|
||||||
|
|
||||||
|
if (action == UNINSTALL) {
|
||||||
mHoverColor = getResources().getColor(R.color.uninstall_target_hover_tint);
|
mHoverColor = getResources().getColor(R.color.uninstall_target_hover_tint);
|
||||||
setDrawable(R.drawable.ic_uninstall_shadow);
|
setDrawable(R.drawable.ic_uninstall_shadow);
|
||||||
|
updateText(R.string.uninstall_drop_target_label);
|
||||||
|
} else {
|
||||||
|
mHoverColor = Themes.getColorAccent(getContext());
|
||||||
|
setDrawable(R.drawable.ic_setup_shadow);
|
||||||
|
updateText(R.string.gadget_setup_text);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -66,11 +94,30 @@ public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmList
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAccessibilityAction() {
|
public int getAccessibilityAction() {
|
||||||
return LauncherAccessibilityDelegate.UNINSTALL;
|
return mCurrentAccessibilityAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getControlTypeForLogging() {
|
||||||
|
return mCurrentAccessibilityAction == UNINSTALL ? UNINSTALL_TARGET : SETTINGS_BUTTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean supportsDrop(ItemInfo info) {
|
protected boolean supportsDrop(ItemInfo info) {
|
||||||
|
return supportsAccessibilityDrop(info, getViewUnderDrag(info));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean supportsAccessibilityDrop(ItemInfo info, View view) {
|
||||||
|
if (view instanceof AppWidgetHostView) {
|
||||||
|
if (getReconfigurableWidgetId(view) != INVALID_APPWIDGET_ID) {
|
||||||
|
setupUi(RECONFIGURE);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setupUi(UNINSTALL);
|
||||||
Boolean uninstallDisabled = mUninstallDisabledCache.get(info.user);
|
Boolean uninstallDisabled = mUninstallDisabledCache.get(info.user);
|
||||||
if (uninstallDisabled == null) {
|
if (uninstallDisabled == null) {
|
||||||
UserManager userManager =
|
UserManager userManager =
|
||||||
|
@ -126,7 +173,7 @@ public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmList
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void completeDrop(final DragObject d) {
|
public void completeDrop(final DragObject d) {
|
||||||
ComponentName target = performDropAction(d.dragInfo);
|
ComponentName target = performDropAction(getViewUnderDrag(d.dragInfo), d.dragInfo);
|
||||||
if (d.dragSource instanceof DeferredOnComplete) {
|
if (d.dragSource instanceof DeferredOnComplete) {
|
||||||
DeferredOnComplete deferred = (DeferredOnComplete) d.dragSource;
|
DeferredOnComplete deferred = (DeferredOnComplete) d.dragSource;
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
|
@ -138,11 +185,48 @@ public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private View getViewUnderDrag(ItemInfo info) {
|
||||||
|
if (info instanceof LauncherAppWidgetInfo && info.container == CONTAINER_DESKTOP &&
|
||||||
|
mLauncher.getWorkspace().getDragInfo() != null) {
|
||||||
|
return mLauncher.getWorkspace().getDragInfo().cell;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verifies that the view is an reconfigurable widget and returns the corresponding widget Id,
|
||||||
|
* otherwise return {@code INVALID_APPWIDGET_ID}
|
||||||
|
*/
|
||||||
|
private int getReconfigurableWidgetId(View view) {
|
||||||
|
if (!(view instanceof AppWidgetHostView)) {
|
||||||
|
return INVALID_APPWIDGET_ID;
|
||||||
|
}
|
||||||
|
AppWidgetHostView hostView = (AppWidgetHostView) view;
|
||||||
|
AppWidgetProviderInfo widgetInfo = hostView.getAppWidgetInfo();
|
||||||
|
if (widgetInfo == null || widgetInfo.configure == null) {
|
||||||
|
return INVALID_APPWIDGET_ID;
|
||||||
|
}
|
||||||
|
if ( (LauncherAppWidgetProviderInfo.fromProviderInfo(getContext(), widgetInfo)
|
||||||
|
.getWidgetFeatures() & WIDGET_FEATURE_RECONFIGURABLE) == 0) {
|
||||||
|
return INVALID_APPWIDGET_ID;
|
||||||
|
}
|
||||||
|
return hostView.getAppWidgetId();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs the drop action and returns the target component for the dragObject or null if
|
* Performs the drop action and returns the target component for the dragObject or null if
|
||||||
* the action was not performed.
|
* the action was not performed.
|
||||||
*/
|
*/
|
||||||
protected ComponentName performDropAction(ItemInfo info) {
|
protected ComponentName performDropAction(View view, ItemInfo info) {
|
||||||
|
if (mCurrentAccessibilityAction == RECONFIGURE) {
|
||||||
|
int widgetId = getReconfigurableWidgetId(view);
|
||||||
|
if (widgetId != INVALID_APPWIDGET_ID) {
|
||||||
|
mLauncher.getAppWidgetHost().startConfigActivity(mLauncher, widgetId, -1);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// else: mCurrentAccessibilityAction == UNINSTALL
|
||||||
|
|
||||||
ComponentName cn = getUninstallTarget(info);
|
ComponentName cn = getUninstallTarget(info);
|
||||||
if (cn == null) {
|
if (cn == null) {
|
||||||
// System applications cannot be installed. For now, show a toast explaining that.
|
// System applications cannot be installed. For now, show a toast explaining that.
|
||||||
|
@ -164,7 +248,7 @@ public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmList
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAccessibilityDrop(View view, ItemInfo item) {
|
public void onAccessibilityDrop(View view, ItemInfo item) {
|
||||||
performDropAction(item);
|
performDropAction(view, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -203,7 +287,7 @@ public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmList
|
||||||
.getApplicationInfo(mPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES,
|
.getApplicationInfo(mPackageName, PackageManager.MATCH_UNINSTALLED_PACKAGES,
|
||||||
mDragObject.dragInfo.user) == null) {
|
mDragObject.dragInfo.user) == null) {
|
||||||
mDragObject.dragSource = mOriginal;
|
mDragObject.dragSource = mOriginal;
|
||||||
mOriginal.onDropCompleted(UninstallDropTarget.this, mDragObject, true);
|
mOriginal.onDropCompleted(SecondaryDropTarget.this, mDragObject, true);
|
||||||
} else {
|
} else {
|
||||||
sendFailure();
|
sendFailure();
|
||||||
}
|
}
|
||||||
|
@ -212,7 +296,7 @@ public class UninstallDropTarget extends ButtonDropTarget implements OnAlarmList
|
||||||
public void sendFailure() {
|
public void sendFailure() {
|
||||||
mDragObject.dragSource = mOriginal;
|
mDragObject.dragSource = mOriginal;
|
||||||
mDragObject.cancelled = true;
|
mDragObject.cancelled = true;
|
||||||
mOriginal.onDropCompleted(UninstallDropTarget.this, mDragObject, false);
|
mOriginal.onDropCompleted(SecondaryDropTarget.this, mDragObject, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -47,8 +47,8 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
||||||
private static final String TAG = "LauncherAccessibilityDelegate";
|
private static final String TAG = "LauncherAccessibilityDelegate";
|
||||||
|
|
||||||
public static final int REMOVE = R.id.action_remove;
|
public static final int REMOVE = R.id.action_remove;
|
||||||
public static final int INFO = R.id.action_info;
|
|
||||||
public static final int UNINSTALL = R.id.action_uninstall;
|
public static final int UNINSTALL = R.id.action_uninstall;
|
||||||
|
public static final int RECONFIGURE = R.id.action_reconfigure;
|
||||||
protected static final int ADD_TO_WORKSPACE = R.id.action_add_to_workspace;
|
protected static final int ADD_TO_WORKSPACE = R.id.action_add_to_workspace;
|
||||||
protected static final int MOVE = R.id.action_move;
|
protected static final int MOVE = R.id.action_move;
|
||||||
protected static final int MOVE_TO_WORKSPACE = R.id.action_move_to_workspace;
|
protected static final int MOVE_TO_WORKSPACE = R.id.action_move_to_workspace;
|
||||||
|
@ -77,10 +77,10 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
||||||
|
|
||||||
mActions.put(REMOVE, new AccessibilityAction(REMOVE,
|
mActions.put(REMOVE, new AccessibilityAction(REMOVE,
|
||||||
launcher.getText(R.string.remove_drop_target_label)));
|
launcher.getText(R.string.remove_drop_target_label)));
|
||||||
mActions.put(INFO, new AccessibilityAction(INFO,
|
|
||||||
launcher.getText(R.string.app_info_drop_target_label)));
|
|
||||||
mActions.put(UNINSTALL, new AccessibilityAction(UNINSTALL,
|
mActions.put(UNINSTALL, new AccessibilityAction(UNINSTALL,
|
||||||
launcher.getText(R.string.uninstall_drop_target_label)));
|
launcher.getText(R.string.uninstall_drop_target_label)));
|
||||||
|
mActions.put(RECONFIGURE, new AccessibilityAction(RECONFIGURE,
|
||||||
|
launcher.getText(R.string.gadget_setup_text)));
|
||||||
mActions.put(ADD_TO_WORKSPACE, new AccessibilityAction(ADD_TO_WORKSPACE,
|
mActions.put(ADD_TO_WORKSPACE, new AccessibilityAction(ADD_TO_WORKSPACE,
|
||||||
launcher.getText(R.string.action_add_to_workspace)));
|
launcher.getText(R.string.action_add_to_workspace)));
|
||||||
mActions.put(MOVE, new AccessibilityAction(MOVE,
|
mActions.put(MOVE, new AccessibilityAction(MOVE,
|
||||||
|
@ -110,7 +110,7 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ButtonDropTarget target : mLauncher.getDropTargetBar().getDropTargets()) {
|
for (ButtonDropTarget target : mLauncher.getDropTargetBar().getDropTargets()) {
|
||||||
if (target.supportsAccessibilityDrop(item)) {
|
if (target.supportsAccessibilityDrop(item, host)) {
|
||||||
info.addAction(mActions.get(target.getAccessibilityAction()));
|
info.addAction(mActions.get(target.getAccessibilityAction()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -222,7 +222,8 @@ public class LauncherAccessibilityDelegate extends AccessibilityDelegate impleme
|
||||||
return PopupContainerWithArrow.showForIcon((BubbleTextView) host) != null;
|
return PopupContainerWithArrow.showForIcon((BubbleTextView) host) != null;
|
||||||
} else {
|
} else {
|
||||||
for (ButtonDropTarget dropTarget : mLauncher.getDropTargetBar().getDropTargets()) {
|
for (ButtonDropTarget dropTarget : mLauncher.getDropTargetBar().getDropTargets()) {
|
||||||
if (action == dropTarget.getAccessibilityAction()) {
|
if (dropTarget.supportsAccessibilityDrop(item, host) &&
|
||||||
|
action == dropTarget.getAccessibilityAction()) {
|
||||||
dropTarget.onAccessibilityDrop(host, item);
|
dropTarget.onAccessibilityDrop(host, item);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,8 @@ import android.util.SparseArray;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.android.launcher3.ButtonDropTarget;
|
import com.android.launcher3.ButtonDropTarget;
|
||||||
import com.android.launcher3.DeleteDropTarget;
|
|
||||||
import com.android.launcher3.InfoDropTarget;
|
|
||||||
import com.android.launcher3.ItemInfo;
|
import com.android.launcher3.ItemInfo;
|
||||||
import com.android.launcher3.LauncherSettings;
|
import com.android.launcher3.LauncherSettings;
|
||||||
import com.android.launcher3.UninstallDropTarget;
|
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogExtensions.TargetExtension;
|
import com.android.launcher3.userevent.nano.LauncherLogExtensions.TargetExtension;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.Action;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||||
|
@ -165,12 +162,8 @@ public class LoggerUtils {
|
||||||
return newTarget(Target.Type.CONTAINER);
|
return newTarget(Target.Type.CONTAINER);
|
||||||
}
|
}
|
||||||
Target t = newTarget(Target.Type.CONTROL);
|
Target t = newTarget(Target.Type.CONTROL);
|
||||||
if (v instanceof InfoDropTarget) {
|
if (v instanceof ButtonDropTarget) {
|
||||||
t.controlType = ControlType.APPINFO_TARGET;
|
t.controlType = ((ButtonDropTarget) v).getControlTypeForLogging();
|
||||||
} else if (v instanceof UninstallDropTarget) {
|
|
||||||
t.controlType = ControlType.UNINSTALL_TARGET;
|
|
||||||
} else if (v instanceof DeleteDropTarget) {
|
|
||||||
t.controlType = ControlType.REMOVE_TARGET;
|
|
||||||
}
|
}
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
|
|
||||||
package com.android.launcher3.model;
|
package com.android.launcher3.model;
|
||||||
|
|
||||||
|
import static android.appwidget.AppWidgetProviderInfo.WIDGET_FEATURE_HIDE_FROM_PICKER;
|
||||||
|
|
||||||
import android.appwidget.AppWidgetProviderInfo;
|
import android.appwidget.AppWidgetProviderInfo;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
|
@ -153,6 +155,11 @@ public class WidgetsModel {
|
||||||
// add and update.
|
// add and update.
|
||||||
for (WidgetItem item : rawWidgetsShortcuts) {
|
for (WidgetItem item : rawWidgetsShortcuts) {
|
||||||
if (item.widgetInfo != null) {
|
if (item.widgetInfo != null) {
|
||||||
|
if ((item.widgetInfo.getWidgetFeatures() & WIDGET_FEATURE_HIDE_FROM_PICKER) != 0) {
|
||||||
|
// Widget is hidden from picker
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Ensure that all widgets we show can be added on a workspace of this size
|
// Ensure that all widgets we show can be added on a workspace of this size
|
||||||
int minSpanX = Math.min(item.widgetInfo.spanX, item.widgetInfo.minSpanX);
|
int minSpanX = Math.min(item.widgetInfo.spanX, item.widgetInfo.minSpanX);
|
||||||
int minSpanY = Math.min(item.widgetInfo.spanY, item.widgetInfo.minSpanY);
|
int minSpanY = Math.min(item.widgetInfo.spanY, item.widgetInfo.minSpanY);
|
||||||
|
|
|
@ -9,7 +9,6 @@ import android.os.Bundle;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.android.launcher3.AbstractFloatingView;
|
import com.android.launcher3.AbstractFloatingView;
|
||||||
import com.android.launcher3.InfoDropTarget;
|
|
||||||
import com.android.launcher3.ItemInfo;
|
import com.android.launcher3.ItemInfo;
|
||||||
import com.android.launcher3.Launcher;
|
import com.android.launcher3.Launcher;
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
|
@ -83,7 +82,8 @@ public abstract class SystemShortcut extends ItemInfo {
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
Rect sourceBounds = launcher.getViewBounds(view);
|
Rect sourceBounds = launcher.getViewBounds(view);
|
||||||
Bundle opts = launcher.getActivityLaunchOptionsAsBundle(view, false);
|
Bundle opts = launcher.getActivityLaunchOptionsAsBundle(view, false);
|
||||||
InfoDropTarget.startDetailsActivityForInfo(itemInfo, launcher, sourceBounds, opts);
|
new PackageManagerHelper(launcher).startDetailsActivityForInfo(
|
||||||
|
itemInfo, sourceBounds, opts);
|
||||||
launcher.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
|
launcher.getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
|
||||||
ControlType.APPINFO_TARGET, view);
|
ControlType.APPINFO_TARGET, view);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
package com.android.launcher3.util;
|
package com.android.launcher3.util;
|
||||||
|
|
||||||
import android.app.AppOpsManager;
|
import android.app.AppOpsManager;
|
||||||
|
import android.content.ActivityNotFoundException;
|
||||||
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
|
@ -24,13 +26,23 @@ import android.content.pm.LauncherActivityInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.PackageManager.NameNotFoundException;
|
import android.content.pm.PackageManager.NameNotFoundException;
|
||||||
import android.content.pm.ResolveInfo;
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.graphics.Rect;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.android.launcher3.AppInfo;
|
import com.android.launcher3.AppInfo;
|
||||||
|
import com.android.launcher3.ItemInfo;
|
||||||
|
import com.android.launcher3.Launcher;
|
||||||
|
import com.android.launcher3.LauncherAppWidgetInfo;
|
||||||
|
import com.android.launcher3.PendingAddItemInfo;
|
||||||
|
import com.android.launcher3.PromiseAppInfo;
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
|
import com.android.launcher3.ShortcutInfo;
|
||||||
import com.android.launcher3.Utilities;
|
import com.android.launcher3.Utilities;
|
||||||
import com.android.launcher3.compat.LauncherAppsCompat;
|
import com.android.launcher3.compat.LauncherAppsCompat;
|
||||||
|
|
||||||
|
@ -42,6 +54,8 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class PackageManagerHelper {
|
public class PackageManagerHelper {
|
||||||
|
|
||||||
|
private static final String TAG = "PackageManagerHelper";
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
private final PackageManager mPm;
|
private final PackageManager mPm;
|
||||||
private final LauncherAppsCompat mLauncherApps;
|
private final LauncherAppsCompat mLauncherApps;
|
||||||
|
@ -169,4 +183,35 @@ public class PackageManagerHelper {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the details activity for {@code info}
|
||||||
|
*/
|
||||||
|
public void startDetailsActivityForInfo(ItemInfo info, Rect sourceBounds, Bundle opts) {
|
||||||
|
if (info instanceof PromiseAppInfo) {
|
||||||
|
PromiseAppInfo promiseAppInfo = (PromiseAppInfo) info;
|
||||||
|
mContext.startActivity(promiseAppInfo.getMarketIntent(mContext));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ComponentName componentName = null;
|
||||||
|
if (info instanceof AppInfo) {
|
||||||
|
componentName = ((AppInfo) info).componentName;
|
||||||
|
} else if (info instanceof ShortcutInfo) {
|
||||||
|
componentName = info.getTargetComponent();
|
||||||
|
} else if (info instanceof PendingAddItemInfo) {
|
||||||
|
componentName = ((PendingAddItemInfo) info).componentName;
|
||||||
|
} else if (info instanceof LauncherAppWidgetInfo) {
|
||||||
|
componentName = ((LauncherAppWidgetInfo) info).providerName;
|
||||||
|
}
|
||||||
|
if (componentName != null) {
|
||||||
|
try {
|
||||||
|
mLauncherApps.showAppDetailsForProfile(
|
||||||
|
componentName, info.user, sourceBounds, opts);
|
||||||
|
} catch (SecurityException | ActivityNotFoundException e) {
|
||||||
|
Toast.makeText(mContext, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
|
||||||
|
Log.e(TAG, "Unable to launch settings", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,17 @@
|
||||||
android:resource="@xml/appwidget_no_config" />
|
android:resource="@xml/appwidget_no_config" />
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
|
||||||
|
<receiver
|
||||||
|
android:name="com.android.launcher3.testcomponent.AppWdigetHidden"
|
||||||
|
android:label="Hidden widget">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data android:name="android.appwidget.provider"
|
||||||
|
android:resource="@xml/appwidget_hidden" />
|
||||||
|
</receiver>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name="com.android.launcher3.testcomponent.AppWidgetWithConfig"
|
android:name="com.android.launcher3.testcomponent.AppWidgetWithConfig"
|
||||||
android:label="With Config">
|
android:label="With Config">
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<appwidget-provider
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:minWidth="180dp"
|
||||||
|
android:minHeight="110dp"
|
||||||
|
android:updatePeriodMillis="86400000"
|
||||||
|
android:initialLayout="@layout/test_layout_appwidget_blue"
|
||||||
|
android:resizeMode="horizontal|vertical"
|
||||||
|
android:widgetFeatures="hide_from_picker"
|
||||||
|
android:widgetCategory="home_screen">
|
||||||
|
</appwidget-provider>
|
|
@ -7,5 +7,6 @@
|
||||||
android:initialLayout="@layout/test_layout_appwidget_blue"
|
android:initialLayout="@layout/test_layout_appwidget_blue"
|
||||||
android:configure="com.android.launcher3.testcomponent.WidgetConfigActivity"
|
android:configure="com.android.launcher3.testcomponent.WidgetConfigActivity"
|
||||||
android:resizeMode="horizontal|vertical"
|
android:resizeMode="horizontal|vertical"
|
||||||
|
android:widgetFeatures="reconfigurable"
|
||||||
android:widgetCategory="home_screen">
|
android:widgetCategory="home_screen">
|
||||||
</appwidget-provider>
|
</appwidget-provider>
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2018 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.testcomponent;
|
||||||
|
|
||||||
|
import android.appwidget.AppWidgetProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple app widget without any configuration screen and is hidden in picker.
|
||||||
|
*/
|
||||||
|
public class AppWidgetHidden extends AppWidgetProvider { }
|
Loading…
Reference in New Issue