Статьи

Подключи и играй — Интеграция YouTube с Eclipse

В следующей статье описывается, как создать поисковый плагин YouTube для Eclipse, который можно интегрировать в ваш повседневный экземпляр IDE. В этой статье вы узнаете, как создать плагин с использованием среды разработки плагинов и как использовать некоторые части API Google YouTube. Эта статья основана на руководстве Гертьяна , где он создал плагин такого же типа для IntelliJ IDE.

Начиная

Этот пример основан на Eclipse 3.3. Я бы порекомендовал скачать Eclipse For Plugin Developers Pack, поскольку в нем есть все, что вам нужно для начала работы. Для взаимодействия с YouTube вам необходимо загрузить API данных YouTube .

Создать новый проект

В меню «Файл» выберите «Создать новый проект плагина».

[Img_assist | NID = 1316 | название = | убывание = | ссылка = нет | ALIGN = слева | ширина = 525 | высота = 541]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Мы хотим, чтобы этот плагин запускался из Eclipse, а не создавал для него отдельное приложение RCP. Таким образом, вы можете просто выбрать «Нет», чтобы создать приложение Rich Client, и отметить выбор для внесения вклада в пользовательский интерфейс.

[Img_assist | NID = 1317 | название = | убывание = | ссылка = нет | ALIGN = слева | ширина = 525 | высота = 541]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

На этом этапе вы можете нажать «Готово», так как мы не будем использовать шаблоны для плагинов, которые предоставляет Eclipse. После того, как вы нажмете «Готово», вас спросят, хотите ли вы переключиться на Перспективу разработчиков плагинов. Конечно, это хорошая идея.

Среда разработки плагинов

Для плагинов файл MANIFEST.MF визуализируется и разбивается на разделы. Страница «Обзор» содержит ссылки для запуска, так что вы можете запустить свой плагин оттуда. Это полезная функция, поскольку она избавляет вас от необходимости настраивать собственную конфигурацию запуска.

Первое, что нам нужно сделать, это настроить наши зависимости, чтобы мы могли использовать API Google для YouTube. Чтобы настроить путь к классам, перейдите на вкладку «Runtime» в программе просмотра MANIFEST.MF и добавьте следующие файлы jar из загрузки Google API.

  • GData-ядро-1.0.jar
  • GData-YouTube-1.0.jar
  • GData-медиа-1.0.jar
  • GData-клиент-1.0.jar

Вам также нужно будет включить mail.jar из дистрибутива JavaMail .

[Img_assist | NID = 1320 | название = | убывание = | ссылка = нет | ALIGN = слева | ширина = 743 | Высота = 528]

Создать новое меню

Мы создадим меню YouTube для вызова нашего кода. В этом разделе рассказывается, как создать такое меню.
Для создания меню в Eclipse вам нужно использовать платформу Menu Contributions .

Чтобы использовать точку расширения, вам нужно перейти на вкладку Расширения. Здесь вам нужно добавить новое расширение org.eclipse.ui.menus , нажав на кнопку Добавить.

[Img_assist | NID = 1321 | название = | убывание = | ссылка = нет | ALIGN = слева | ширина = 500 | высота = 717]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Когда вы нажмете Finish, вы увидите новый узел в списке расширений с именем org.eclipse.ui.menus . Щелкните правой кнопкой мыши по этому узлу и выберите New Menu Contribution, и в поле locationURI мы выберем размещение меню в разделе, выделенном для дополнений — menu: org.eclipse.ui.main.menu? After = дополнения

Теперь, когда мы определили местоположение нашего вклада, нам нужно определить само меню. На этот раз щелкните правой кнопкой мыши новый узел вклада в списке «Расширения» и выберите «Создать / Меню». Единственное обязательное поле здесь — это текст, который будет отображаться в меню, которое мы назовем «You Tube».

[img_assist | nid = 1323 | title = | desc = | link = none | align = left | width = 740 | height = 264] Это приведет к тому, что узел будет переименован в YouTube. Щелкните правой кнопкой мыши по этому узлу и выберите добавление новой команды. Укажите для этого метку «Поиск» и измените идентификатор команды на значение, отличное от значения по умолчанию.
В этом примере я использую com.eclipsezone.youtube.searchcommand в качестве идентификатора.

[Img_assist | NID = 1324 | название = | убывание = | ссылка = нет | ALIGN = слева | ширина = 735 | высота = 280]

 

 

Теперь нам нужно связать этот идентификатор команды с командой, поэтому добавьте новое расширение org.eclipse.ui.commands .

[Img_assist | NID = тысяча триста двадцать пять | название = | убывание = | ссылка = нет | ALIGN = слева | ширина = 503 | высота = 717]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

На новом узле создайте новую команду, которая соответствует указанному ранее идентификатору команды, и дайте команде более удобочитаемое имя.

