mmeitine / google-cast-sdk

Automatically exported from code.google.com/p/google-cast-sdk
1 stars 0 forks source link

Chromecast discovery failing for some users #642

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1.
2.
3.

What is the expected output? What do you see instead?

What version of the product are you using? On what operating system?

Please provide any additional information below.

Original issue reported on code.google.com by casol...@gmail.com on 3 Sep 2015 at 7:05

GoogleCodeExporter commented 9 years ago
Sorry I hit enter by mistake before typing anything. 

I'm switching my app away from the CastCompanionLibrary and a few of my users 
are having trouble with Chromecast discovery. I stripped out all of the 
unnecessary code and made an app just to see what was going on during discovery 
and sent it to one of those users and the code is never getting any of the 
callbacks from the media router. At the exact same time they can run my old app 
with the CastCompanionLibrary and it will find the Chromecast just fine. 

Here is the code I sent the user:

    public class MainActivity extends AppCompatActivity {

        private static SimpleDateFormat TIME_ONLY = new SimpleDateFormat("HH:mm:ss.SSS");
        protected MediaRouter.Callback mMediaRouterCallback;
        boolean isRunning = false;
        private TextView logView;
        private MediaRouter mMediaRouter;
        private MediaRouteSelector mMediaRouteSelector;
        private Timer removeRoutesTimer;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            mMediaRouter = createMediaRouter(getApplicationContext());
            mMediaRouterCallback = new MediaRouterCallback();
            logView = (TextView) findViewById(R.id.log);
            Button sendLog = (Button)findViewById(R.id.send_log);
            sendLog.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Intent send = new Intent(Intent.ACTION_SENDTO);
                    String uriText = "mailto:" + Uri.encode("myemailaddress") +
                            "?subject=" + Uri.encode("Logs") +
                            "&body=" + Uri.encode(logView.getText().toString());
                    Uri uri = Uri.parse(uriText);

                    send.setData(uri);
                    startActivity(Intent.createChooser(send, "Send logs..."));
                }
            });
            restart();
        }

        protected MediaRouter createMediaRouter(Context context) {
            return MediaRouter.getInstance(context);
        }

        public void start() {
            log("start");
            if (isRunning) {
                log("start - is running");
                return;
            }
            isRunning = true;

            if (mMediaRouteSelector == null) {
                log("start - route selector null");
                try {
                    mMediaRouteSelector = new MediaRouteSelector.Builder()
                            .addControlCategory(CastMediaControlIntent.categoryForCast(
                                    CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID))
                            .build();
                    log("start - route selector built");
                } catch (IllegalArgumentException e) {
                    log("start - route selector null exception " + e);

                    return;
                }
            } else {
                log("start - route selector not null");
            }

            rescan();
        }

        private void log(String start) {
            Calendar cal = new GregorianCalendar();
            String currentLog = logView.getText().toString();
            logView.setText(currentLog + "\n" + TIME_ONLY.format(cal.getTime()) + " - " + start);

        }

        public void stop() {
            log("stop");
            isRunning = false;

            if (removeRoutesTimer != null) {
                log("stop - removeRoutesTimer not null");
                removeRoutesTimer.cancel();
                removeRoutesTimer = null;
            } else {
                log("stop - removeRoutesTimer null");
            }

            if (mMediaRouter != null) {
                log("stop - mMediaRouter not null");

                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                        log("stop - mMediaRouter inside ui thread");

                        mMediaRouter.removeCallback(mMediaRouterCallback);
                    }
                });
            } else {
                log("stop - mMediaRouter  null");

            }
        }

        public void restart() {
            log("restart");

            stop();
            log("restart  - stop called");
            start();
            log("restart  - start called");
        }

        public void rescan() {
            log("rescan");
            mMediaRouter.addCallback(mMediaRouteSelector, mMediaRouterCallback,
                    MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);

        }

        private class MediaRouterCallback extends MediaRouter.Callback {

            @Override
            public void onRouteAdded(MediaRouter router, MediaRouter.RouteInfo route) {
                log("onRouteAdded - " + route.getName());

                super.onRouteAdded(router, route);

            }

            @Override
            public void onRouteChanged(MediaRouter router, MediaRouter.RouteInfo route) {
                log("onRouteChanged - " + route.getName());

                super.onRouteChanged(router, route);

            }

            @Override
            public void onRoutePresentationDisplayChanged(MediaRouter router,
                                                          MediaRouter.RouteInfo route) {

                log("onRoutePresentationDisplayChanged -  [" + route.getName() + "] ["
                        + route.getDescription() + "]");

                super.onRoutePresentationDisplayChanged(router, route);
            }

            @Override
            public void onRouteRemoved(final MediaRouter router, final MediaRouter.RouteInfo route) {
                log("onRouteRemoved - " + route.getName());

                super.onRouteRemoved(router, route);

            }

            @Override
            public void onRouteVolumeChanged(MediaRouter router, final MediaRouter.RouteInfo route) {

                super.onRouteVolumeChanged(router, route);
            }

            private void removeServices(final MediaRouter.RouteInfo route) {
                log("removeServices - " + route.getName());

            }
        }
    }

