1 /* 2 * Copyright (C) 2009 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 com.android.launcher3; 18 19 import android.appwidget.AppWidgetHost; 20 import android.appwidget.AppWidgetHostView; 21 import android.appwidget.AppWidgetProviderInfo; 22 import android.content.Context; 23 import android.os.TransactionTooLargeException; 24 import android.view.LayoutInflater; 25 import android.view.View; 26 27 import java.util.ArrayList; 28 29 30 /** 31 * Specific {@link AppWidgetHost} that creates our {@link LauncherAppWidgetHostView} 32 * which correctly captures all long-press events. This ensures that users can 33 * always pick up and move widgets. 34 */ 35 public class LauncherAppWidgetHost extends AppWidgetHost { 36 37 private final ArrayList<Runnable> mProviderChangeListeners = new ArrayList<Runnable>(); 38 39 private int mQsbWidgetId = -1; 40 private Launcher mLauncher; 41 42 public LauncherAppWidgetHost(Launcher launcher, int hostId) { 43 super(launcher, hostId); 44 mLauncher = launcher; 45 } 46 47 public void setQsbWidgetId(int widgetId) { 48 mQsbWidgetId = widgetId; 49 } 50 51 @Override 52 protected AppWidgetHostView onCreateView(Context context, int appWidgetId, 53 AppWidgetProviderInfo appWidget) { 54 if (appWidgetId == mQsbWidgetId) { 55 return new LauncherAppWidgetHostView(context) { 56 57 @Override 58 protected View getErrorView() { 59 // For the QSB, show an empty view instead of an error view. 60 return new View(getContext()); 61 } 62 }; 63 } 64 return new LauncherAppWidgetHostView(context); 65 } 66 67 @Override 68 public void startListening() { 69 try { 70 super.startListening(); 71 } catch (Exception e) { 72 if (e.getCause() instanceof TransactionTooLargeException) { 73 // We're willing to let this slide. The exception is being caused by the list of 74 // RemoteViews which is being passed back. The startListening relationship will 75 // have been established by this point, and we will end up populating the 76 // widgets upon bind anyway. See issue 14255011 for more context. 77 } else { 78 throw new RuntimeException(e); 79 } 80 } 81 } 82 83 @Override 84 public void stopListening() { 85 super.stopListening(); 86 clearViews(); 87 } 88 89 public void addProviderChangeListener(Runnable callback) { 90 mProviderChangeListeners.add(callback); 91 } 92 93 public void removeProviderChangeListener(Runnable callback) { 94 mProviderChangeListeners.remove(callback); 95 } 96 97 protected void onProvidersChanged() { 98 mLauncher.getModel().loadAndBindWidgetsAndShortcuts(mLauncher, mLauncher, 99 true /* refresh */); 100 if (!mProviderChangeListeners.isEmpty()) { 101 for (Runnable callback : new ArrayList<>(mProviderChangeListeners)) { 102 callback.run(); 103 } 104 } 105 } 106 107 public AppWidgetHostView createView(Context context, int appWidgetId, 108 LauncherAppWidgetProviderInfo appWidget) { 109 if (appWidget.isCustomWidget) { 110 LauncherAppWidgetHostView lahv = new LauncherAppWidgetHostView(context); 111 LayoutInflater inflater = (LayoutInflater) 112 context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 113 inflater.inflate(appWidget.initialLayout, lahv); 114 lahv.setAppWidget(0, appWidget); 115 lahv.updateLastInflationOrientation(); 116 return lahv; 117 } else { 118 return super.createView(context, appWidgetId, appWidget); 119 } 120 } 121 122 /** 123 * Called when the AppWidget provider for a AppWidget has been upgraded to a new apk. 124 */ 125 @Override 126 protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidget) { 127 LauncherAppWidgetProviderInfo info = LauncherAppWidgetProviderInfo.fromProviderInfo( 128 mLauncher, appWidget); 129 super.onProviderChanged(appWidgetId, info); 130 } 131 } 132