Merge "Update AppWidgetHost with better support for OnClickHandlers" into jb-mr1-dev

This commit is contained in:
Jim Miller
2012-08-21 13:19:31 -07:00
committed by Android (Google) Code Review
3 changed files with 101 additions and 70 deletions

View File

@@ -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<Integer,AppWidgetHostView> mViews = new HashMap<Integer, AppWidgetHostView>();
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<RemoteViews> updatedViews = new ArrayList<RemoteViews>();
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);

View File

@@ -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.
*/

View File

@@ -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<Action> 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.
* <p>
* 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.
*
*
* <p><strong>Caller beware: this may throw</strong>
*
*
* @param context Default context to use
* @param parent Parent that the resulting view hierarchy will be attached to. This method
* does <strong>not</strong> 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.
*
* <p><strong>Caller beware: this may throw</strong>
*
*
* @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) {