185 lines
6.4 KiB
Java
185 lines
6.4 KiB
Java
![]() |
/*
|
||
|
* 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 android.content.Context;
|
||
|
import android.media.MediaRouter;
|
||
|
import android.media.MediaRouter.RouteInfo;
|
||
|
import android.util.Log;
|
||
|
import android.view.ActionProvider;
|
||
|
import android.view.MenuItem;
|
||
|
import android.view.View;
|
||
|
import android.view.ViewGroup;
|
||
|
|
||
|
import java.lang.ref.WeakReference;
|
||
|
|
||
|
/**
|
||
|
* The media route action provider displays a {@link MediaRouteButton media route button}
|
||
|
* in the application's {@link ActionBar} to allow the user to select routes and
|
||
|
* to control the currently selected route.
|
||
|
* <p>
|
||
|
* The application must specify the kinds of routes that the user should be allowed
|
||
|
* to select by specifying the route types with the {@link #setRouteTypes} method.
|
||
|
* </p><p>
|
||
|
* Refer to {@link MediaRouteButton} for a description of the button that will
|
||
|
* appear in the action bar menu. Note that instead of disabling the button
|
||
|
* when no routes are available, the action provider will instead make the
|
||
|
* menu item invisible. In this way, the button will only be visible when it
|
||
|
* is possible for the user to discover and select a matching route.
|
||
|
* </p>
|
||
|
*/
|
||
|
public class MediaRouteActionProvider extends ActionProvider {
|
||
|
private static final String TAG = "MediaRouteActionProvider";
|
||
|
|
||
|
private final Context mContext;
|
||
|
private final MediaRouter mRouter;
|
||
|
private final MediaRouterCallback mCallback;
|
||
|
|
||
|
private int mRouteTypes;
|
||
|
private MediaRouteButton mButton;
|
||
|
private View.OnClickListener mExtendedSettingsListener;
|
||
|
|
||
|
public MediaRouteActionProvider(Context context) {
|
||
|
super(context);
|
||
|
|
||
|
mContext = context;
|
||
|
mRouter = (MediaRouter) context.getSystemService(Context.MEDIA_ROUTER_SERVICE);
|
||
|
mCallback = new MediaRouterCallback(this);
|
||
|
|
||
|
// Start with live audio by default.
|
||
|
// TODO Update this when new route types are added; segment by API level
|
||
|
// when different route types were added.
|
||
|
setRouteTypes(MediaRouter.ROUTE_TYPE_LIVE_AUDIO);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the types of routes that will be shown in the media route chooser dialog
|
||
|
* launched by this button.
|
||
|
*
|
||
|
* @param types The route types to match.
|
||
|
*/
|
||
|
public void setRouteTypes(int types) {
|
||
|
if (mRouteTypes != types) {
|
||
|
// FIXME: We currently have no way of knowing whether the action provider
|
||
|
// is still needed by the UI. Unfortunately this means the action provider
|
||
|
// may leak callbacks until garbage collection occurs. This may result in
|
||
|
// media route providers doing more work than necessary in the short term
|
||
|
// while trying to discover routes that are no longer of interest to the
|
||
|
// application. To solve this problem, the action provider will need some
|
||
|
// indication from the framework that it is being destroyed.
|
||
|
if (mRouteTypes != 0) {
|
||
|
mRouter.removeCallback(mCallback);
|
||
|
}
|
||
|
mRouteTypes = types;
|
||
|
if (types != 0) {
|
||
|
mRouter.addCallback(types, mCallback,
|
||
|
MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);
|
||
|
}
|
||
|
refreshRoute();
|
||
|
|
||
|
if (mButton != null) {
|
||
|
mButton.setRouteTypes(mRouteTypes);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public void setExtendedSettingsClickListener(View.OnClickListener listener) {
|
||
|
mExtendedSettingsListener = listener;
|
||
|
if (mButton != null) {
|
||
|
mButton.setExtendedSettingsClickListener(listener);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
@SuppressWarnings("deprecation")
|
||
|
public View onCreateActionView() {
|
||
|
throw new UnsupportedOperationException("Use onCreateActionView(MenuItem) instead.");
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public View onCreateActionView(MenuItem item) {
|
||
|
if (mButton != null) {
|
||
|
Log.e(TAG, "onCreateActionView: this ActionProvider is already associated " +
|
||
|
"with a menu item. Don't reuse MediaRouteActionProvider instances! " +
|
||
|
"Abandoning the old one...");
|
||
|
}
|
||
|
|
||
|
mButton = new MediaRouteButton(mContext);
|
||
|
mButton.setRouteTypes(mRouteTypes);
|
||
|
mButton.setExtendedSettingsClickListener(mExtendedSettingsListener);
|
||
|
mButton.setLayoutParams(new ViewGroup.LayoutParams(
|
||
|
ViewGroup.LayoutParams.WRAP_CONTENT,
|
||
|
ViewGroup.LayoutParams.MATCH_PARENT));
|
||
|
return mButton;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean onPerformDefaultAction() {
|
||
|
if (mButton != null) {
|
||
|
return mButton.showDialogInternal();
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean overridesItemVisibility() {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean isVisible() {
|
||
|
return mRouter.isRouteAvailable(mRouteTypes,
|
||
|
MediaRouter.AVAILABILITY_FLAG_IGNORE_DEFAULT_ROUTE);
|
||
|
}
|
||
|
|
||
|
private void refreshRoute() {
|
||
|
refreshVisibility();
|
||
|
}
|
||
|
|
||
|
private static class MediaRouterCallback extends MediaRouter.SimpleCallback {
|
||
|
private final WeakReference<MediaRouteActionProvider> mProviderWeak;
|
||
|
|
||
|
public MediaRouterCallback(MediaRouteActionProvider provider) {
|
||
|
mProviderWeak = new WeakReference<MediaRouteActionProvider>(provider);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void onRouteAdded(MediaRouter router, RouteInfo info) {
|
||
|
refreshRoute(router);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void onRouteRemoved(MediaRouter router, RouteInfo info) {
|
||
|
refreshRoute(router);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void onRouteChanged(MediaRouter router, RouteInfo info) {
|
||
|
refreshRoute(router);
|
||
|
}
|
||
|
|
||
|
private void refreshRoute(MediaRouter router) {
|
||
|
MediaRouteActionProvider provider = mProviderWeak.get();
|
||
|
if (provider != null) {
|
||
|
provider.refreshRoute();
|
||
|
} else {
|
||
|
router.removeCallback(this);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|