AppWidgetHost.java revision f140be6c3c21dd0f6d2214929e89d60de31d2c04
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 17package android.appwidget; 18 19import android.content.Context; 20import android.os.Handler; 21import android.os.IBinder; 22import android.os.Looper; 23import android.os.Message; 24import android.os.RemoteException; 25import android.os.ServiceManager; 26import android.widget.RemoteViews; 27 28import java.util.ArrayList; 29import java.util.HashMap; 30 31import com.android.internal.appwidget.IAppWidgetHost; 32import com.android.internal.appwidget.IAppWidgetService; 33 34/** 35 * AppWidgetHost provides the interaction with the AppWidget service for apps, 36 * like the home screen, that want to embed AppWidgets in their UI. 37 */ 38public class AppWidgetHost { 39 40 static final int HANDLE_UPDATE = 1; 41 static final int HANDLE_PROVIDER_CHANGED = 2; 42 43 final static Object sServiceLock = new Object(); 44 static IAppWidgetService sService; 45 46 Context mContext; 47 String mPackageName; 48 49 class Callbacks extends IAppWidgetHost.Stub { 50 public void updateAppWidget(int appWidgetId, RemoteViews views) { 51 Message msg = mHandler.obtainMessage(HANDLE_UPDATE); 52 msg.arg1 = appWidgetId; 53 msg.obj = views; 54 msg.sendToTarget(); 55 } 56 57 public void providerChanged(int appWidgetId, AppWidgetProviderInfo info) { 58 Message msg = mHandler.obtainMessage(HANDLE_PROVIDER_CHANGED); 59 msg.arg1 = appWidgetId; 60 msg.obj = info; 61 msg.sendToTarget(); 62 } 63 } 64 65 class UpdateHandler extends Handler { 66 public UpdateHandler(Looper looper) { 67 super(looper); 68 } 69 70 public void handleMessage(Message msg) { 71 switch (msg.what) { 72 case HANDLE_UPDATE: { 73 updateAppWidgetView(msg.arg1, (RemoteViews)msg.obj); 74 break; 75 } 76 case HANDLE_PROVIDER_CHANGED: { 77 onProviderChanged(msg.arg1, (AppWidgetProviderInfo)msg.obj); 78 break; 79 } 80 } 81 } 82 } 83 84 Handler mHandler; 85 86 int mHostId; 87 Callbacks mCallbacks = new Callbacks(); 88 final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<Integer, AppWidgetHostView>(); 89 90 public AppWidgetHost(Context context, int hostId) { 91 mContext = context; 92 mHostId = hostId; 93 mHandler = new UpdateHandler(context.getMainLooper()); 94 synchronized (sServiceLock) { 95 if (sService == null) { 96 IBinder b = ServiceManager.getService(Context.APPWIDGET_SERVICE); 97 sService = IAppWidgetService.Stub.asInterface(b); 98 } 99 } 100 } 101 102 /** 103 * Start receiving onAppWidgetChanged calls for your AppWidgets. Call this when your activity 104 * becomes visible, i.e. from onStart() in your Activity. 105 */ 106 public void startListening() { 107 int[] updatedIds; 108 ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>(); 109 110 try { 111 if (mPackageName == null) { 112 mPackageName = mContext.getPackageName(); 113 } 114 updatedIds = sService.startListening(mCallbacks, mPackageName, mHostId, updatedViews); 115 } 116 catch (RemoteException e) { 117 throw new RuntimeException("system server dead?", e); 118 } 119 120 final int N = updatedIds.length; 121 for (int i=0; i<N; i++) { 122 updateAppWidgetView(updatedIds[i], updatedViews.get(i)); 123 } 124 } 125 126 /** 127 * Stop receiving onAppWidgetChanged calls for your AppWidgets. Call this when your activity is 128 * no longer visible, i.e. from onStop() in your Activity. 129 */ 130 public void stopListening() { 131 try { 132 sService.stopListening(mHostId); 133 } 134 catch (RemoteException e) { 135 throw new RuntimeException("system server dead?", e); 136 } 137 } 138 139 /** 140 * Get a appWidgetId for a host in the calling process. 141 * 142 * @return a appWidgetId 143 */ 144 public int allocateAppWidgetId() { 145 try { 146 if (mPackageName == null) { 147 mPackageName = mContext.getPackageName(); 148 } 149 return sService.allocateAppWidgetId(mPackageName, mHostId); 150 } 151 catch (RemoteException e) { 152 throw new RuntimeException("system server dead?", e); 153 } 154 } 155 156 /** 157 * Stop listening to changes for this AppWidget. 158 */ 159 public void deleteAppWidgetId(int appWidgetId) { 160 synchronized (mViews) { 161 mViews.remove(appWidgetId); 162 try { 163 sService.deleteAppWidgetId(appWidgetId); 164 } 165 catch (RemoteException e) { 166 throw new RuntimeException("system server dead?", e); 167 } 168 } 169 } 170 171 /** 172 * Remove all records about this host from the AppWidget manager. 173 * <ul> 174 * <li>Call this when initializing your database, as it might be because of a data wipe.</li> 175 * <li>Call this to have the AppWidget manager release all resources associated with your 176 * host. Any future calls about this host will cause the records to be re-allocated.</li> 177 * </ul> 178 */ 179 public void deleteHost() { 180 try { 181 sService.deleteHost(mHostId); 182 } 183 catch (RemoteException e) { 184 throw new RuntimeException("system server dead?", e); 185 } 186 } 187 188 /** 189 * Remove all records about all hosts for your package. 190 * <ul> 191 * <li>Call this when initializing your database, as it might be because of a data wipe.</li> 192 * <li>Call this to have the AppWidget manager release all resources associated with your 193 * host. Any future calls about this host will cause the records to be re-allocated.</li> 194 * </ul> 195 */ 196 public static void deleteAllHosts() { 197 try { 198 sService.deleteAllHosts(); 199 } 200 catch (RemoteException e) { 201 throw new RuntimeException("system server dead?", e); 202 } 203 } 204 205 public final AppWidgetHostView createView(Context context, int appWidgetId, 206 AppWidgetProviderInfo appWidget) { 207 AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget); 208 view.setAppWidget(appWidgetId, appWidget); 209 synchronized (mViews) { 210 mViews.put(appWidgetId, view); 211 } 212 RemoteViews views; 213 try { 214 views = sService.getAppWidgetViews(appWidgetId); 215 } catch (RemoteException e) { 216 throw new RuntimeException("system server dead?", e); 217 } 218 view.updateAppWidget(views); 219 return view; 220 } 221 222 /** 223 * Called to create the AppWidgetHostView. Override to return a custom subclass if you 224 * need it. {@more} 225 */ 226 protected AppWidgetHostView onCreateView(Context context, int appWidgetId, 227 AppWidgetProviderInfo appWidget) { 228 return new AppWidgetHostView(context); 229 } 230 231 /** 232 * Called when the AppWidget provider for a AppWidget has been upgraded to a new apk. 233 */ 234 protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidget) { 235 AppWidgetHostView v; 236 synchronized (mViews) { 237 v = mViews.get(appWidgetId); 238 } 239 if (v != null) { 240 v.updateAppWidget(null, AppWidgetHostView.UPDATE_FLAGS_RESET); 241 } 242 } 243 244 void updateAppWidgetView(int appWidgetId, RemoteViews views) { 245 AppWidgetHostView v; 246 synchronized (mViews) { 247 v = mViews.get(appWidgetId); 248 } 249 if (v != null) { 250 v.updateAppWidget(views, 0); 251 } 252 } 253} 254 255 256