vitalidze/chromecast-java-api-v2

Unrecognized field "extendedStatus"

Closed this issue · 10 comments

Hi, have you ever seen the field extendedStatus?

2016-10-24 22:22:48.499 [WARN ] [tvak.chromecast.api.v2.Channel:191  ]
Error while reading: Unrecognized field "extendedStatus" (Class su.litvak.chromecast.api.v2.MediaStatus), not marked as ignorable
 at [Source: N/A; line: -1, column: -1] (through reference chain: su.litvak.chromecast.api.v2.MediaStatus["extendedStatus"])

2016-10-24 22:22:48.499 [WARN ] [tvak.chromecast.api.v2.Channel:198  ]
<-- {"type":"MEDIA_STATUS","status":[{"mediaSessionId":1,"playbackRate":1,"playerState":"IDLE","currentTime":0,"supportedMediaCommands":15,"volume":{"level":1,"muted":false},"media":{"contentId":"http://192.168.2.139:9080/audio/99fd6998-aa4d-4764-9b41-c6869dcfc85f.mp3","contentType":null},"currentItemId":1,"extendedStatus":{"playerState":"LOADING","media":{"contentId":"http://192.168.2.139:9080/audio/99fd6998-aa4d-4764-9b41-c6869dcfc85f.mp3","contentType":null}},"repeatMode":"REPEAT_OFF"}],"requestId":0}

I don't know how to handle that correctly.
@vitalidze can you give me some details how it is done for the other stuff?

As the player state "loading" is not found in the specification you linked in your source code and its the only one I receive ATM in the extended status, I added a new enum.

To fix the runtime error, I use this changes:
https://github.com/vitalidze/chromecast-java-api-v2/compare/master...maggu2810:extended-status?expand=1

I have never seen that. From which app do you receive that field in MediaStatus?

I don't see any info in android docs as well.

I am not sure how to handle it correctly since it's not expected. Maybe it's worth to start ignoring missing fields during JSON deserialization.

My standard test does not work also due to additional videoInfo field in MediaStatus:

{  
   "type":"MEDIA_STATUS",
   "status":[  
      {  
         "mediaSessionId":1,
         "playbackRate":1,
         "playerState":"BUFFERING",
         "currentTime":0,
         "supportedMediaCommands":15,
         "volume":{  
            "level":1,
            "muted":false
         },
         "videoInfo":{  
            "width":1280,
            "height":720,
            "hdrType":"sdr"
         },
         "media":{  
            "contentId":"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
            "contentType":"video/mp4",
            "duration":596.474195
         },
         "currentItemId":1,
         "items":[  
            {  
               "itemId":1,
               "media":{  
                  "contentId":"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4",
                  "contentType":"video/mp4",
                  "duration":596.474195
               },
               "autoplay":true,
               "customData":{  
                  "payload":{  
                     "title:":"Big Buck Bunny",
                     "thumb":"images/BigBuckBunny.jpg"
                  }
               }
            }
         ],
         "repeatMode":"REPEAT_OFF"
      }
   ],
   "requestId":7
}

I think the best way to handle this is to add @JsonIgnoreProperties(ignoreUnknown = true) annotation to the MediaStatus and to all other classes, which are deserializaed from JSON. I will add it.

From which app do you receive that field in MediaStatus?

I assume the message is generated by the media player of my ChromeCast.
I am using the following code to play a stream provided by a given URL:

private static final String MEDIA_PLAYER = "CC1AD845";

void playUri(final String uri) {
    try {
        final Status status = chromecast.getStatus();
        if (chromecast.isAppAvailable(MEDIA_PLAYER)) {
            if (!status.isAppRunning(MEDIA_PLAYER)) {
                final Application app = chromecast.launchApp(MEDIA_PLAYER);
                logger.debug("Application launched: {}", app);
            }
            chromecast.load(uri);
        } else {
            logger.error("Missing media player app");
        }
    } catch (final IOException ex) {
        logger.debug("Play URI failed.", ex);
    }
}

I think the best way to handle this is to add @JsonIgnoreProperties(ignoreUnknown = true) annotation to the MediaStatus and to all other classes, which are deserializaed from JSON.

It seems the best thing to do.
At least after calling my function above the first time, the URL is played on the ChromeCast and the library complains about the unrecognised field. After that I cannot play the URL again, the communication seems a little bit broken. I need to have a further look at, what causes the broken connection.
After adding the extendedStatus (at least the fields of the response) to prevent the exception I can play the URL multiple times.

As long as there is no use case for the "new" fields, there is no need to add a class for every information.

Do you know if there is a mechanism to log such available but ignored properties?
It seems that Google adds fields on updates.
Wouldn't it be nice to have a mechanism to identify such new fields?

I will add it.

Thank you.

Do you know if there is a mechanism to log such available but ignored properties?
It seems that Google adds fields on updates.
Wouldn't it be nice to have a mechanism to identify such new fields?

I have spent some times researching that. Unfortunately there is no such mechanism. The only thing that is present is so-called any-setter, which does not work because currently objects are created via constructor. I don't want to change this because this allows to keep objects immutable.

I think I have added necessary code. Please try running your code after pulling from upstream.

Will do it if I am at home again and report. Thank you.

If it works I will release next version ASAP because it looks like a "show stopper" issue.

Works for me.

Great. Thank you. I will release new version tomorrow.