diff --git a/core/java/android/appwidget/AppWidgetHost.java b/core/java/android/appwidget/AppWidgetHost.java index 2c19c0c54536a..c76bf91fcae72 100644 --- a/core/java/android/appwidget/AppWidgetHost.java +++ b/core/java/android/appwidget/AppWidgetHost.java @@ -29,6 +29,7 @@ import android.os.ServiceManager; import android.util.DisplayMetrics; import android.util.TypedValue; import android.widget.RemoteViews; +import android.widget.RemoteViews.OnClickHandler; import com.android.internal.appwidget.IAppWidgetHost; import com.android.internal.appwidget.IAppWidgetService; @@ -83,7 +84,7 @@ public class AppWidgetHost { public UpdateHandler(Looper looper) { super(looper); } - + public void handleMessage(Message msg) { switch (msg.what) { case HANDLE_UPDATE: { @@ -105,16 +106,25 @@ public class AppWidgetHost { } } } - + Handler mHandler; int mHostId; Callbacks mCallbacks = new Callbacks(); final HashMap mViews = new HashMap(); + private OnClickHandler mOnClickHandler; public AppWidgetHost(Context context, int hostId) { + this(context, hostId, null); + } + + /** + * @hide + */ + public AppWidgetHost(Context context, int hostId, OnClickHandler handler) { mContext = context; mHostId = hostId; + mOnClickHandler = handler; mHandler = new UpdateHandler(context.getMainLooper()); mDisplayMetrics = context.getResources().getDisplayMetrics(); synchronized (sServiceLock) { @@ -132,7 +142,7 @@ public class AppWidgetHost { public void startListening() { int[] updatedIds; ArrayList updatedViews = new ArrayList(); - + try { if (mPackageName == null) { mPackageName = mContext.getPackageName(); @@ -180,7 +190,7 @@ public class AppWidgetHost { } /** - * Stop listening to changes for this AppWidget. + * Stop listening to changes for this AppWidget. */ public void deleteAppWidgetId(int appWidgetId) { synchronized (mViews) { @@ -235,6 +245,7 @@ public class AppWidgetHost { public final AppWidgetHostView createView(Context context, int appWidgetId, AppWidgetProviderInfo appWidget) { AppWidgetHostView view = onCreateView(context, appWidgetId, appWidget); + view.setOnClickHandler(mOnClickHandler); view.setAppWidget(appWidgetId, appWidget); synchronized (mViews) { mViews.put(appWidgetId, view); @@ -246,6 +257,7 @@ public class AppWidgetHost { throw new RuntimeException("system server dead?", e); } view.updateAppWidget(views); + return view; } @@ -255,7 +267,7 @@ public class AppWidgetHost { */ protected AppWidgetHostView onCreateView(Context context, int appWidgetId, AppWidgetProviderInfo appWidget) { - return new AppWidgetHostView(context); + return new AppWidgetHostView(context, mOnClickHandler); } /** @@ -265,7 +277,7 @@ public class AppWidgetHost { AppWidgetHostView v; // Convert complex to dp -- we are getting the AppWidgetProviderInfo from the - // AppWidgetService, which doesn't have our context, hence we need to do the + // AppWidgetService, which doesn't have our context, hence we need to do the // conversion here. appWidget.minWidth = TypedValue.complexToDimensionPixelSize(appWidget.minWidth, mDisplayMetrics); diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java index ed95ae587de83..603ceb7626f51 100644 --- a/core/java/android/appwidget/AppWidgetHostView.java +++ b/core/java/android/appwidget/AppWidgetHostView.java @@ -44,6 +44,7 @@ import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.FrameLayout; import android.widget.RemoteViews; +import android.widget.RemoteViews.OnClickHandler; import android.widget.RemoteViewsAdapter.RemoteAdapterConnectionCallback; import android.widget.TextView; @@ -83,7 +84,8 @@ public class AppWidgetHostView extends FrameLayout { long mFadeStartTime = -1; Bitmap mOld; Paint mOldPaint = new Paint(); - + private OnClickHandler mOnClickHandler; + /** * Create a host view. Uses default fade animations. */ @@ -91,10 +93,18 @@ public class AppWidgetHostView extends FrameLayout { this(context, android.R.anim.fade_in, android.R.anim.fade_out); } + /** + * @hide + */ + public AppWidgetHostView(Context context, OnClickHandler handler) { + this(context, android.R.anim.fade_in, android.R.anim.fade_out); + mOnClickHandler = handler; + } + /** * Create a host view. Uses specified animations when pushing * {@link #updateAppWidget(RemoteViews)}. - * + * * @param animationIn Resource ID of in animation to use * @param animationOut Resource ID of out animation to use */ @@ -108,6 +118,17 @@ public class AppWidgetHostView extends FrameLayout { setIsRootNamespace(true); } + /** + * Pass the given handler to RemoteViews when updating this widget. Unless this + * is done immediatly after construction, a call to {@link #updateAppWidget(RemoteViews)} + * should be made. + * @param handler + * @hide + */ + public void setOnClickHandler(OnClickHandler handler) { + mOnClickHandler = handler; + } + /** * Set the AppWidget that will be displayed by this view. This method also adds default padding * to widgets, as described in {@link #getDefaultPaddingForWidget(Context, ComponentName, Rect)} @@ -177,7 +198,7 @@ public class AppWidgetHostView extends FrameLayout { public int getAppWidgetId() { return mAppWidgetId; } - + public AppWidgetProviderInfo getAppWidgetInfo() { return mInfo; } @@ -281,12 +302,13 @@ public class AppWidgetHostView extends FrameLayout { * AppWidget provider. Will animate into these new views as needed */ public void updateAppWidget(RemoteViews remoteViews) { + if (LOGD) Log.d(TAG, "updateAppWidget called mOld=" + mOld); boolean recycled = false; View content = null; Exception exception = null; - + // Capture the old view into a bitmap so we can do the crossfade. if (CROSSFADE) { if (mFadeStartTime < 0) { @@ -305,7 +327,7 @@ public class AppWidgetHostView extends FrameLayout { } } } - + if (remoteViews == null) { if (mViewMode == VIEW_MODE_DEFAULT) { // We've already done this -- nothing to do. @@ -324,7 +346,7 @@ public class AppWidgetHostView extends FrameLayout { // layout matches, try recycling it if (content == null && layoutId == mLayoutId) { try { - remoteViews.reapply(mContext, mView); + remoteViews.reapply(mContext, mView, mOnClickHandler); content = mView; recycled = true; if (LOGD) Log.d(TAG, "was able to recycled existing layout"); @@ -332,11 +354,11 @@ public class AppWidgetHostView extends FrameLayout { exception = e; } } - + // Try normal RemoteView inflation if (content == null) { try { - content = remoteViews.apply(mContext, this); + content = remoteViews.apply(mContext, this, mOnClickHandler); if (LOGD) Log.d(TAG, "had to inflate new layout"); } catch (RuntimeException e) { exception = e; @@ -346,7 +368,7 @@ public class AppWidgetHostView extends FrameLayout { mLayoutId = layoutId; mViewMode = VIEW_MODE_CONTENT; } - + if (content == null) { if (mViewMode == VIEW_MODE_ERROR) { // We've already done this -- nothing to do. @@ -356,7 +378,7 @@ public class AppWidgetHostView extends FrameLayout { content = getErrorView(); mViewMode = VIEW_MODE_ERROR; } - + if (!recycled) { prepareView(content); addView(content); @@ -455,7 +477,7 @@ public class AppWidgetHostView extends FrameLayout { return super.drawChild(canvas, child, drawingTime); } } - + /** * Prepare the given view to be shown. This might include adjusting * {@link FrameLayout.LayoutParams} before inserting. @@ -471,7 +493,7 @@ public class AppWidgetHostView extends FrameLayout { requested.gravity = Gravity.CENTER; view.setLayoutParams(requested); } - + /** * Inflate and return the default layout requested by AppWidget provider. */ @@ -481,7 +503,7 @@ public class AppWidgetHostView extends FrameLayout { } View defaultView = null; Exception exception = null; - + try { if (mInfo != null) { Context theirContext = mContext.createPackageContext( @@ -500,19 +522,19 @@ public class AppWidgetHostView extends FrameLayout { } catch (RuntimeException e) { exception = e; } - + if (exception != null) { Log.w(TAG, "Error inflating AppWidget " + mInfo + ": " + exception.toString()); } - + if (defaultView == null) { if (LOGD) Log.d(TAG, "getDefaultView couldn't find any view, so inflating error"); defaultView = getErrorView(); } - + return defaultView; } - + /** * Inflate and return a view that represents an error state. */ diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index dd05a03e2d144..dcf90e9123bc7 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -61,9 +61,9 @@ import java.util.ArrayList; * the content of the inflated hierarchy. */ public class RemoteViews implements Parcelable, Filter { - + private static final String LOG_TAG = "RemoteViews"; - + /** * The intent extra that contains the appWidgetId. * @hide @@ -71,11 +71,11 @@ public class RemoteViews implements Parcelable, Filter { static final String EXTRA_REMOTEADAPTER_APPWIDGET_ID = "remoteAdapterAppWidgetId"; /** - * The package name of the package containing the layout + * The package name of the package containing the layout * resource. (Added to the parcel) */ private final String mPackage; - + /** * The resource ID of the layout file. (Added to the parcel) */ @@ -86,7 +86,7 @@ public class RemoteViews implements Parcelable, Filter { * inflated */ private ArrayList mActions; - + /** * A class to keep track of memory usage by this RemoteViews */ @@ -522,13 +522,13 @@ public class RemoteViews implements Parcelable, Filter { .getCompatibilityInfo().applicationScale; final int[] pos = new int[2]; v.getLocationOnScreen(pos); - + final Rect rect = new Rect(); rect.left = (int) (pos[0] * appScale + 0.5f); rect.top = (int) (pos[1] * appScale + 0.5f); rect.right = (int) ((pos[0] + v.getWidth()) * appScale + 0.5f); rect.bottom = (int) ((pos[1] + v.getHeight()) * appScale + 0.5f); - + final Intent intent = new Intent(); intent.setSourceBounds(rect); handler.onClickHandler(v, pendingIntent, intent); @@ -567,7 +567,7 @@ public class RemoteViews implements Parcelable, Filter { this.filterMode = mode; this.level = level; } - + public SetDrawableParameters(Parcel parcel) { viewId = parcel.readInt(); targetBackground = parcel.readInt() != 0; @@ -581,7 +581,7 @@ public class RemoteViews implements Parcelable, Filter { } level = parcel.readInt(); } - + public void writeToParcel(Parcel dest, int flags) { dest.writeInt(TAG); dest.writeInt(viewId); @@ -596,12 +596,12 @@ public class RemoteViews implements Parcelable, Filter { } dest.writeInt(level); } - + @Override public void apply(View root, ViewGroup rootParent, OnClickHandler handler) { final View target = root.findViewById(viewId); if (target == null) return; - + // Pick the correct drawable to modify for this view Drawable targetDrawable = null; if (targetBackground) { @@ -610,7 +610,7 @@ public class RemoteViews implements Parcelable, Filter { ImageView imageView = (ImageView) target; targetDrawable = imageView.getDrawable(); } - + if (targetDrawable != null) { // Perform modifications only if values are set correctly if (alpha != -1) { @@ -634,7 +634,7 @@ public class RemoteViews implements Parcelable, Filter { public final static int TAG = 3; } - + private class ReflectionActionWithoutParams extends Action { int viewId; String methodName; @@ -938,7 +938,7 @@ public class RemoteViews implements Parcelable, Filter { out.writeString((String)this.value); break; case CHAR_SEQUENCE: - TextUtils.writeToParcel((CharSequence)this.value, out, flags); + TextUtils.writeToParcel((CharSequence)this.value, out, flags); break; case URI: out.writeInt(this.value != null ? 1 : 0); @@ -1314,7 +1314,7 @@ public class RemoteViews implements Parcelable, Filter { /** * Create a new RemoteViews object that will display the views contained * in the specified layout file. - * + * * @param packageName Name of the package that contains the layout resource * @param layoutId The id of the layout resource */ @@ -1364,7 +1364,7 @@ public class RemoteViews implements Parcelable, Filter { /** * Reads a RemoteViews object from a parcel. - * + * * @param parcel */ public RemoteViews(Parcel parcel) { @@ -1547,7 +1547,7 @@ public class RemoteViews implements Parcelable, Filter { /** * Add an action to be executed on the remote side when apply is called. - * + * * @param a The action to add */ private void addAction(Action a) { @@ -1619,7 +1619,7 @@ public class RemoteViews implements Parcelable, Filter { /** * Equivalent to calling View.setVisibility - * + * * @param viewId The id of the view whose visibility should change * @param visibility The new visibility for the view */ @@ -1629,7 +1629,7 @@ public class RemoteViews implements Parcelable, Filter { /** * Equivalent to calling TextView.setText - * + * * @param viewId The id of the view whose text should change * @param text The new text for the view */ @@ -1639,7 +1639,7 @@ public class RemoteViews implements Parcelable, Filter { /** * Equivalent to calling {@link TextView#setTextSize(int, float)} - * + * * @param viewId The id of the view whose text size should change * @param units The units of size (e.g. COMPLEX_UNIT_SP) * @param size The size of the text @@ -1649,33 +1649,29 @@ public class RemoteViews implements Parcelable, Filter { } /** - * Equivalent to calling + * Equivalent to calling * {@link TextView#setCompoundDrawablesWithIntrinsicBounds(int, int, int, int)}. * * @param viewId The id of the view whose text should change * @param left The id of a drawable to place to the left of the text, or 0 * @param top The id of a drawable to place above the text, or 0 * @param right The id of a drawable to place to the right of the text, or 0 - * @param bottom The id of a drawable to place below the text, or 0 + * @param bottom The id of a drawable to place below the text, or 0 */ public void setTextViewCompoundDrawables(int viewId, int left, int top, int right, int bottom) { addAction(new TextViewDrawableAction(viewId, false, left, top, right, bottom)); } /** - * Equivalent to calling {@link + * Equivalent to calling {@link * TextView#setCompoundDrawablesRelativeWithIntrinsicBounds(int, int, int, int)}. * * @param viewId The id of the view whose text should change - * @param start The id of a drawable to place before the text (relative to the + * @param start The id of a drawable to place before the text (relative to the * layout direction), or 0 * @param top The id of a drawable to place above the text, or 0 * @param end The id of a drawable to place after the text, or 0 -<<<<<<< HEAD - * @param bottom The id of a drawable to place below the text, or 0 -======= * @param bottom The id of a drawable to place below the text, or 0 ->>>>>>> 0a43f67e */ public void setTextViewCompoundDrawablesRelative(int viewId, int start, int top, int end, int bottom) { addAction(new TextViewDrawableAction(viewId, true, start, top, end, bottom)); @@ -1683,17 +1679,17 @@ public class RemoteViews implements Parcelable, Filter { /** * Equivalent to calling ImageView.setImageResource - * + * * @param viewId The id of the view whose drawable should change * @param srcId The new resource id for the drawable */ - public void setImageViewResource(int viewId, int srcId) { + public void setImageViewResource(int viewId, int srcId) { setInt(viewId, "setImageResource", srcId); } /** * Equivalent to calling ImageView.setImageURI - * + * * @param viewId The id of the view whose drawable should change * @param uri The Uri for the image */ @@ -1703,7 +1699,7 @@ public class RemoteViews implements Parcelable, Filter { /** * Equivalent to calling ImageView.setImageBitmap - * + * * @param viewId The id of the view whose bitmap should change * @param bitmap The new Bitmap for the drawable */ @@ -1726,7 +1722,7 @@ public class RemoteViews implements Parcelable, Filter { * {@link Chronometer#setFormat Chronometer.setFormat}, * and {@link Chronometer#start Chronometer.start()} or * {@link Chronometer#stop Chronometer.stop()}. - * + * * @param viewId The id of the {@link Chronometer} to change * @param base The time at which the timer would have read 0:00. This * time should be based off of @@ -1740,21 +1736,21 @@ public class RemoteViews implements Parcelable, Filter { setString(viewId, "setFormat", format); setBoolean(viewId, "setStarted", started); } - + /** * Equivalent to calling {@link ProgressBar#setMax ProgressBar.setMax}, * {@link ProgressBar#setProgress ProgressBar.setProgress}, and * {@link ProgressBar#setIndeterminate ProgressBar.setIndeterminate} * * If indeterminate is true, then the values for max and progress are ignored. - * + * * @param viewId The id of the {@link ProgressBar} to change * @param max The 100% value for the progress bar * @param progress The current value of the progress bar. - * @param indeterminate True if the progress bar is indeterminate, + * @param indeterminate True if the progress bar is indeterminate, * false if not. */ - public void setProgressBar(int viewId, int max, int progress, + public void setProgressBar(int viewId, int max, int progress, boolean indeterminate) { setBoolean(viewId, "setIndeterminate", indeterminate); if (!indeterminate) { @@ -1762,12 +1758,12 @@ public class RemoteViews implements Parcelable, Filter { setInt(viewId, "setProgress", progress); } } - + /** * Equivalent to calling * {@link android.view.View#setOnClickListener(android.view.View.OnClickListener)} * to launch the provided {@link PendingIntent}. - * + * * When setting the on-click action of items within collections (eg. {@link ListView}, * {@link StackView} etc.), this method will not work. Instead, use {@link * RemoteViews#setPendingIntentTemplate(int, PendingIntent) in conjunction with @@ -1827,7 +1823,7 @@ public class RemoteViews implements Parcelable, Filter { * view. *

* You can omit specific calls by marking their values with null or -1. - * + * * @param viewId The id of the view that contains the target * {@link Drawable} * @param targetBackground If true, apply these parameters to the @@ -1853,7 +1849,7 @@ public class RemoteViews implements Parcelable, Filter { /** * Equivalent to calling {@link android.widget.TextView#setTextColor(int)}. - * + * * @param viewId The id of the view whose text color should change * @param color Sets the text color for all the states (normal, selected, * focused) to be this color. @@ -2105,16 +2101,16 @@ public class RemoteViews implements Parcelable, Filter { /** * Inflates the view hierarchy represented by this object and applies * all of the actions. - * + * *

Caller beware: this may throw - * + * * @param context Default context to use * @param parent Parent that the resulting view hierarchy will be attached to. This method * does not attach the hierarchy. The caller should do so when appropriate. * @return The inflated view hierarchy */ public View apply(Context context, ViewGroup parent) { - return apply(context, parent, DEFAULT_ON_CLICK_HANDLER); + return apply(context, parent, null); } /** @hide */ @@ -2142,12 +2138,12 @@ public class RemoteViews implements Parcelable, Filter { * Applies all of the actions to the provided view. * *

Caller beware: this may throw - * + * * @param v The view to apply the actions to. This should be the result of * the {@link #apply(Context,ViewGroup)} call. */ public void reapply(Context context, View v) { - reapply(context, v, DEFAULT_ON_CLICK_HANDLER); + reapply(context, v, null); } /** @hide */ @@ -2170,6 +2166,7 @@ public class RemoteViews implements Parcelable, Filter { private void performApply(View v, ViewGroup parent, OnClickHandler handler) { if (mActions != null) { + handler = handler == null ? DEFAULT_ON_CLICK_HANDLER : handler; final int count = mActions.size(); for (int i = 0; i < count; i++) { Action a = mActions.get(i); @@ -2198,7 +2195,7 @@ public class RemoteViews implements Parcelable, Filter { /* (non-Javadoc) * Used to restrict the views which can be inflated - * + * * @see android.view.LayoutInflater.Filter#onLoadClass(java.lang.Class) */ public boolean onLoadClass(Class clazz) {