Marco
Marco

Reputation: 1093

Get all videos of a YouTube Playlist in Java

Context I'm working with Android Studio (Java). I want to obtain all the videos of a given playlist (or 50, I will get all the other after).

Problem I see people using url like https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=50&playlistId=PLiEwZfNgb4fVrRzTonlVEMj6DB2Nmzg2M&key=AIzaSyC2_YRcTE9916fsmA0_KRnef43GbLzz8m0 but I don't know how to implement this in Java. I follow some tuto and I got a way to get information totally different like :

YouTube.Search.List query;
query = youtube.search().list("id,snippet");
      query.setKey(MY_API_KEY);
      query.setMaxResults((long)20);
      query.setType("video");
      query.setFields("items(id/videoId,snippet/title,snippet/description,snippet/thumbnails/default/url)");

And I really don't understand how do I get something else than a search. Most of documentation is in english only...

EDIT Ok, so I continued to try, I think I got a near solution, but I got an error.

private YouTube youtube;
private YouTube.PlaylistItems.List playlistItemRequest;
private String PLAYLIST_ID = "PLiEwZfNgb4fVrRzTonlVEMj6DB2Nmzg2M";
public static final String KEY = "AIzaSyC2_YRcTE9916fsmA0_KRnef43GbLzz8m0";

// Constructor
public YoutubeConnector(Context context)
{
    youtube = new YouTube.Builder(new NetHttpTransport(),
            new JacksonFactory(), new HttpRequestInitializer()
    {
        @Override
        public void initialize(HttpRequest hr) throws IOException {}
    }).setApplicationName(context.getString(R.string.app_name)).build();
}

public List<VideoItem> result()
{
    List<PlaylistItem> playlistItemList = new ArrayList<PlaylistItem>();
    try
    {
    /* HERE MUST BE MY PROBLEM ! */
        playlistItemRequest = youtube.playlistItems().list("snippet");
        playlistItemRequest.setPlaylistId(PLAYLIST_ID);
        playlistItemRequest.setFields("items(id/videoId,snippet/title,snippet/description,snippet/thumbnails/default/url),nextPageToken,pageInfo");
        playlistItemRequest.setKey(KEY);
        String nextToken = "";
        do {
            playlistItemRequest.setPageToken(nextToken);
            PlaylistItemListResponse playlistItemResult = playlistItemRequest.execute();

            playlistItemList.addAll(playlistItemResult.getItems());

            nextToken = playlistItemResult.getNextPageToken();
        } while (nextToken != null);
    }catch(IOException e)
    {
        Log.d("YC", "Could not initialize: "+e);
    }
//[...]
}

Here is the error I got : { "code" : 400, "errors" : [ { "domain" : "global", "location" : "fields", "locationType" : "parameter", "message" : "Invalid field selection videoId", "reason" : "invalidParameter" } ], "message" : "Invalid field selection videoId" }

EDIT 2 Thanks to : Martijn Woudstra. Correct line was :

playlistItemRequest = youtube.playlistItems().list("snippet,contentDetails");
//[...]
playlistItemRequest.setFields("items(snippet/title,snippet/description,snippet/thumbnails/default/url,contentDetails/videoId),nextPageToken,pageInfo");
//[...]
videoItem.setId(item.getContentDetails().getVideoId());

Upvotes: 3

Views: 3925

Answers (2)

Teocci
Teocci

Reputation: 8975

I know that is an old question but It is important to identify which resources are we using to understand how to get the proper information. There are many resources in the YouTube API v3, but we usually use the search, video, playlist and playlistItems.

According to the documentation the following JSON structure shows the format of a playlistItems resource:

{
  "kind": "youtube#playlistItem",
  "etag": etag,
  "id": string,
  "snippet": {
    "publishedAt": datetime,
    "channelId": string,
    "title": string,
    "description": string,
    "thumbnails": {
      (key): {
        "url": string,
        "width": unsigned integer,
        "height": unsigned integer
      }
    },
    "channelTitle": string,
    "playlistId": string,
    "position": unsigned integer,
    "resourceId": {
      "kind": string,
      "videoId": string,
    }
  },
  "contentDetails": {
    "videoId": string,
    "startAt": string,
    "endAt": string,
    "note": string,
    "videoPublishedAt": datetime
  },
  "status": {
    "privacyStatus": string
  }
}

From this structure, we may suppose that there are three ways to get the videoId. But first it is important to know how we going to define the PARTS and the FIELDS of the resource.

To define the PARTS we use this code:

YouTube.PlaylistItems.List list = youtube.playlistItems().list("snippet");

In the previous line, "snippet" identifies a property that contains numerous fields (or child properties), including the title, description, position, and resourceId, so when we set "snippet" the API's response will contain all of those child properties.

Now, we also can limit the previous properties if we define the FIELDS. For example, in this code:

list.setFields("items(id/videoId,snippet/title,snippet/description," +
    "snippet/thumbnails/default/url)");

If we call list.execute(), it will show an error because we didn't define id in the PARTS properties. Also, according to the JSON structure, id is a String and does not contains videoId as a child property. Ah!, but we can extract videoId from the resourceId? -Well, the answers is YES/NO. -Why so? Come on Teo, the JSON structure shows it clearly. -Yes, I can see that, but the documentation says:

If the snippet.resourceId.kind property's value is youtube#video, then this property will be present and its value will contain the ID that YouTube uses to uniquely identify the video in the playlist.

This means that sometimes may not be available. -Then, how we can get the videoId? -Well, we can add id or contentDetails to the PARTS resources. If we add id then defines fields like this:

YouTube.PlaylistItems.List list = youtube.playlistItems().list("id,snippet");
list.setFields("items(id,snippet/title,snippet/description," +
    "snippet/thumbnails/default/url)");

If we add contentDetails then defines fields like this:

YouTube.PlaylistItems.List list = youtube.playlistItems()
    .list("snippet,contentDetails");
list.setFields("items(contentDetails/videoId,snippet/title,snippet/description," +
    "snippet/thumbnails/default/url)");

I hope this helps you guys.

Upvotes: 3

MartW
MartW

Reputation: 131

id/videoId doesnt exist. There is an id and a snippet/resourceId/videoId. So my guess is your setfields aren't right.

Upvotes: 2

Related Questions