diff options
author | Adam Cohen <adamcohen@google.com> | 2010-08-15 18:20:04 -0700 |
---|---|---|
committer | Adam Cohen <adamcohen@google.com> | 2010-08-17 10:29:35 -0700 |
commit | 2dd2197805edb4d9547b143deef2226413218f4c (patch) | |
tree | 9ac6869e60bc425c276bce8c309aecdb1ebb450e /core | |
parent | 0c316eeb437a0ac1d6840690be643d1a553f0b23 (diff) | |
download | frameworks_base-2dd2197805edb4d9547b143deef2226413218f4c.zip frameworks_base-2dd2197805edb4d9547b143deef2226413218f4c.tar.gz frameworks_base-2dd2197805edb4d9547b143deef2226413218f4c.tar.bz2 |
-> Enabled partial updates to app widgets through AppWidgetManager.
Partial updates are not cached by the AppWidgetService.
-> Added the ability to insert commands with no parameters into
RemoteViews objects.
-> Added showNext() and showPrevious() methods to RemoteViews.
-> Made showNext() / showPrevious() of AdapterViewFlipper remotable.
Change-Id: Ic5491bb374424a54728c4ca92b94b1f00dfb87ff
Diffstat (limited to 'core')
4 files changed, 173 insertions, 2 deletions
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java index 5ee721f..b83642b 100644 --- a/core/java/android/appwidget/AppWidgetManager.java +++ b/core/java/android/appwidget/AppWidgetManager.java @@ -233,6 +233,10 @@ public class AppWidgetManager { /** * Set the RemoteViews to use for the specified appWidgetIds. * + * Note that the RemoteViews parameter will be cached by the AppWidgetService, and hence should + * contain a complete representation of the widget. For performing partial widget updates, see + * {@link #partiallyUpdateAppWidget(int[], RemoteViews)}. + * * <p> * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast, * and outside of the handler. @@ -253,6 +257,10 @@ public class AppWidgetManager { /** * Set the RemoteViews to use for the specified appWidgetId. * + * Note that the RemoteViews parameter will be cached by the AppWidgetService, and hence should + * contain a complete representation of the widget. For performing partial widget updates, see + * {@link #partiallyUpdateAppWidget(int, RemoteViews)}. + * * <p> * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast, * and outside of the handler. @@ -266,6 +274,59 @@ public class AppWidgetManager { } /** + * Perform an incremental update or command on the widget(s) specified by appWidgetIds. + * + * This update differs from {@link #updateAppWidget(int[], RemoteViews)} in that the + * RemoteViews object which is passed is understood to be an incomplete representation of the + * widget, and hence is not cached by the AppWidgetService. Note that because these updates are + * not cached, any state that they modify that is not restored by restoreInstanceState will not + * persist in the case that the widgets are restored using the cached version in + * AppWidgetService. + * + * Use with {@link RemoteViews#showNext(int)}, {@link RemoteViews#showPrevious(int)}, + * {@link RemoteViews#setScrollPosition(int, int)} and similar commands. + * + * <p> + * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast, + * and outside of the handler. + * This method will only work when called from the uid that owns the AppWidget provider. + * + * @param appWidgetIds The AppWidget instances for which to set the RemoteViews. + * @param views The RemoteViews object containing the incremental update / command. + */ + public void partiallyUpdateAppWidget(int[] appWidgetIds, RemoteViews views) { + try { + sService.partiallyUpdateAppWidgetIds(appWidgetIds, views); + } catch (RemoteException e) { + throw new RuntimeException("system server dead?", e); + } + } + + /** + * Perform an incremental update or command on the widget specified by appWidgetId. + * + * This update differs from {@link #updateAppWidget(int, RemoteViews)} in that the RemoteViews + * object which is passed is understood to be an incomplete representation of the widget, and + * hence is not cached by the AppWidgetService. Note that because these updates are not cached, + * any state that they modify that is not restored by restoreInstanceState will not persist in + * the case that the widgets are restored using the cached version in AppWidgetService. + * + * Use with {@link RemoteViews#showNext(int)}, {@link RemoteViews#showPrevious(int)}, + * {@link RemoteViews#setScrollPosition(int, int)} and similar commands. + * + * <p> + * It is okay to call this method both inside an {@link #ACTION_APPWIDGET_UPDATE} broadcast, + * and outside of the handler. + * This method will only work when called from the uid that owns the AppWidget provider. + * + * @param appWidgetId The AppWidget instance for which to set the RemoteViews. + * @param views The RemoteViews object containing the incremental update / command. + */ + public void partiallyUpdateAppWidget(int appWidgetId, RemoteViews views) { + partiallyUpdateAppWidget(new int[] { appWidgetId }, views); + } + + /** * Set the RemoteViews to use for all AppWidget instances for the supplied AppWidget provider. * * <p> diff --git a/core/java/android/widget/AdapterViewFlipper.java b/core/java/android/widget/AdapterViewFlipper.java index 901c761..205c0ba 100644 --- a/core/java/android/widget/AdapterViewFlipper.java +++ b/core/java/android/widget/AdapterViewFlipper.java @@ -25,6 +25,7 @@ import android.os.Handler; import android.os.Message; import android.util.AttributeSet; import android.util.Log; +import android.view.RemotableViewMethod; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.widget.RemoteViews.RemoteView; @@ -137,6 +138,38 @@ public class AdapterViewFlipper extends AdapterViewAnimator { } /** + * {@inheritDoc} + */ + @Override + @RemotableViewMethod + public void showNext() { + // if the flipper is currently flipping automatically, and showNext() is called + // we should we should make sure to reset the timer + if (mRunning) { + mHandler.removeMessages(FLIP_MSG); + Message msg = mHandler.obtainMessage(FLIP_MSG); + mHandler.sendMessageDelayed(msg, mFlipInterval); + } + super.showNext(); + } + + /** + * {@inheritDoc} + */ + @Override + @RemotableViewMethod + public void showPrevious() { + // if the flipper is currently flipping automatically, and showPrevious() is called + // we should we should make sure to reset the timer + if (mRunning) { + mHandler.removeMessages(FLIP_MSG); + Message msg = mHandler.obtainMessage(FLIP_MSG); + mHandler.sendMessageDelayed(msg, mFlipInterval); + } + super.showPrevious(); + } + + /** * How long to wait before flipping to the next view * * @param milliseconds @@ -229,8 +262,6 @@ public class AdapterViewFlipper extends AdapterViewAnimator { if (msg.what == FLIP_MSG) { if (mRunning) { showNext(); - msg = obtainMessage(FLIP_MSG); - sendMessageDelayed(msg, mFlipInterval); } } } diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java index 50745dc0..f23a723 100644 --- a/core/java/android/widget/RemoteViews.java +++ b/core/java/android/widget/RemoteViews.java @@ -266,6 +266,63 @@ public class RemoteViews implements Parcelable, Filter { public final static int TAG = 3; } + private class ReflectionActionWithoutParams extends Action { + int viewId; + String methodName; + + public final static int TAG = 5; + + ReflectionActionWithoutParams(int viewId, String methodName) { + this.viewId = viewId; + this.methodName = methodName; + } + + ReflectionActionWithoutParams(Parcel in) { + this.viewId = in.readInt(); + this.methodName = in.readString(); + } + + public void writeToParcel(Parcel out, int flags) { + out.writeInt(TAG); + out.writeInt(this.viewId); + out.writeString(this.methodName); + } + + @Override + public void apply(View root) { + final View view = root.findViewById(viewId); + if (view == null) { + throw new ActionException("can't find view: 0x" + Integer.toHexString(viewId)); + } + + Class klass = view.getClass(); + Method method; + try { + method = klass.getMethod(this.methodName); + } catch (NoSuchMethodException ex) { + throw new ActionException("view: " + klass.getName() + " doesn't have method: " + + this.methodName + "()"); + } + + if (!method.isAnnotationPresent(RemotableViewMethod.class)) { + throw new ActionException("view: " + klass.getName() + + " can't use method with RemoteViews: " + + this.methodName + "()"); + } + + try { + //noinspection ConstantIfStatement + if (false) { + Log.d("RemoteViews", "view: " + klass.getName() + " calling method: " + + this.methodName + "()"); + } + method.invoke(view); + } catch (Exception ex) { + throw new ActionException(ex); + } + } + } + /** * Base class for the reflection actions. */ @@ -571,6 +628,9 @@ public class RemoteViews implements Parcelable, Filter { case ViewGroupAction.TAG: mActions.add(new ViewGroupAction(parcel)); break; + case ReflectionActionWithoutParams.TAG: + mActions.add(new ReflectionActionWithoutParams(parcel)); + break; default: throw new ActionException("Tag " + tag + " not found"); } @@ -632,6 +692,24 @@ public class RemoteViews implements Parcelable, Filter { } /** + * Equivalent to calling {@link AdapterViewFlipper#showNext()} + * + * @param viewId The id of the view on which to call {@link AdapterViewFlipper#showNext()} + */ + public void showNext(int viewId) { + addAction(new ReflectionActionWithoutParams(viewId, "showNext")); + } + + /** + * Equivalent to calling {@link AdapterViewFlipper#showPrevious()} + * + * @param viewId The id of the view on which to call {@link AdapterViewFlipper#showPrevious()} + */ + public void showPrevious(int viewId) { + addAction(new ReflectionActionWithoutParams(viewId, "showPrevious")); + } + + /** * Equivalent to calling View.setVisibility * * @param viewId The id of the view whose visibility should change diff --git a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl index af75d5b..8da51b1 100644 --- a/core/java/com/android/internal/appwidget/IAppWidgetService.aidl +++ b/core/java/com/android/internal/appwidget/IAppWidgetService.aidl @@ -40,6 +40,7 @@ interface IAppWidgetService { // for AppWidgetManager // void updateAppWidgetIds(in int[] appWidgetIds, in RemoteViews views); + void partiallyUpdateAppWidgetIds(in int[] appWidgetIds, in RemoteViews views); void updateAppWidgetProvider(in ComponentName provider, in RemoteViews views); void notifyAppWidgetViewDataChanged(in int[] appWidgetIds, in RemoteViews views, int viewId); List<AppWidgetProviderInfo> getInstalledProviders(); |