diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2017-01-13 12:15:53 -0800 |
---|---|---|
committer | Sunny Goyal <sunnygoyal@google.com> | 2017-01-18 18:38:34 -0800 |
commit | 278359539c02ca160caf1df54ce96053a2a2ef59 (patch) | |
tree | e4dc8afc511fd553ffe8766855bb9cefdf54656e | |
parent | 627006eeb4a9ba3bedacd7c0e4edce4fafdb9ac2 (diff) | |
download | android_packages_apps_Trebuchet-278359539c02ca160caf1df54ce96053a2a2ef59.tar.gz android_packages_apps_Trebuchet-278359539c02ca160caf1df54ce96053a2a2ef59.tar.bz2 android_packages_apps_Trebuchet-278359539c02ca160caf1df54ce96053a2a2ef59.zip |
Adding support for requesting addition of shortcut/widget
on the workspace.
Bug: 33584624
Change-Id: I664366822fe8088742faff2cce006239ab0771bc
-rw-r--r-- | AndroidManifest-common.xml | 8 | ||||
-rw-r--r-- | res/drawable/bg_drag_box.xml | 25 | ||||
-rw-r--r-- | res/layout/add_item_confirmation_activity.xml | 55 | ||||
-rw-r--r-- | res/values/strings.xml | 4 | ||||
-rw-r--r-- | src/com/android/launcher3/BaseActivity.java | 42 | ||||
-rw-r--r-- | src/com/android/launcher3/InstallShortcutReceiver.java | 4 | ||||
-rw-r--r-- | src/com/android/launcher3/InvariantDeviceProfile.java | 6 | ||||
-rw-r--r-- | src/com/android/launcher3/Launcher.java | 18 | ||||
-rw-r--r-- | src/com/android/launcher3/WidgetPreviewLoader.java | 8 | ||||
-rw-r--r-- | src/com/android/launcher3/compat/PinItemRequestCompat.java | 83 | ||||
-rw-r--r-- | src/com/android/launcher3/dragndrop/AddItemActivity.java | 207 | ||||
-rw-r--r-- | src/com/android/launcher3/model/AddWorkspaceItemsTask.java | 7 | ||||
-rw-r--r-- | src/com/android/launcher3/widget/WidgetCell.java | 12 |
13 files changed, 451 insertions, 28 deletions
diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml index bbe1f4a88..974b0df45 100644 --- a/AndroidManifest-common.xml +++ b/AndroidManifest-common.xml @@ -79,5 +79,13 @@ <meta-data android:name="android.nfc.disable_beam_default" android:value="true" /> + <activity android:name="com.android.launcher3.dragndrop.AddItemActivity" + android:theme="@android:style/Theme.DeviceDefault.Light.Dialog.Alert" + android:label="@string/action_add_to_workspace" > + <intent-filter> + <action android:name="android.content.pm.action.CONFIRM_PIN_ITEM" /> + </intent-filter> + </activity> + </application> </manifest> diff --git a/res/drawable/bg_drag_box.xml b/res/drawable/bg_drag_box.xml new file mode 100644 index 000000000..49b3b8618 --- /dev/null +++ b/res/drawable/bg_drag_box.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 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. +*/ +--> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle" > + <stroke android:color="?android:attr/colorAccent" + android:dashGap="2dp" + android:dashWidth="4dp" + android:width="1dp" /> +</shape> diff --git a/res/layout/add_item_confirmation_activity.xml b/res/layout/add_item_confirmation_activity.xml new file mode 100644 index 000000000..46d34447d --- /dev/null +++ b/res/layout/add_item_confirmation_activity.xml @@ -0,0 +1,55 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +/* +** Copyright 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. +*/ +--> +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent"> + + <TextView + android:padding="16dp" + android:text="@string/add_item_request_drag_hint" + android:layout_width="match_parent" + android:layout_height="wrap_content" /> + + <TextView + android:layout_width="match_parent" + android:layout_height="100dp" + android:layout_margin="10dp" + android:gravity="center" + android:id="@+id/drag_target" + android:background="@drawable/bg_drag_box" /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + style="?android:attr/buttonBarStyle" + android:gravity="end" > + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@android:string/cancel" + android:onClick="onCancelClick" + style="?android:attr/buttonBarButtonStyle" /> + <Button + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/place_automatically" + android:onClick="onPlaceAutomaticallyClick" + style="?android:attr/buttonBarButtonStyle" /> + </LinearLayout> +</LinearLayout> diff --git a/res/values/strings.xml b/res/values/strings.xml index a9c970d6d..f1de62378 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -52,6 +52,10 @@ <string name="widget_dims_format">%1$d \u00d7 %2$d</string> <!-- Accessibility spoken message format for the dimensions of a widget in the drawer --> <string name="widget_accessible_dims_format">%1$d wide by %2$d high</string> + <!-- Message to tell the user to press and hold a widget/icon to add it --> + <string name="add_item_request_drag_hint" translatable="false">Touch & hold to place on home screen</string> + <!-- Button label to automatically add icon on home screen [CHAR_LIMIT=50] --> + <string name="place_automatically" translatable="false">Place automatically</string> <!-- All Apps --> <!-- Search bar text in the apps view. [CHAR_LIMIT=50] --> diff --git a/src/com/android/launcher3/BaseActivity.java b/src/com/android/launcher3/BaseActivity.java new file mode 100644 index 000000000..9f4f1f9c4 --- /dev/null +++ b/src/com/android/launcher3/BaseActivity.java @@ -0,0 +1,42 @@ +/* + * 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; + +import android.app.Activity; +import android.content.Context; +import android.content.ContextWrapper; +import android.view.View.AccessibilityDelegate; + +public abstract class BaseActivity extends Activity { + + protected DeviceProfile mDeviceProfile; + + public DeviceProfile getDeviceProfile() { + return mDeviceProfile; + } + + public AccessibilityDelegate getAccessibilityDelegate() { + return null; + } + + public static BaseActivity fromContext(Context context) { + if (context instanceof BaseActivity) { + return (BaseActivity) context; + } + return ((BaseActivity) ((ContextWrapper) context).getBaseContext()); + } +} diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java index a35469e0c..96d6b895c 100644 --- a/src/com/android/launcher3/InstallShortcutReceiver.java +++ b/src/com/android/launcher3/InstallShortcutReceiver.java @@ -498,7 +498,9 @@ public class InstallShortcutReceiver extends BroadcastReceiver { DeepShortcutManager sm = DeepShortcutManager.getInstance(context); List<ShortcutInfoCompat> si = sm.queryForFullDetails( decoder.launcherIntent.getPackage(), - Arrays.asList(ShortcutInfoCompat.EXTRA_SHORTCUT_ID), decoder.user); + Arrays.asList(decoder.launcherIntent.getStringExtra( + ShortcutInfoCompat.EXTRA_SHORTCUT_ID)), + decoder.user); if (si.isEmpty()) { return null; } else { diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 1b0e5b371..e3c6965f7 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -18,6 +18,7 @@ package com.android.launcher3; import android.annotation.TargetApi; import android.content.Context; +import android.content.res.Configuration; import android.content.res.TypedArray; import android.content.res.XmlResourceParser; import android.graphics.Point; @@ -326,6 +327,11 @@ public class InvariantDeviceProfile { return rank == getAllAppsButtonRank(); } + public DeviceProfile getDeviceProfile(Context context) { + return context.getResources().getConfiguration().orientation + == Configuration.ORIENTATION_LANDSCAPE ? landscapeProfile : portraitProfile; + } + private float weight(float x0, float y0, float x1, float y1, float pow) { float d = dist(x0, y0, x1, y1); if (Float.compare(d, 0f) == 0) { diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index fc112f380..13534b97b 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -22,7 +22,6 @@ import android.animation.AnimatorSet; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.annotation.TargetApi; -import android.app.Activity; import android.app.ActivityOptions; import android.app.AlertDialog; import android.app.SearchManager; @@ -42,7 +41,6 @@ import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; -import android.content.res.Configuration; import android.database.sqlite.SQLiteDatabase; import android.graphics.Point; import android.graphics.Rect; @@ -136,7 +134,7 @@ import java.util.List; /** * Default launcher application. */ -public class Launcher extends Activity +public class Launcher extends BaseActivity implements LauncherExterns, View.OnClickListener, OnLongClickListener, LauncherModel.Callbacks, View.OnTouchListener, LauncherProviderChangeListener, AccessibilityManager.AccessibilityStateChangeListener { @@ -194,7 +192,7 @@ public class Launcher extends Activity private boolean mIsSafeModeEnabled; - static final int APPWIDGET_HOST_ID = 1024; + public static final int APPWIDGET_HOST_ID = 1024; public static final int EXIT_SPRINGLOADED_MODE_SHORT_TIMEOUT = 500; private static final int ON_ACTIVITY_RESULT_ANIMATION_DELAY = 500; private static final int ACTIVITY_START_DELAY = 1000; @@ -273,8 +271,6 @@ public class Launcher extends Activity // it from the context. private SharedPreferences mSharedPrefs; - private DeviceProfile mDeviceProfile; - private boolean mMoveToDefaultScreenFromNewIntent; // This is set to the view that launched the activity that navigated the user away from @@ -359,11 +355,7 @@ public class Launcher extends Activity LauncherAppState app = LauncherAppState.getInstance(this); // Load configuration-specific DeviceProfile - mDeviceProfile = - getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE - ? app.getInvariantDeviceProfile().landscapeProfile - : app.getInvariantDeviceProfile().portraitProfile; - + mDeviceProfile = app.getInvariantDeviceProfile().getDeviceProfile(this); if (Utilities.ATLEAST_NOUGAT && isInMultiWindowMode()) { Display display = getWindowManager().getDefaultDisplay(); Point mwSize = new Point(); @@ -1657,10 +1649,6 @@ public class Launcher extends Activity return mSharedPrefs; } - public DeviceProfile getDeviceProfile() { - return mDeviceProfile; - } - @Override protected void onNewIntent(Intent intent) { long startTime = 0; diff --git a/src/com/android/launcher3/WidgetPreviewLoader.java b/src/com/android/launcher3/WidgetPreviewLoader.java index 0f62b31c1..83c978e95 100644 --- a/src/com/android/launcher3/WidgetPreviewLoader.java +++ b/src/com/android/launcher3/WidgetPreviewLoader.java @@ -272,7 +272,7 @@ public class WidgetPreviewLoader { return null; } - private Bitmap generatePreview(Launcher launcher, WidgetItem item, Bitmap recycle, + private Bitmap generatePreview(BaseActivity launcher, WidgetItem item, Bitmap recycle, int previewWidth, int previewHeight) { if (item.widgetInfo != null) { return generateWidgetPreview(launcher, item.widgetInfo, @@ -294,7 +294,7 @@ public class WidgetPreviewLoader { * @param preScaledWidthOut return the width of the returned bitmap * @return */ - public Bitmap generateWidgetPreview(Launcher launcher, LauncherAppWidgetProviderInfo info, + public Bitmap generateWidgetPreview(BaseActivity launcher, LauncherAppWidgetProviderInfo info, int maxPreviewWidth, Bitmap preview, int[] preScaledWidthOut) { // Load the preview image if possible if (maxPreviewWidth < 0) maxPreviewWidth = Integer.MAX_VALUE; @@ -415,7 +415,7 @@ public class WidgetPreviewLoader { } private Bitmap generateShortcutPreview( - Launcher launcher, ActivityInfo info, int maxWidth, int maxHeight, Bitmap preview) { + BaseActivity launcher, ActivityInfo info, int maxWidth, int maxHeight, Bitmap preview) { final Canvas c = new Canvas(); if (preview == null) { preview = Bitmap.createBitmap(maxWidth, maxHeight, Config.ARGB_8888); @@ -591,7 +591,7 @@ public class WidgetPreviewLoader { // which would gets re-written next time. mVersions = getPackageVersion(mKey.componentName.getPackageName()); - Launcher launcher = Launcher.getLauncher(mCaller.getContext()); + BaseActivity launcher = BaseActivity.fromContext(mCaller.getContext()); // it's not in the db... we need to generate it preview = generatePreview(launcher, mInfo, unusedBitmap, mPreviewWidth, mPreviewHeight); diff --git a/src/com/android/launcher3/compat/PinItemRequestCompat.java b/src/com/android/launcher3/compat/PinItemRequestCompat.java new file mode 100644 index 000000000..956b38cb1 --- /dev/null +++ b/src/com/android/launcher3/compat/PinItemRequestCompat.java @@ -0,0 +1,83 @@ +/* + * 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.compat; + +import android.appwidget.AppWidgetProviderInfo; +import android.content.Intent; +import android.content.pm.ShortcutInfo; +import android.os.Bundle; +import android.os.Parcelable; + +/** + * A wrapper around platform implementation of PinItemRequestCompat until the + * updated SDK is available. + */ +public class PinItemRequestCompat { + + public static final String EXTRA_PIN_ITEM_REQUEST = "android.content.pm.extra.PIN_ITEM_REQUEST"; + + public static final int REQUEST_TYPE_SHORTCUT = 1; + public static final int REQUEST_TYPE_APPWIDGET = 2; + + private final Parcelable mObject; + + private PinItemRequestCompat(Parcelable object) { + mObject = object; + } + + public int getRequestType() { + return (Integer) invokeMethod("getRequestType"); + } + + public ShortcutInfo getShortcutInfo() { + return (ShortcutInfo) invokeMethod("getShortcutInfo"); + } + + public AppWidgetProviderInfo getAppWidgetProviderInfo() { + return (AppWidgetProviderInfo) invokeMethod("getAppWidgetProviderInfo"); + } + + public boolean isValid() { + return (Boolean) invokeMethod("isValid"); + } + + public boolean accept() { + return (Boolean) invokeMethod("accept"); + } + + public boolean accept(Bundle options) { + try { + return (Boolean) mObject.getClass().getDeclaredMethod("accept", Bundle.class) + .invoke(mObject, options); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private Object invokeMethod(String methodName) { + try { + return mObject.getClass().getDeclaredMethod(methodName).invoke(mObject); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static PinItemRequestCompat getPinItemRequest(Intent intent) { + Parcelable extra = intent.getParcelableExtra(EXTRA_PIN_ITEM_REQUEST); + return extra == null ? null : new PinItemRequestCompat(extra); + } +} diff --git a/src/com/android/launcher3/dragndrop/AddItemActivity.java b/src/com/android/launcher3/dragndrop/AddItemActivity.java new file mode 100644 index 000000000..c48db60fa --- /dev/null +++ b/src/com/android/launcher3/dragndrop/AddItemActivity.java @@ -0,0 +1,207 @@ +/* + * 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.dragndrop; + +import android.annotation.TargetApi; +import android.appwidget.AppWidgetHost; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProviderInfo; +import android.content.Intent; +import android.graphics.Bitmap; +import android.os.Build; +import android.os.Bundle; +import android.text.TextUtils; +import android.view.View; +import android.widget.TextView; + +import com.android.launcher3.BaseActivity; +import com.android.launcher3.FastBitmapDrawable; +import com.android.launcher3.InstallShortcutReceiver; +import com.android.launcher3.InvariantDeviceProfile; +import com.android.launcher3.Launcher; +import com.android.launcher3.LauncherAppState; +import com.android.launcher3.LauncherAppWidgetProviderInfo; +import com.android.launcher3.R; +import com.android.launcher3.compat.AppWidgetManagerCompat; +import com.android.launcher3.compat.PinItemRequestCompat; +import com.android.launcher3.graphics.LauncherIcons; +import com.android.launcher3.shortcuts.DeepShortcutManager; +import com.android.launcher3.shortcuts.ShortcutInfoCompat; +import com.android.launcher3.widget.PendingAddWidgetInfo; +import com.android.launcher3.widget.WidgetHostViewLoader; + +@TargetApi(Build.VERSION_CODES.N_MR1) +public class AddItemActivity extends BaseActivity { + + private static final int REQUEST_BIND_APPWIDGET = 1; + private static final String STATE_EXTRA_WIDGET_ID = "state.widget.id"; + + private PinItemRequestCompat mRequest; + private LauncherAppState mApp; + private InvariantDeviceProfile mIdp; + + private TextView mTextView; + + // Widget request specific options. + private AppWidgetHost mAppWidgetHost; + private AppWidgetManagerCompat mAppWidgetManager; + private PendingAddWidgetInfo mPendingWidgetInfo; + private int mPendingBindWidgetId; + private Bundle mWidgetOptions; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mRequest = PinItemRequestCompat.getPinItemRequest(getIntent()); + if (mRequest == null) { + finish(); + return; + } + + setContentView(R.layout.add_item_confirmation_activity); + mTextView = (TextView) findViewById(R.id.drag_target); + + mApp = LauncherAppState.getInstance(this); + mIdp = mApp.getInvariantDeviceProfile(); + + // Use the application context to get the device profile, as in multiwindow-mode, the + // confirmation activity might be rotated. + mDeviceProfile = mIdp.getDeviceProfile(getApplicationContext()); + + if (mRequest.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_SHORTCUT) { + setupShortcut(); + } else { + if (!setupWidget()) { + // TODO: show error toast? + finish(); + } + } + } + + private void setupShortcut() { + ShortcutInfoCompat shortcut = new ShortcutInfoCompat(mRequest.getShortcutInfo()); + FastBitmapDrawable d = new FastBitmapDrawable(LauncherIcons.createIconBitmap( + DeepShortcutManager.getInstance(this).getShortcutIconDrawable( + shortcut, mIdp.fillResIconDpi), this)); + d.setFilterBitmap(true); + mTextView.setText(TextUtils.isEmpty(shortcut.getLongLabel()) + ? shortcut.getShortLabel() : shortcut.getLongLabel()); + mTextView.setCompoundDrawables(null, d, null, null); + } + + private boolean setupWidget() { + AppWidgetProviderInfo info = mRequest.getAppWidgetProviderInfo(); + LauncherAppWidgetProviderInfo widgetInfo = AppWidgetManagerCompat.getInstance(this) + .findProvider(info.provider, info.getProfile()); + if (widgetInfo.minSpanX > mIdp.numColumns || widgetInfo.minSpanY > mIdp.numRows) { + // Cannot add widget + return false; + } + + mAppWidgetManager = AppWidgetManagerCompat.getInstance(this); + mAppWidgetHost = new AppWidgetHost(this, Launcher.APPWIDGET_HOST_ID); + + mPendingWidgetInfo = new PendingAddWidgetInfo(widgetInfo); + mPendingWidgetInfo.spanX = Math.min(mIdp.numColumns, widgetInfo.spanX); + mPendingWidgetInfo.spanY = Math.min(mIdp.numRows, widgetInfo.spanY); + mWidgetOptions = WidgetHostViewLoader.getDefaultOptionsForWidget(this, mPendingWidgetInfo); + + Bitmap preview = mApp.getWidgetCache().generateWidgetPreview(this, widgetInfo, + mPendingWidgetInfo.spanX * mDeviceProfile.cellWidthPx, null, null); + FastBitmapDrawable d = new FastBitmapDrawable(preview); + d.setFilterBitmap(true); + mTextView.setText(widgetInfo.getLabel(getPackageManager())); + mTextView.setCompoundDrawables(null, d, null, null); + return true; + } + + /** + * Called when the cancel button is clicked. + */ + public void onCancelClick(View v) { + finish(); + } + + /** + * Called when place-automatically button is clicked. + */ + public void onPlaceAutomaticallyClick(View v) { + if (mRequest.getRequestType() == PinItemRequestCompat.REQUEST_TYPE_SHORTCUT) { + InstallShortcutReceiver.queueShortcut( + new ShortcutInfoCompat(mRequest.getShortcutInfo()), this); + mRequest.accept(); + finish(); + return; + } + + mPendingBindWidgetId = mAppWidgetHost.allocateAppWidgetId(); + boolean success = mAppWidgetManager.bindAppWidgetIdIfAllowed( + mPendingBindWidgetId, mRequest.getAppWidgetProviderInfo(), mWidgetOptions); + if (success) { + acceptWidget(mPendingBindWidgetId); + return; + } + + // request bind widget + Intent intent = new Intent(AppWidgetManager.ACTION_APPWIDGET_BIND); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mPendingBindWidgetId); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER, + mPendingWidgetInfo.componentName); + intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_PROVIDER_PROFILE, + mRequest.getAppWidgetProviderInfo().getProfile()); + startActivityForResult(intent, REQUEST_BIND_APPWIDGET); + } + + private void acceptWidget(int widgetId) { + InstallShortcutReceiver.queueWidget(mRequest.getAppWidgetProviderInfo(), widgetId, this); + mWidgetOptions.putInt(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); + mRequest.accept(mWidgetOptions); + finish(); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + if (requestCode == REQUEST_BIND_APPWIDGET) { + int widgetId = data != null + ? data.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, mPendingBindWidgetId) + : mPendingBindWidgetId; + if (resultCode == RESULT_OK) { + acceptWidget(widgetId); + } else { + // Simply wait it out. + mAppWidgetHost.deleteAppWidgetId(widgetId); + mPendingBindWidgetId = -1; + } + return; + } + super.onActivityResult(requestCode, resultCode, data); + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putInt(STATE_EXTRA_WIDGET_ID, mPendingBindWidgetId); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + mPendingBindWidgetId = savedInstanceState + .getInt(STATE_EXTRA_WIDGET_ID, mPendingBindWidgetId); + } +} diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java index a03dd8f34..c97b3b5cf 100644 --- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java +++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java @@ -70,7 +70,8 @@ public class AddWorkspaceItemsTask extends ExtendedModelTask { ArrayList<Long> workspaceScreens = LauncherModel.loadWorkspaceScreensDb(context); synchronized(dataModel) { for (ItemInfo item : workspaceApps) { - if (item instanceof ShortcutInfo) { + if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION || + item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) { // Short-circuit this logic if the icon exists somewhere on the workspace if (shortcutExists(dataModel, item.getIntent(), item.user)) { continue; @@ -143,6 +144,10 @@ public class AddWorkspaceItemsTask extends ExtendedModelTask { */ protected boolean shortcutExists(BgDataModel dataModel, Intent intent, UserHandle user) { final String intentWithPkg, intentWithoutPkg; + if (intent == null) { + // Skip items with null intents + return true; + } if (intent.getComponent() != null) { // If component is not null, an intent with null package will produce // the same result and should also be a match. diff --git a/src/com/android/launcher3/widget/WidgetCell.java b/src/com/android/launcher3/widget/WidgetCell.java index 5eeae87e2..9e2091b50 100644 --- a/src/com/android/launcher3/widget/WidgetCell.java +++ b/src/com/android/launcher3/widget/WidgetCell.java @@ -17,7 +17,6 @@ package com.android.launcher3.widget; import android.content.Context; -import android.content.res.Resources; import android.graphics.Bitmap; import android.util.AttributeSet; import android.util.Log; @@ -28,8 +27,8 @@ import android.view.ViewPropertyAnimator; import android.widget.LinearLayout; import android.widget.TextView; +import com.android.launcher3.BaseActivity; import com.android.launcher3.DeviceProfile; -import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.SimpleOnStylusPressListener; import com.android.launcher3.StylusEventHelper; @@ -72,7 +71,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { private PreviewLoadRequest mActiveRequest; private StylusEventHelper mStylusEventHelper; - private final Launcher mLauncher; + private final BaseActivity mActivity; public WidgetCell(Context context) { this(context, null); @@ -85,18 +84,17 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener { public WidgetCell(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); - final Resources r = context.getResources(); - mLauncher = Launcher.getLauncher(context); + mActivity = BaseActivity.fromContext(context); mStylusEventHelper = new StylusEventHelper(new SimpleOnStylusPressListener(this), this); setContainerWidth(); setWillNotDraw(false); setClipToPadding(false); - setAccessibilityDelegate(mLauncher.getAccessibilityDelegate()); + setAccessibilityDelegate(mActivity.getAccessibilityDelegate()); } private void setContainerWidth() { - DeviceProfile profile = mLauncher.getDeviceProfile(); + DeviceProfile profile = mActivity.getDeviceProfile(); cellSize = (int) (profile.cellWidthPx * WIDTH_SCALE); mPresetPreviewSize = (int) (cellSize * PREVIEW_SCALE); } |