summaryrefslogtreecommitdiff
path: root/core/java/android/app/MediaRouteButton.java
diff options
context:
space:
mode:
authorAdam Powell <adamp@google.com>2012-06-04 19:22:45 -0700
committerAdam Powell <adamp@google.com>2012-06-05 19:15:57 -0700
commit690ffb4e1f735148a15f2036d9a3c1962fba188c (patch)
treeaa5179aa9beedd2ef71dc1d97c9353b16a1de043 /core/java/android/app/MediaRouteButton.java
parent3676b137ecf2f24e88e8a3567c11234e7d4416d2 (diff)
More fun with MediaRouter
Add action provider, button, and styles. Extend ActionProvider to allow for getting references to MenuItem instances. Implement toggle mode for the MediaRouteButton/ActionProvider. Dialog selection yet to come. Change-Id: Ibe3188570f503bbf8dd00cf154663435656a7171
Diffstat (limited to 'core/java/android/app/MediaRouteButton.java')
-rw-r--r--core/java/android/app/MediaRouteButton.java284
1 files changed, 284 insertions, 0 deletions
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java
new file mode 100644
index 000000000000..3aabd5d0d561
--- /dev/null
+++ b/core/java/android/app/MediaRouteButton.java
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import com.android.internal.R;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.media.MediaRouter;
+import android.media.MediaRouter.RouteInfo;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.SoundEffectConstants;
+import android.view.View;
+
+public class MediaRouteButton extends View {
+ private static final String TAG = "MediaRouteButton";
+
+ private MediaRouter mRouter;
+ private final MediaRouteCallback mRouterCallback = new MediaRouteCallback();
+ private int mRouteTypes;
+
+ private Drawable mRemoteIndicator;
+ private boolean mRemoteActive;
+ private boolean mToggleMode;
+
+ private int mMinWidth;
+ private int mMinHeight;
+
+ private static final int[] ACTIVATED_STATE_SET = {
+ R.attr.state_activated
+ };
+
+ public MediaRouteButton(Context context) {
+ this(context, null);
+ }
+
+ public MediaRouteButton(Context context, AttributeSet attrs) {
+ this(context, null, com.android.internal.R.attr.mediaRouteButtonStyle);
+ }
+
+ public MediaRouteButton(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ mRouter = MediaRouter.forApplication(context);
+
+ TypedArray a = context.obtainStyledAttributes(attrs,
+ com.android.internal.R.styleable.MediaRouteButton, defStyleAttr, 0);
+ setRemoteIndicatorDrawable(a.getDrawable(
+ com.android.internal.R.styleable.MediaRouteButton_externalRouteEnabledDrawable));
+ mMinWidth = a.getDimensionPixelSize(
+ com.android.internal.R.styleable.MediaRouteButton_minWidth, 0);
+ mMinHeight = a.getDimensionPixelSize(
+ com.android.internal.R.styleable.MediaRouteButton_minHeight, 0);
+ a.recycle();
+
+ setClickable(true);
+ }
+
+ private void setRemoteIndicatorDrawable(Drawable d) {
+ if (mRemoteIndicator != null) {
+ mRemoteIndicator.setCallback(null);
+ unscheduleDrawable(mRemoteIndicator);
+ }
+ mRemoteIndicator = d;
+ if (d != null) {
+ d.setCallback(this);
+ d.setState(getDrawableState());
+ d.setVisible(getVisibility() == VISIBLE, false);
+ }
+
+ refreshDrawableState();
+ }
+
+ @Override
+ public boolean performClick() {
+ // Send the appropriate accessibility events and call listeners
+ boolean handled = super.performClick();
+ if (!handled) {
+ playSoundEffect(SoundEffectConstants.CLICK);
+ }
+
+ if (mToggleMode) {
+ if (mRemoteActive) {
+ mRouter.selectRoute(mRouteTypes, mRouter.getSystemAudioRoute());
+ } else {
+ final int N = mRouter.getRouteCount();
+ for (int i = 0; i < N; i++) {
+ final RouteInfo route = mRouter.getRouteAt(i);
+ if ((route.getSupportedTypes() & mRouteTypes) != 0 &&
+ route != mRouter.getSystemAudioRoute()) {
+ mRouter.selectRoute(mRouteTypes, route);
+ }
+ }
+ }
+ } else {
+ Log.d(TAG, "TODO: Implement the dialog!");
+ }
+
+ return handled;
+ }
+
+ public void setRouteTypes(int types) {
+ if (types == mRouteTypes) {
+ // Already registered; nothing to do.
+ return;
+ }
+ if (mRouteTypes != 0) {
+ mRouter.removeCallback(mRouterCallback);
+ }
+ mRouteTypes = types;
+ updateRemoteIndicator();
+ updateRouteCount();
+ mRouter.addCallback(types, mRouterCallback);
+ }
+
+ public int getRouteTypes() {
+ return mRouteTypes;
+ }
+
+ void updateRemoteIndicator() {
+ final boolean isRemote =
+ mRouter.getSelectedRoute(mRouteTypes) != mRouter.getSystemAudioRoute();
+ if (mRemoteActive != isRemote) {
+ mRemoteActive = isRemote;
+ refreshDrawableState();
+ }
+ }
+
+ void updateRouteCount() {
+ final int N = mRouter.getRouteCount();
+ int count = 0;
+ for (int i = 0; i < N; i++) {
+ if ((mRouter.getRouteAt(i).getSupportedTypes() & mRouteTypes) != 0) {
+ count++;
+ }
+ }
+
+ setEnabled(count != 0);
+
+ // Only allow toggling if we have more than just user routes
+ mToggleMode = count == 2 && (mRouteTypes & MediaRouter.ROUTE_TYPE_LIVE_AUDIO) != 0;
+ }
+
+ @Override
+ protected int[] onCreateDrawableState(int extraSpace) {
+ final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
+ if (mRemoteActive) {
+ mergeDrawableStates(drawableState, ACTIVATED_STATE_SET);
+ }
+ return drawableState;
+ }
+
+ @Override
+ protected void drawableStateChanged() {
+ super.drawableStateChanged();
+
+ if (mRemoteIndicator != null) {
+ int[] myDrawableState = getDrawableState();
+ mRemoteIndicator.setState(myDrawableState);
+ invalidate();
+ }
+ }
+
+ @Override
+ protected boolean verifyDrawable(Drawable who) {
+ return super.verifyDrawable(who) || who == mRemoteIndicator;
+ }
+
+ @Override
+ public void jumpDrawablesToCurrentState() {
+ super.jumpDrawablesToCurrentState();
+ if (mRemoteIndicator != null) mRemoteIndicator.jumpToCurrentState();
+ }
+
+ @Override
+ public void setVisibility(int visibility) {
+ super.setVisibility(visibility);
+ if (mRemoteIndicator != null) {
+ mRemoteIndicator.setVisible(getVisibility() == VISIBLE, false);
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+ final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
+ final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
+ final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
+
+ final int minWidth = Math.max(mMinWidth,
+ mRemoteIndicator != null ? mRemoteIndicator.getIntrinsicWidth() : 0);
+ final int minHeight = Math.max(mMinHeight,
+ mRemoteIndicator != null ? mRemoteIndicator.getIntrinsicHeight() : 0);
+
+ int width;
+ switch (widthMode) {
+ case MeasureSpec.EXACTLY:
+ width = widthSize;
+ break;
+ case MeasureSpec.AT_MOST:
+ width = Math.min(widthSize, minWidth + getPaddingLeft() + getPaddingRight());
+ break;
+ default:
+ case MeasureSpec.UNSPECIFIED:
+ width = minWidth + getPaddingLeft() + getPaddingRight();
+ break;
+ }
+
+ int height;
+ switch (heightMode) {
+ case MeasureSpec.EXACTLY:
+ height = heightSize;
+ break;
+ case MeasureSpec.AT_MOST:
+ height = Math.min(heightSize, minHeight + getPaddingTop() + getPaddingBottom());
+ break;
+ default:
+ case MeasureSpec.UNSPECIFIED:
+ height = minHeight + getPaddingTop() + getPaddingBottom();
+ break;
+ }
+
+ setMeasuredDimension(width, height);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if (mRemoteIndicator == null) return;
+
+ final int left = getPaddingLeft();
+ final int right = getWidth() - getPaddingRight();
+ final int top = getPaddingTop();
+ final int bottom = getHeight() - getPaddingBottom();
+
+ final int drawWidth = mRemoteIndicator.getIntrinsicWidth();
+ final int drawHeight = mRemoteIndicator.getIntrinsicHeight();
+ final int drawLeft = left + (right - left - drawWidth) / 2;
+ final int drawTop = top + (bottom - top - drawHeight) / 2;
+
+ mRemoteIndicator.setBounds(drawLeft, drawTop, drawLeft + drawWidth, drawTop + drawHeight);
+ mRemoteIndicator.draw(canvas);
+ }
+
+ private class MediaRouteCallback extends MediaRouter.SimpleCallback {
+ @Override
+ public void onRouteSelected(int type, RouteInfo info) {
+ updateRemoteIndicator();
+ }
+
+ @Override
+ public void onRouteUnselected(int type, RouteInfo info) {
+ updateRemoteIndicator();
+ }
+
+ @Override
+ public void onRouteAdded(int type, RouteInfo info) {
+ updateRouteCount();
+ }
+
+ @Override
+ public void onRouteRemoved(int type, RouteInfo info) {
+ updateRouteCount();
+ }
+ }
+}