Here is the log he sent me:

    17:50:24.194 - restart
    17:50:24.194 - stop
    17:50:24.195 - stop - removeRoutesTimer null
    17:50:24.195 - stop - mMediaRouter not null
    17:50:24.195 - stop - mMediaRouter inside ui thread
    17:50:24.195 - restart  - stop called
    17:50:24.196 - start
    17:50:24.196 - start - route selector null
    17:50:24.197 - start - route selector built
    17:50:24.197 - rescan
    17:50:24.198 - restart  - start called

So basically no calls to the callback methods. 

Here is a log from my network where it works just fine (exact same apk):

    15:59:27.307 - restart
    15:59:27.307 - stop
    15:59:27.308 - stop - removeRoutesTimer null
    15:59:27.308 - stop - mMediaRouter not null
    15:59:27.308 - stop - mMediaRouter inside ui thread
    15:59:27.309 - restart  - stop called
    15:59:27.309 - start
    15:59:27.309 - start - route selector null
    15:59:27.311 - start - route selector built
    15:59:27.311 - rescan
    15:59:27.312 - restart  - start called
    15:59:28.457 - onRouteAdded - Master bedroom
    15:59:28.482 - onRouteChanged - Master bedroom
    15:59:28.484 - onRouteAdded - Living room chromecast
    15:59:28.528 - onRouteChanged - Master bedroom
    15:59:28.542 - onRouteChanged - Living room chromecast
    15:59:28.542 - onRouteAdded - Basement east bedroom
    15:59:28.639 - onRouteChanged - Master bedroom
    15:59:28.640 - onRouteChanged - Living room chromecast
    15:59:28.641 - onRouteAdded - Gym
    15:59:28.641 - onRouteChanged - Basement east bedroom
    16:01:42.117 - onRouteChanged - Living room chromecast
    16:01:42.122 - onRouteChanged - Gym
    16:01:42.124 - onRouteChanged - Basement east bedroom
    16:01:50.663 - onRouteChanged - Master bedroom
    16:01:50.664 - onRouteChanged - Living room chromecast
    16:01:50.664 - onRouteChanged - Gym
    16:01:50.664 - onRouteChanged - Basement east bedroom

So what is wrong with my discovery code?

Thanks. 

Original comment by casol...@gmail.com on 3 Sep 2015 at 7:06

GoogleCodeExporter commented 9 years ago
Please be advised that Cast Companion Library is strongly recommended. If you 
have a special use-case, do share. 

Original comment by na...@google.com on 5 Sep 2015 at 12:01

GoogleCodeExporter commented 9 years ago
I totally understand that but I have moved to ConnectSDK 
(http://connectsdk.com/). The example I posted above is the ConnectSDK 
discovery code stripped off code that only makes sense on their SDK. 

Like I said it works perfectly fine on my network but I have two users for whom 
it never finds the Chromecast. I've had them run apps (including my own but an 
older version) which use the CastCompanionLibrary and they find the Chromecast 
just fine. 

The code is ridiculously simple so I'm really curious as to where the bug is. 
There are a couple of runOnUIThread calls in that code that I'm not sure if 
they are needed but I've had the users test without those and they still have 
the same issue. 

Thanks. 

Original comment by car...@instantbits.com on 5 Sep 2015 at 12:20

GoogleCodeExporter commented 9 years ago
I have been sending tests to a user and changing the add callback flag to 
MediaRouter.CALLBACK_FLAG_FORCE_DISCOVERY fixes the issue but according to the 
documentation that isn't the recommended flag. 

Original comment by casol...@gmail.com on 7 Sep 2015 at 12:50

