Skip to content

Commit e667a7a

Browse files
author
Jim Miller
committed
Update AppWidgetHost with better support for OnClickHandlers
This updates AppWidgetHost and AppWidgetHostView to do a better job at refreshing widgets and their host views. It now allows an OnClickHandler to be specified when creating the AppWidgetHost which allows it to correctly update AppWidgetHostViews when needed. Change-Id: I710c1d00a8d145bf3a9fd5f5691885bec9d1c7e4
1 parent f337a89 commit e667a7a

File tree

3 files changed

+101
-70
lines changed

3 files changed

+101
-70
lines changed

core/java/android/appwidget/AppWidgetHost.java

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import android.util.DisplayMetrics;
3030
import android.util.TypedValue;
3131
import android.widget.RemoteViews;
32+
import android.widget.RemoteViews.OnClickHandler;
3233

3334
import com.android.internal.appwidget.IAppWidgetHost;
3435
import com.android.internal.appwidget.IAppWidgetService;
@@ -83,7 +84,7 @@ class UpdateHandler extends Handler {
8384
public UpdateHandler(Looper looper) {
8485
super(looper);
8586
}
86-
87+
8788
public void handleMessage(Message msg) {
8889
switch (msg.what) {
8990
case HANDLE_UPDATE: {
@@ -105,16 +106,25 @@ public void handleMessage(Message msg) {
105106
}
106107
}
107108
}
108-
109+
109110
Handler mHandler;
110111

111112
int mHostId;
112113
Callbacks mCallbacks = new Callbacks();
113114
final HashMap<Integer,AppWidgetHostView> mViews = new HashMap<Integer, AppWidgetHostView>();
115+
private OnClickHandler mOnClickHandler;
114116

115117
public AppWidgetHost(Context context, int hostId) {
118+
this(context, hostId, null);
119+
}
120+
121+
/**
122+
* @hide
123+
*/
124+
public AppWidgetHost(Context context, int hostId, OnClickHandler handler) {
116125
mContext = context;
117126
mHostId = hostId;
127+
mOnClickHandler = handler;
118128
mHandler = new UpdateHandler(context.getMainLooper());
119129
mDisplayMetrics = context.getResources().getDisplayMetrics();
120130
synchronized (sServiceLock) {
@@ -132,7 +142,7 @@ public AppWidgetHost(Context context, int hostId) {
132142
public void startListening() {
133143
int[] updatedIds;
134144
ArrayList<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
135-
145+
136146
try {
137147
if (mPackageName == null) {
138148
mPackageName = mContext.getPackageName();
@@ -180,7 +190,7 @@ public int allocateAppWidgetId() {
180190
}
181191

182192
/**
183-
* Stop listening to changes for this AppWidget.
193+
* Stop listening to changes for this AppWidget.
184194
*/
185195
public void deleteAppWidgetId(int appWidgetId) {
186196
synchronized (mViews) {
@@ -235,6 +245,7 @@ public static void deleteAllHosts() {
235245
public final AppWidgetHostView createView(Context context, int appWidgetId,
236246
AppWidgetProviderInfo appWidget) {
237247
AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget);
248+
view.setOnClickHandler(mOnClickHandler);
238249
view.setAppWidget(appWidgetId, appWidget);
239250
synchronized (mViews) {
240251
mViews.put(appWidgetId, view);
@@ -246,6 +257,7 @@ public final AppWidgetHostView createView(Context context, int appWidgetId,
246257
throw new RuntimeException("system server dead?", e);
247258
}
248259
view.updateAppWidget(views);
260+
249261
return view;
250262
}
251263

@@ -255,7 +267,7 @@ public final AppWidgetHostView createView(Context context, int appWidgetId,
255267
*/
256268
protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
257269
AppWidgetProviderInfo appWidget) {
258-
return new AppWidgetHostView(context);
270+
return new AppWidgetHostView(context, mOnClickHandler);
259271
}
260272

261273
/**
@@ -265,7 +277,7 @@ protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidge
265277
AppWidgetHostView v;
266278

267279
// Convert complex to dp -- we are getting the AppWidgetProviderInfo from the
268-
// AppWidgetService, which doesn't have our context, hence we need to do the
280+
// AppWidgetService, which doesn't have our context, hence we need to do the
269281
// conversion here.
270282
appWidget.minWidth =
271283
TypedValue.complexToDimensionPixelSize(appWidget.minWidth, mDisplayMetrics);

core/java/android/appwidget/AppWidgetHostView.java

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
import android.widget.BaseAdapter;
4545
import android.widget.FrameLayout;
4646
import android.widget.RemoteViews;
47+
import android.widget.RemoteViews.OnClickHandler;
4748
import android.widget.RemoteViewsAdapter.RemoteAdapterConnectionCallback;
4849
import android.widget.TextView;
4950

@@ -83,18 +84,27 @@ public boolean onLoadClass(Class clazz) {
8384
long mFadeStartTime = -1;
8485
Bitmap mOld;
8586
Paint mOldPaint = new Paint();
86-
87+
private OnClickHandler mOnClickHandler;
88+
8789
/**
8890
* Create a host view. Uses default fade animations.
8991
*/
9092
public AppWidgetHostView(Context context) {
9193
this(context, android.R.anim.fade_in, android.R.anim.fade_out);
9294
}
9395

96+
/**
97+
* @hide
98+
*/
99+
public AppWidgetHostView(Context context, OnClickHandler handler) {
100+
this(context, android.R.anim.fade_in, android.R.anim.fade_out);
101+
mOnClickHandler = handler;
102+
}
103+
94104
/**
95105
* Create a host view. Uses specified animations when pushing
96106
* {@link #updateAppWidget(RemoteViews)}.
97-
*
107+
*
98108
* @param animationIn Resource ID of in animation to use
99109
* @param animationOut Resource ID of out animation to use
100110
*/
@@ -108,6 +118,17 @@ public AppWidgetHostView(Context context, int animationIn, int animationOut) {
108118
setIsRootNamespace(true);
109119
}
110120

121+
/**
122+
* Pass the given handler to RemoteViews when updating this widget. Unless this
123+
* is done immediatly after construction, a call to {@link #updateAppWidget(RemoteViews)}
124+
* should be made.
125+
* @param handler
126+
* @hide
127+
*/
128+
public void setOnClickHandler(OnClickHandler handler) {
129+
mOnClickHandler = handler;
130+
}
131+
111132
/**
112133
* Set the AppWidget that will be displayed by this view. This method also adds default padding
113134
* to widgets, as described in {@link #getDefaultPaddingForWidget(Context, ComponentName, Rect)}
@@ -177,7 +198,7 @@ public static Rect getDefaultPaddingForWidget(Context context, ComponentName com
177198
public int getAppWidgetId() {
178199
return mAppWidgetId;
179200
}
180-
201+
181202
public AppWidgetProviderInfo getAppWidgetInfo() {
182203
return mInfo;
183204
}
@@ -281,12 +302,13 @@ void resetAppWidget(AppWidgetProviderInfo info) {
281302
* AppWidget provider. Will animate into these new views as needed
282303
*/
283304
public void updateAppWidget(RemoteViews remoteViews) {
305+
284306
if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld);
285307

286308
boolean recycled = false;
287309
View content = null;
288310
Exception exception = null;
289-
311+
290312
// Capture the old view into a bitmap so we can do the crossfade.
291313
if (CROSSFADE) {
292314
if (mFadeStartTime < 0) {
@@ -305,7 +327,7 @@ public void updateAppWidget(RemoteViews remoteViews) {
305327
}
306328
}
307329
}
308-
330+
309331
if (remoteViews == null) {
310332
if (mViewMode == VIEW_MODE_DEFAULT) {
311333
// We've already done this -- nothing to do.
@@ -324,19 +346,19 @@ public void updateAppWidget(RemoteViews remoteViews) {
324346
// layout matches, try recycling it
325347
if (content == null && layoutId == mLayoutId) {
326348
try {
327-
remoteViews.reapply(mContext, mView);
349+
remoteViews.reapply(mContext, mView, mOnClickHandler);
328350
content = mView;
329351
recycled = true;
330352
if (LOGD) Log.d(TAG, "was able to recycled existing layout");
331353
} catch (RuntimeException e) {
332354
exception = e;
333355
}
334356
}
335-
357+
336358
// Try normal RemoteView inflation
337359
if (content == null) {
338360
try {
339-
content = remoteViews.apply(mContext, this);
361+
content = remoteViews.apply(mContext, this, mOnClickHandler);
340362
if (LOGD) Log.d(TAG, "had to inflate new layout");
341363
} catch (RuntimeException e) {
342364
exception = e;
@@ -346,7 +368,7 @@ public void updateAppWidget(RemoteViews remoteViews) {
346368
mLayoutId = layoutId;
347369
mViewMode = VIEW_MODE_CONTENT;
348370
}
349-
371+
350372
if (content == null) {
351373
if (mViewMode == VIEW_MODE_ERROR) {
352374
// We've already done this -- nothing to do.
@@ -356,7 +378,7 @@ public void updateAppWidget(RemoteViews remoteViews) {
356378
content = getErrorView();
357379
mViewMode = VIEW_MODE_ERROR;
358380
}
359-
381+
360382
if (!recycled) {
361383
prepareView(content);
362384
addView(content);
@@ -455,7 +477,7 @@ protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
455477
return super.drawChild(canvas, child, drawingTime);
456478
}
457479
}
458-
480+
459481
/**
460482
* Prepare the given view to be shown. This might include adjusting
461483
* {@link FrameLayout.LayoutParams} before inserting.
@@ -471,7 +493,7 @@ protected void prepareView(View view) {
471493
requested.gravity = Gravity.CENTER;
472494
view.setLayoutParams(requested);
473495
}
474-
496+
475497
/**
476498
* Inflate and return the default layout requested by AppWidget provider.
477499
*/
@@ -481,7 +503,7 @@ protected View getDefaultView() {
481503
}
482504
View defaultView = null;
483505
Exception exception = null;
484-
506+
485507
try {
486508
if (mInfo != null) {
487509
Context theirContext = mContext.createPackageContext(
@@ -500,19 +522,19 @@ protected View getDefaultView() {
500522
} catch (RuntimeException e) {
501523
exception = e;
502524
}
503-
525+
504526
if (exception != null) {
505527
Log.w(TAG, "Error inflating AppWidget " + mInfo + ": " + exception.toString());
506528
}
507-
529+
508530
if (defaultView == null) {
509531
if (LOGD) Log.d(TAG, "getDefaultView couldn't find any view, so inflating error");
510532
defaultView = getErrorView();
511533
}
512-
534+
513535
return defaultView;
514536
}
515-
537+
516538
/**
517539
* Inflate and return a view that represents an error state.
518540
*/

0 commit comments

Comments
 (0)