На этом экране вы можете настроить обработчик для команды — это класс, который активируется для запуска нашего действия You Tube. Просто нажмите на ссылку defaultHandler, и Eclipse предоставит мастер для создания нового класса, реализующего интерфейс IHandler из инфраструктуры команд.

[Img_assist | NID = 1326 | название = | убывание = | ссылка = нет | ALIGN = слева | ширина = 744 | Высота = 280]

 

 

На этом этапе, если вы запустите проект, используя вкладку Обзор и выберете опцию запуска, вы должны просто увидеть новое меню с элементом поиска внизу.

Полезный совет для запуска ваших приложений — добавить аргумент –consoleLog в конфигурацию времени выполнения. Вы можете добавить это, щелкнув по пункту меню Run … и добавить аргумент в поле Program Arguments. Добавление этого приведет к тому, что все журналы и другие сообщения будут отображаться на вкладке консоли.

[Img_assist | NID = 1327 | название = | убывание = | ссылка = нет | ALIGN = слева | ширина = 800 | Высота = 640]

Теперь, когда мы определили наши точки расширения и создали наши пункты меню, пришло время начать писать наш код взаимодействия с YouTube.

Взаимодействие с YouTube

Чтобы упростить тестирование и сделать код поиска пригодным для использования в других местах, имеет смысл создать отдельный класс, который будет обрабатывать поиск и возвращать список результатов.
Список кода для этого выглядит следующим образом.

   /**
* 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;
}

Создать представление для поиска

Вместо того, чтобы запускать простой старый всплывающий диалог, мы сделаем что-то немного более продвинутое, чтобы соответствовать внешнему виду и ощущению Eclipse. Это также покажет, как использовать дополнительные точки расширения.

Используя точку расширения org.eclipse.ui.views , на этот раз мы будем использовать шаблон примера, чтобы получить необходимый код, сгенерированный быстрее.

[Img_assist | NID = 1329 | название = | убывание = | ссылка = нет | ALIGN = слева | ширина = 500 | высота = 717]

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

По мере заполнения примера используйте TableViewer — мы будем изменять внешний вид представления, но выбор этого дает хороший старт и предоставляет все заглушки методов, которые нам понадобятся.

По завершении этого диалогового окна вы увидите ряд новых записей в редакторе плагинов, включая использование точек расширения org.eclipse.ui.views и org.eclipse.ui.perspectiveExtension .
Если вы запустите приложение сейчас и выберите «Показать вид / другое» — вы увидите запись YouTube в списке, где вы можете выбрать «Поиск на YouTube». Если вы нажмете на это, появится окно поиска в нижней части экрана. Ряд записей по умолчанию предоставляется в компоненте таблицы.

[Img_assist | NID = 1330 | название = | убывание = | ссылка = нет | ALIGN = слева | ширина = 750 | высота = 185]

Кроме того, мы обновим наш код SearchHandler, чтобы при выполнении действия для поиска он также открывал представление YouTube. В метод execute добавьте следующий код — вы можете получить идентификатор представления, щелкнув по нему в редакторе плагинов и скопировав значение поля id. Хорошей практикой является добавление идентификатора в качестве константы для каждого представления для быстрого доступа к вашему коду.

try 
{
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().showView("com.eclipsezone.youtube.views.YouTubeView");
}
catch (WorkbenchException e)
{
e.printStackTrace();
}

Реализация интерфейса поиска пользователя

Сгенерированный класс YouTubeView содержит код пользовательского интерфейса, который отображается на нашей вкладке Поиск в представлении задач.
Метод createPartControl — это место, где создаются композиты.

В этом примере я использовал FormsToolkit для визуализации компонентов в представлении с использованием расширения org.eclipse.ui.forms . Вам нужно будет добавить это в список необходимых плагинов. Над нашим табличным представлением мы хотим отобразить поле поиска, где мы можем ввести автора или заголовок и увидеть результаты, заполняющие таблицу.

Вот фрагмент кода из метода createPartControl, который вносит лишь несколько изменений в код создания TableViewer для макета.

		//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());

Нам также нужно предоставить SelectionListener для кнопки, чтобы она могла заполнять таблицу результатами нашего поиска. Важной особенностью этого кода является то, что мы используем IRunnableWithProgress, чтобы мы могли отображать индикатор хода выполнения во время выполнения поиска.

		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();
}
}
});



Когда представление было создано с использованием шаблона, оно предоставило модель по умолчанию для TableViewer. Нам нужно заменить эту модель на наши результаты поиска YouTube. Как вы можете видеть из приведенного выше кода слушателя, мы просто сохраняем фид как переменную внутри этого класса.

ViewContentProvider внутренний класс , который создается содержит getElements метод, который возвращает модель , которая будет предоставляться в виде массива объектов. Этот фрагмент показывает изменения, сделанные для этого метода.

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.