Plugin and Play - Integrating YouTube with Eclipse
Join the DZone community and get the full member experience.
Join For FreeThe following article describes how to create a YouTube search plugin for Eclipse, that can be integrated into your everyday instance of the IDE. In this article you'll learn how to create a plugin using the Plugin Development Environment and how to use some parts of the Google YouTube API. This article is inspired from Geertjan's lead, where he created the same type of plugin for the IntelliJ IDE.
Getting Started
This example is based on Eclipse 3.3. I would recommend downloading the Eclipse For Plugin Developers Pack as it has all you need to get going. To interact with YouTube, you’ll need to download the YouTube Data API.
Create A New Project
From the File menu, choose to create a New Plug-in Project.
[img_assist|nid=1316|title=|desc=|link=none|align=left|width=525|height=541]
We want this plug-in to run from within Eclipse, rather than to create a separate RCP application for it. So you can just choose No to create a Rich Client Application, and to tick the choice for contributing to the UI.
[img_assist|nid=1317|title=|desc=|link=none|align=left|width=525|height=541]
At this stage you can click on Finish, as we won’t be using any of the templates for plug-ins that Eclipse provides. Once you click finish you will be asked if you wish to switch to the Plugin Developers Perspective. Of course, this is a good idea.
The Plugin Development Environment
For plug-ins, the MANIFEST.MF file is visualised and broken up into sections. The Overview page provides launch links so that you can run you plugin from there. This is a useful feature as it saves you from having to configure your own Run configuration.
The first thing we need to do is set up our Dependencies so that we can use the Google APIs for YouTube. To set up the classpath go to the Runtime tab in you MANIFEST.MF viewer and add the following jars from the Google API download.
- gdata-core-1.0.jar
- gdata-youtube-1.0.jar
- gdata-media-1.0.jar
- gdata-client-1.0.jar
You’ll also need to include mail.jar from the JavaMail distribution.
[img_assist|nid=1320|title=|desc=|link=none|align=left|width=743|height=528]
Create a New Menu
We’ll create a YouTube menu to invoke our code from. This section outlines how to create such a menu.
To create menus in Eclipse you need to use the Menu Contributions framework.
To use an extension point, you will need to go to the Extensions tab. Here you need to add a new org.eclipse.ui.menus extension by clicking on the Add button.
[img_assist|nid=1321|title=|desc=|link=none|align=left|width=500|height=717]
When you click on Finish you will see a new node in the list of Extensions named org.eclipse.ui.menus. Right-click on this node and choose New Menu Contribution, and in the locationURI field, We will choose to have the menu placed in a section set aside for additions - menu:org.eclipse.ui.main.menu?after=additions
Now that we’ve defined the location of our contribution, we need to define the menu itself. This time, right-click on the new contribution node in the Extensions list and choose New/ Menu. The only required field here is the text that will be displayed on the menu, which we’ll call “You Tube”.
[img_assist|nid=1323|title=|desc=|link=none|align=left|width=740|height=264]This will cause the node to be renamed to YouTube. Right click on that node and choose to add a new command. Provide this with the label “Search” and change the commandID to something other than the default.
In this example I use com.eclipsezone.youtube.searchcommand as the id.
[img_assist|nid=1324|title=|desc=|link=none|align=left|width=735|height=280]
Now we need to associate that commandID with a command, so add a new org.eclipse.ui.commands extension.
[img_assist|nid=1325|title=|desc=|link=none|align=left|width=503|height=717]
From the new node, create a new command that matches the commandID you provided previously and give the command a more readable name.
From this screen you can set up the handler for the command – this is the class that will get activated to run our You Tube action. Simply click on the defaultHandler link and Eclipse will provide a wizard to create the new class implementing the IHandler interface from the commands framework.
[img_assist|nid=1326|title=|desc=|link=none|align=left|width=744|height=280]
At this point, if you run the project, using the Overview tab and choose the launch option, you should simply see the new menu, with the search item underneath.
A useful tip for running your applications is to add the –consoleLog argument to the runtime configuration. You can add this by clicking on the Run… menu item, and add the argument to the Program Arguments field. Adding this will cause all logging and other messages to be displayed on the console tab.
[img_assist|nid=1327|title=|desc=|link=none|align=left|width=800|height=640]
Now that we have defined our extension points and created our menu items, it’s time to start writing our YouTube interaction code.
Interacting with YouTube
To make testing this easy, and to make the search code usable elsewhere, it makes sense to create a separate class to handle taking a search term and returning a list of results.
The code listing for this is as follows.
/**
* Return a list of video entries back to the calling method
*/
public VideoFeed getResults(String author, String title) throws IOException, ServiceException
{
YouTubeService myService = new YouTubeService("mycompany-myapp-1");
YouTubeQuery query = new YouTubeQuery(new URL(VIDEO_FEED));
//set the author
if( (author != null) && author.length() > 0)
{
query.setAuthor(author);
}
//set the actual query string
if((title != null) && title.length() > 0)
{
query.setVideoQuery(title);
}
//choose most viewed as the ordering
query.setOrderBy(YouTubeQuery.OrderBy.VIEW_COUNT);
//for the fun of it - include anything :-)
query.setIncludeRacy(true);
//get the video feed
VideoFeed feed = myService.query(query,VideoFeed.class);
return feed;
}
Create a View For Searching
Rather than launching a plain old pop up dialog, we’ll do something slightly more advanced, to fit in with the Eclipse look & feel. This will also show how to use further extension points.
Using the org.eclipse.ui.views extension point, this time we’ll use the example template to get the necessary code generated faster.
[img_assist|nid=1329|title=|desc=|link=none|align=left|width=500|height=717]
As you fill out the example, use the TableViewer – we will be changing how the view looks, but selecting this gives a good headstart, and provides all the method stubs we will need.
On completion of this dialog, you will notice a number of new entries in the plugin editor, including use of the org.eclipse.ui.views and org.eclipse.ui.perspectiveExtension extension points.
If you run the application now, and choose Show View/Other – you will see a YouTube entry in the list, where you can choose to Search YouTube. If you click on this it will display the Search window at the bottom section of the screen. A number of default entries are provided in the table component.
[img_assist|nid=1330|title=|desc=|link=none|align=left|width=750|height=185]
Also, we will update our SearchHandler code so that when the action is executed for Search that it will also open the YouTube view. In the execute method, add the following code – you can get the id of the view by clicking on it in the plugin editor and copying the value of the id field. It is good practise to add the ID as a constant for each view for easy access in your code.
try
{
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView("com.eclipsezone.youtube.views.YouTubeView");
}
catch (WorkbenchException e)
{
e.printStackTrace();
}
Implementing the Search User Interface
The generated YouTubeView class contains the UI code that gets displayed in our Search tab in the tasks view.
The createPartControl method is where the composites are created.
In this example I have used the FormsToolkit to render the components in the view using the org.eclipse.ui.forms extension. You will need to add this to your list of Required Plugins. Above our table view, we want to display a search field where we can type in an author or title and see the results populate the table.
Here is a code snippet from the createPartControl method which makes only a few alterations to the TableViewer creation code for layout purposes.
//use the form toolkit for rendering
FormToolkit toolkit = new FormToolkit(Display.getCurrent());
Composite container = new Composite(parent, SWT.NONE);
toolkit.adapt(container);
toolkit.paintBordersFor(container);
container.setLayout(new GridLayout());
final GridData gd_container = new GridData(SWT.FILL, SWT.BEGINNING, true, true);
container.setLayoutData(gd_container);
/**
* Create a group for the search fields and button
*/
final Group searchGroup = new Group(container, SWT.NONE);
toolkit.adapt(searchGroup);
toolkit.paintBordersFor(searchGroup);
searchGroup.setText("Search");
final GridData gd_searchGroup = new GridData(SWT.FILL, SWT.CENTER, true, false);
searchGroup.setLayoutData(gd_searchGroup);
final GridLayout gridLayout = new GridLayout();
gridLayout.numColumns = 2;
searchGroup.setLayout(gridLayout);
final Label titleLabel = toolkit.createLabel(searchGroup,null, SWT.NONE);
titleLabel.setText("Title:");
txtTitle = toolkit.createText(searchGroup, null, SWT.BORDER);
txtTitle.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
final Label authorLabel = toolkit.createLabel(searchGroup,null, SWT.NONE);
authorLabel.setText("Author:");
txtAuthor = toolkit.createText(searchGroup,null, SWT.BORDER);
txtAuthor.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
new Label(searchGroup, SWT.NONE);
searchYoutubeButton = toolkit.createButton(searchGroup, null, SWT.NONE);
searchYoutubeButton.setText("Search YouTube");
viewer = new TableViewer(container, SWT.SINGLE | SWT.FILL | SWT.H_SCROLL | SWT.V_SCROLL );
viewer.getControl().setLayoutData(new GridData(GridData.BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING | GridData.GRAB_VERTICAL
| GridData.FILL_BOTH));
viewer.setContentProvider(new ViewContentProvider());
viewer.setLabelProvider(new ViewLabelProvider());
viewer.setSorter(new NameSorter());
viewer.setInput(getViewSite());
We also need to provide a SelectionListener for the button so that it can populate the table with the results of our search. An important feature of this code is that we use an IRunnableWithProgress so that we can display a wait progress bar while the search is being run.
searchYoutubeButton.addSelectionListener(
new SelectionAdapter()
{
public void widgetSelected(SelectionEvent e)
{
try
{
PlatformUI.getWorkbench().getProgressService().run(false, true,
new IRunnableWithProgress()
{
public void run(org.eclipse.core.runtime.IProgressMonitor monitor) throws java.lang.reflect.InvocationTargetException ,InterruptedException
{
YouTubeSearch search = new YouTubeSearch();
monitor.setTaskName("Retrieving Results....");
try
{
feed = search.getResults(txtAuthor.getText(), txtTitle.getText());
viewer.refresh();
}
catch (IOException e1)
{
e1.printStackTrace();
}
catch (ServiceException e1)
{
e1.printStackTrace();
}
};});
}
catch (InvocationTargetException e4) {
e4.printStackTrace();
} catch (InterruptedException e2) {
e2.printStackTrace();
}
}
});
When the view was created using the template, it provided a default model for the TableViewer. We need to replace this model with our YouTube search results. As you can see from the above listener code, we simply store the feed as a variable within this class.
The ViewContentProvider inner class that is created contains a getElements method, which returns the model to be rendered as an Object array. This snippet shows the changes made for this method.
public Object[] getElements(Object parent)
{
if(feed != null)
{
return feed.getEntries().toArray();
}
return new String[] {};
}
The ViewLabelProvider will render the model. There are two signifigant changes made here. Firstly, the text we want to display is the title of the result, and it would be really nice to display the thumbnail of the result in the tree.
public String getColumnText(Object obj, int index)
{
return ((VideoEntry)obj).getTitle().getPlainText();//getText(obj);
}
public Image getImage(Object obj)
{
YouTubeMediaGroup mediaGroup = ((VideoEntry)obj).getMediaGroup();
//use the first thumbnail
String imgURL = mediaGroup.getThumbnails().get(0).getUrl();
try
{
ImageDescriptor desc = ImageDescriptor.createFromURL(new URL(imgURL));
return desc.createImage();
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
//default image.
return PlatformUI.getWorkbench().
getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT);
}
When the search is run now, we can see the thumbnails for each of the entries.
[img_assist|nid=1331|title=|desc=|link=none|align=left|width=696|height=359]
Providing a Browser View
Finally, it would be nice that when we double click on any of the entries that we could view the video within Eclipse.
There are three stages to this - providing a view, implementing a browser instance and finding the view through a double click action.
To provide the view, rather than using templates again, we just need to create a new instance of the org.eclipse.ui.views extension point in the Plugin Manifest Editor.
[img_assist|nid=1334|title=|desc=|link=none|align=left|width=773|height=174]
Eclipse provides a Browser class which renders HTML using the default browser on your machine. In our generated view, we can just create a browser instance in the createPartControl method.
browser = new Browser(parent, SWT.NONE);
We also need to add a method in the view to set the URL of the browser
public void setURL(String url)
{
browser.setUrl(url);
}
As you can see, it's quite easy to do all of this. A double-click action was provided when we created the view from the template. We just need to alter the run method to find the browser view and pass through the URL of the selected item in the results table.
ISelection selection = viewer.getSelection();
VideoEntry video = (VideoEntry)((IStructuredSelection)selection).getFirstElement();
//open a browser window for this item
try
{
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView(BrowserView.ID);
IViewReference[] views = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getViewReferences();
for(int i = 0; i < views.length; i++)
{
IViewReference ref = views[i];
if(ref.getId().equals(BrowserView.ID))
{
((BrowserView)ref.getView(true)).setURL(video.getHtmlLink().getHref());
}
}
}
catch (WorkbenchException e)
{
e.printStackTrace();
}
The result of these few lines of code is quite satisfying - a browser view will open up within Eclipse to play the video.[img_assist|nid=1332|title=|desc=|link=none|align=left|width=739|height=381]
Conclusion
This article shows how much you can do with the Plugin Development Environment in Eclipse. There's a learning curve involved, as you get used to creating views and actions through the plugin manifest, but it's very rewarding to see the end product.
The best way to learn is by practice. Try implementing the plugin described in this article, and let me know of any extra functionality that you add to it.
Opinions expressed by DZone contributors are their own.
Comments