GoogleCodeExporter commented 9 years ago
Unfortunately, we can not help with third party libraries. Your implementation 
should be closely inline with the code-base from Cast Companion Library which 
is available on GitHub. Please refer to the same. 

Original comment by na...@google.com on 10 Sep 2015 at 9:06

GoogleCodeExporter commented 9 years ago
Thank you for the reply but I'm not asking you to troubleshoot a third party 
library, the example I posted above is self contained. If you look at the code 
it is ridiculously simple, there are just a few lines dealing with discovery:

mMediaRouter = MediaRouter.getInstance(context)
mMediaRouterCallback = new MediaRouterCallback();
mMediaRouteSelector = new MediaRouteSelector.Builder()
                            .addControlCategory(CastMediaControlIntent.categoryForCast(
                                    CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID))
                            .build();
mMediaRouter.addCallback(mMediaRouteSelector, mMediaRouterCallback,
                    MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);

That is basically it.

So where is the bug with the code? I've read the CastCompanionLibrary code 
several times and can't see any difference on this little bit of code. 

Original comment by casol...@gmail.com on 10 Sep 2015 at 9:43

GoogleCodeExporter commented 9 years ago
Are these low-RAM devices? Please note that the documentation 
(https://developer.android.com/reference/android/support/v7/media/MediaRouter.ht
ml#CALLBACK_FLAG_REQUEST_DISCOVERY) clearly mentions the flag 
CALLBACK_FLAG_REQUEST_DISCOVERY is not supported on low-RAM devices 
(https://developer.android.com/reference/android/app/ActivityManager.html#isLowR
amDevice()). If the CALLBACK_FLAG_FORCE_DISCOVERY works on those devices, most 
likely they are low-RAM devices. 

If that's not the case, please respond back with the device configurations for 
the devices these issue can be seen on and we'd gladly look into it.  

Original comment by na...@google.com on 16 Sep 2015 at 8:21

GoogleCodeExporter commented 9 years ago
I've put the question to multiple users as to what kind of device they have but 
only one has responded. She said she had one phone until last weekend and now 
has a new one.

Old phone was a Samsung galaxy prevail Ram: 384mb
And now has a Moto E Ram: 1gb

On my app I use CALLBACK_FLAG_REQUEST_DISCOVERY normally but I added a "rescan" 
button which uses CALLBACK_FLAG_FORCE_DISCOVERY, and she says on the new phone 
she doesn't have to use "rescan" as often as on the old phone but she still has 
to use it. 

If it is an issue with low memory, why does my old app with the CCL and the 
CastVideos sample app work just fine? doesn't the CCL use 
CALLBACK_FLAG_REQUEST_DISCOVERY?

Thanks. 

Original comment by casol...@gmail.com on 17 Sep 2015 at 3:43

GoogleCodeExporter commented 9 years ago
Another user sent me their device model. THL T6 PRO and it looks like it has 1 
gig of ram. They mentioned that other Chromecast apps don't have that issue, 
they mentioned one that I know uses CCL. 

Original comment by casol...@gmail.com on 17 Sep 2015 at 4:05

GoogleCodeExporter commented 9 years ago
Please refer to this example of MediaRouter implementation - 
https://github.com/googlecast/MediaRouter-Cast-Button-android - to debug 
MediaRouter issues.

Original comment by na...@google.com on 17 Sep 2015 at 5:23

GoogleCodeExporter commented 9 years ago
I compiled that example and sent it to two users. One of them said the device 
list populated right away and with my app he said sometimes it does and 
sometimes he has to "rescan" (which uses CALLBACK_FLAG_FORCE_DISCOVERY). 

The other user (the one with the two phones), said that on her new phone the 
device list populated right away but that on the old phone the device list was 
empty. 

For that second user, her old phone certainly has less ram so maybe that is the 
issue but I still don't understand why the CCL works just fine on her old 
phone? 

Thanks. 

Original comment by casol...@gmail.com on 19 Sep 2015 at 1:43

GoogleCodeExporter commented 9 years ago
I have another user who is on a mobile hotspot for whom apps built with the 
CastCompanionLibrary work fine but other apps don't, including 
https://github.com/googlecast/MediaRouter-Cast-Button-android 

He basically gets not devices at all unless the CastCompanionLibrary is used. 

Original comment by casol...@gmail.com on 1 Oct 2015 at 7:42