Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android support v7 MediaRouter sometimes doesn't work properly

I use v7 support library MediaRouter for switching routes between phone's speaker and bluetooth device.

And sometimes it works strange, for example, when I turn off the bluetooth, corresponding route seems to be removed (playback switches to the speaker), but my application doesn't receive any callback about it. And moreover, when I manually get all the routes via MediaRouter.getRoutes(), it returns that bluetooth route, but when I try to switch to it, it seems to be selected, but actually playback still goes through the speaker.

I tried all the flags CALLBACK_FLAG_FORCE_DISCOVERY, CALLBACK_FLAG_REQUEST_DISCOVERY etc, without result. Only phone reboot helps. Any suggestions?

I used Android 4.2, 4.4.

UPDATE, code sample: ....

private MediaRouter mMediaRouter;

    private MediaRouter.Callback mMediaRouterCallback = new MediaRouter.Callback(){
        @Override
        public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo route) {
            super.onRouteAdded(router, route);
            refreshRoutes();
            Log.i(TAG, "Route added ==> " + route.getName());
        }

        @Override
        public void onRouteRemoved(MediaRouter router, MediaRouter.RouteInfo route) {
            super.onRouteRemoved(router, route);
            refreshRoutes();
            Log.i(TAG, "Route removed ==> " + route.getName());
        }

        @Override
        public void onRouteSelected(MediaRouter router, MediaRouter.RouteInfo route) {
            super.onRouteSelected(router, route);
            Log.i(TAG, "Route selected ==> " + route.getName());
            refreshRoutes();
        }

        @Override
        public void onRouteUnselected(MediaRouter router, MediaRouter.RouteInfo route) {
            super.onRouteUnselected(router, route);
            Log.i(TAG, "Route UNselected ==> " + route.getName());
            refreshRoutes();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mRoutesList = (ListView) findViewById(R.id.routesList);

        mRoutesList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                String routeName = mRoutesAdapter.getItem(i);

                List<MediaRouter.RouteInfo> routes = mMediaRouter.getRoutes();
                for (MediaRouter.RouteInfo rout : routes){
                    if (rout.getName().equals(routeName)){
                        mMediaRouter.selectRoute(rout);
                    }
                }
            }
        });

        mMediaRouter = MediaRouter.getInstance(this);
        mMediaRouter.addCallback(
                new MediaRouteSelector.Builder()
                        .addControlCategory(MediaControlIntent.CATEGORY_LIVE_AUDIO)
                        .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK)
                        .build(),
                mMediaRouterCallback,
                MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);

        mRoutesAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, 0);
        mRoutesList.setAdapter(mRoutesAdapter);

        refreshUi();
    }

@Override
    protected void onDestroy() {
        mMediaRouter.removeCallback(mMediaRouterCallback);
        super.onDestroy();
    }

private void refreshRoutes(){
        mRoutesAdapter.clear();
        MediaRouter.RouteInfo selectedRoute = mMediaRouter.getSelectedRoute();
        List<MediaRouter.RouteInfo> routes = mMediaRouter.getRoutes();
        for (MediaRouter.RouteInfo rout : routes){
            if (rout == selectedRoute)
                mRoutesAdapter.add(rout.getName() + " [selected]");
            else
                mRoutesAdapter.add(rout.getName());
        }
        mRoutesAdapter.notifyDataSetChanged();
    }
like image 681
Denisigo Avatar asked Jan 30 '15 14:01

Denisigo


1 Answers

Using @Xaver's suggestion in the question comments, I put all of the MediaRouting in a Service. I got everything working how it was before the service but the same error was occurring. When I returned to an activity, after one switch from the wired to the BlueTooth speaker, the MediaRouter would get stuck on the wired speaker despite saying that the current route was the Bluetooth speaker.

Switching from android.support.v7.media.MediaRouter to the android.media.MediaRouter and refactoring my code a little everything worked perfectly. Hard to say if moving the routing to a service was part of the combination but I got it working (after ~50 hours of tinkering with everything)

The unfortunate thing with android.media.MediaRouter is it doesn't have a getRoutes method, but nothing a little Googleing couldn't handle! Since I found it a pain to figure this out from the docs, since everything is referencing the v7 library, below is how to get the MediaRouter and select a route.

MediaRouter mr = (MediaRouter)this.getSystemService(this.MEDIA_ROUTER_SERVICE);
mr.selectRoute(mr.ROUTE_TYPE_LIVE_AUDIO, mr.getRouteAt(0));

Hopefully this helps someone!

like image 100
locrizak Avatar answered Oct 10 '22 12:10

locrizak