Статьи

Создать клиент YouTube на Android

Конечный продукт
Что вы будете создавать

В Google Play существует множество популярных сторонних клиентов YouTube, таких как Viral Popup и PlayTube, которые могут предложить некоторые уникальные и дополнительные функции, которых нет в официальном приложении YouTube. Если вы хотите создать одно такое приложение самостоятельно, это руководство для вас.

В этом руководстве мы создаем собственный клиент YouTube, который может не только искать видео на YouTube, но и воспроизводить их. Сделав это, мы узнаем, как использовать API проигрывателя YouTube для Android и клиентскую библиотеку API данных YouTube для Java.

Убедитесь, что у вас установлена ​​последняя версия Eclipse ADT Bundle. Вы можете скачать его на сайте разработчика Android ,

Вы также должны иметь ключ разработчика, чтобы использовать API YouTube. Следуйте инструкциям на веб-сайте Google для разработчиков, чтобы получить его.

Запустите Eclipse и создайте новое приложение для Android. Назовите приложение SimplePlayer . Выберите уникальное имя пакета и установите минимальный необходимый SDK для Android 2.2, а целевой SDK для Android 4.X (L Preview) .

Мы собираемся создать действие самостоятельно, поэтому отмените выбор « Создать действие» и нажмите « Готово» .

Для этого проекта вам понадобятся следующие библиотеки:

  • API Android YouTube Player: эта библиотека позволяет вашему приложению без проблем вставлять и контролировать видео YouTube. На момент написания статьи последняя версия этой библиотеки — 1.0.0 . Вы можете скачать его с сайта разработчиков Google .
  • Клиентская библиотека API данных v3 для Java: эта библиотека позволяет вашему приложению запрашивать информацию на YouTube. Мы собираемся использовать его, чтобы наше приложение могло искать видео на YouTube. Это также доступно на сайте разработчиков Google .
  • Пикассо: эта библиотека позволяет легко получать и отображать удаленные изображения. Мы собираемся использовать его для получения эскизов видео на YouTube. Последняя версия в настоящее время — 2.4.0, и вы можете скачать ее прямо из репозитория Maven .

Чтобы добавить API проигрывателя YouTube для Android, разархивируйте YouTubeAndroidPlayerApi-1.0.0.zip и скопируйте файл YouTubeAndroidPlayerApi.jar в папку libs вашего проекта.

Чтобы добавить библиотеку API данных YouTube v3 и ее зависимости, разархивируйте google-api-services-youtube-v3-rev124-java-1.19.0.zip и скопируйте следующие файлы в папку libs вашего проекта:

  • Google-API-сервисы YouTube-v3-rev124-1.19.0.jar
  • Google-апи-клиент-1.19.0.jar
  • Google-OAuth-клиент-1.19.0.jar
  • Google-HTTP-клиент-1.19.0.jar
  • jsr305-1.3.9.jar
  • Google-HTTP-клиент-jackson2-1.19.0.jar
  • ДЖЕКСОН-ядро-2.1.3.jar
  • Google-апи-клиент-андроид-1.19.0.jar
  • Google-HTTP-клиент-андроид-1.19.0.jar

Наконец, чтобы добавить Picasso, скопируйте picasso-2.4.0.jar в папку libs вашего проекта.

Единственное разрешение, в котором нуждается наше приложение, — это android.permission.INTERNET для доступа к серверам YouTube. Добавьте следующее в AndroidManifest.xml :

1
<uses-permission android:name=»android.permission.INTERNET»/>

Наше приложение имеет два вида деятельности: один для поиска видео и один для их воспроизведения. Чтобы не обрабатывать изменения ориентации в этом руководстве, мы заставляем обе операции использовать только ландшафтный режим. Объявите действия в манифесте, добавив в него следующий код:

01
02
03
04
05
06
07
08
09
10
<activity android:name=».SearchActivity»
    android:screenOrientation=»landscape»>
    <intent-filter>
        <action android:name=»android.intent.action.MAIN»/>
        <category android:name=»android.intent.category.LAUNCHER»/>
    </intent-filter>
</activity>
 
<activity android:name=».PlayerActivity»
    android:screenOrientation=»landscape» />

Файл res/values/strings.xml содержит строки, которые использует наше приложение. Обновите его содержимое, как показано ниже:

1
2
3
4
5
<resources>
    <string name=»app_name»>SimplePlayer</string>
    <string name=»search»>Search</string>
    <string name=»failed»>Failed to initialize Youtube Player</string>
</resources>

SearchActivity нужны следующие представления:

  • EditText : разрешить пользователю вводить ключевые слова для поиска
  • ListView : для отображения результатов поиска
  • LinearLayout : это представление служит родительским представлением вышеупомянутых представлений

Создайте новый файл с именем layout / activity_search.xml и добавьте в него следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
<?xml version=»1.0″ encoding=»utf-8″?>
<LinearLayout xmlns:android=»http://schemas.android.com/apk/res/android»
    android:layout_width=»match_parent»
    android:layout_height=»match_parent»
    android:orientation=»vertical» >
     
    <EditText
        android:layout_width=»match_parent»
        android:layout_height=»wrap_content»
        android:hint=»@string/search»
        android:id=»@+id/search_input»
        android:singleLine=»true»
        />
     
    <ListView
        android:id=»@+id/videos_found»
        android:layout_width=»match_parent»
        android:layout_height=»match_parent»
        android:dividerHeight=»5dp»
        />
         
</LinearLayout>

Каждый результат поиска относится к видео на YouTube, и нам нужен макет для отображения информации об этом видео. Поэтому каждый элемент ListView должен содержать следующие представления:

  • ImageView : для отображения миниатюры видео
  • TextView : для отображения заголовка видео
  • TextView : для отображения описания видео
  • RelativeLayout : это представление действует как родительское представление других представлений

Создайте файл с именем layout / video_item.xml и добавьте в него следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?xml version=»1.0″ encoding=»utf-8″?>
<RelativeLayout xmlns:android=»http://schemas.android.com/apk/res/android»
    android:layout_width=»match_parent»
    android:layout_height=»match_parent»
    android:padding=»16dp»
    >
     
    <ImageView
        android:id=»@+id/video_thumbnail»
        android:layout_width=»128dp»
        android:layout_height=»128dp»
        android:layout_alignParentLeft=»true»
        android:layout_alignParentTop=»true»
        android:layout_marginRight=»20dp»
        />
     
    <TextView android:id=»@+id/video_title»
        android:layout_width=»wrap_content»
        android:layout_height=»wrap_content»
        android:layout_toRightOf=»@+id/video_thumbnail»
        android:layout_alignParentTop=»true»
        android:layout_marginTop=»5dp»
        android:textSize=»25sp»
        android:textStyle=»bold»
        />
     
    <TextView android:id=»@+id/video_description»
        android:layout_width=»wrap_content»
        android:layout_height=»wrap_content»
        android:layout_toRightOf=»@+id/video_thumbnail»
        android:layout_below=»@+id/video_title»
        android:textSize=»15sp»
        />
 
</RelativeLayout>

PlayerActivity нужны следующие представления:

  • YouTubePlayerView : для воспроизведения видео YouTube
  • LinearLayout : это представление является родительским представлением YouTubePlayerView

Создайте новый файл с именем layout / activity_player.xml и добавьте в него следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
<?xml version=»1.0″ encoding=»utf-8″?>
<LinearLayout xmlns:android=»http://schemas.android.com/apk/res/android»
    android:layout_width=»match_parent»
    android:layout_height=»match_parent»
    android:orientation=»vertical» >
     
    <com.google.android.youtube.player.YouTubePlayerView
        android:id=»@+id/player_view»
        android:layout_width=»match_parent»
        android:layout_height=»wrap_content»/>
     
</LinearLayout>

Создайте новый класс Java с именем VideoItem.java . Мы используем этот класс для хранения следующей информации о видео YouTube:

  • Идентификатор YouTube
  • заглавие
  • описание
  • URL-адрес эскиза

Все вышеперечисленное хранится в виде строк. После добавления методов получения и установки для каждого из них файл VideoItem.java должен иметь следующее содержимое:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.hathi.simpleplayer;
 
public class VideoItem {
    private String title;
    private String description;
    private String thumbnailURL;
    private String id;
     
    public String getId() {
        return id;
    }
     
    public void setId(String id) {
        this.id = id;
    }
     
    public String getTitle() {
        return title;
    }
     
    public void setTitle(String title) {
        this.title = title;
    }
     
    public String getDescription() {
        return description;
    }
     
    public void setDescription(String description) {
        this.description = description;
    }
     
    public String getThumbnailURL() {
        return thumbnailURL;
    }
     
    public void setThumbnailURL(String thumbnail) {
        this.thumbnailURL = thumbnail;
    }
         
}

Чтобы избежать использования API данных YouTube непосредственно в нашей Activity , создайте новый класс Java и назовите его YoutubeConnector.java . Этот класс имеет следующие переменные-члены:

  • экземпляр класса YouTube который будет использоваться для связи с API YouTube
  • экземпляр YouTube.Search.List для представления поискового запроса
  • ключ API YouTube в виде статической String

Мы инициализируем указанные выше переменные в конструкторе. Чтобы инициализировать экземпляр YouTube , необходимо использовать класс YouTube.Builder . Классы, которые будут отвечать за сетевое соединение и обработку JSON, передаются сборщику.

После инициализации его метод search используется для создания поискового запроса. Затем используется метод list чтобы указать детали, которые мы хотим получить в результатах поиска. Для этого урока нам понадобится id и snippet для каждого результата поиска. Из них мы извлекаем следующие поля:

  • id/videoId
  • snippet/title
  • snippet/description
  • snippet/thumbnails/default/url

Ключ API разработчика необходимо отправлять с каждым поисковым запросом. Для этого setKey метод setKey . Мы также используем метод setType чтобы ограничить результаты поиска только videos . На этом этапе класс должен выглядеть примерно так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.hathi.simpleplayer;
 
public class YoutubeConnector {
    private YouTube youtube;
    private YouTube.Search.List query;
     
    // Your developer key goes here
    public static final String KEY
        = «AIzaSQZZQWQQWMGziK9H_qRxz8g-V6eDL3QW_Us»;
     
    public YoutubeConnector(Context context) {
        youtube = new YouTube.Builder(new NetHttpTransport(),
                new JacksonFactory(), new HttpRequestInitializer() {
            @Override
            public void initialize(HttpRequest hr) throws IOException {}
        }).setApplicationName(content.getString(R.string.app_name)).build();
         
        try{
            query = youtube.search().list(«id,snippet»);
            query.setKey(KEY);
            query.setType(«video»);
            query.setFields(«items(id/videoId,snippet/title,snippet/description,snippet/thumbnails/default/url)»);
        }catch(IOException e){
            Log.d(«YC», «Could not initialize: «+e);
        }
    }
}

Далее мы создаем метод с именем search для выполнения поиска по ключевым словам пользователя. Этот метод принимает ключевые слова в качестве параметра String . Метод setQ переменной query используется для установки ключевых слов.

Затем мы запускаем запрос, используя метод execute . Результаты возвращаются в форме экземпляра SearchListResponse . Мы перебираем элементы результата и создаем новый List объектов VideoItem , который будет возвращаемым значением этого метода. После добавления соответствующей обработки ошибок метод search должен выглядеть следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
public List<VideoItem> search(String keywords){
    query.setQ(keywords);
    try{
        SearchListResponse response = query.execute();
        List<SearchResult> results = response.getItems();
         
        List<VideoItem> items = new ArrayList<VideoItem>();
        for(SearchResult result:results){
            VideoItem item = new VideoItem();
            item.setTitle(result.getSnippet().getTitle());
            item.setDescription(result.getSnippet().getDescription());
            item.setThumbnailURL(result.getSnippet().getThumbnails().getDefault().getUrl());
            item.setId(result.getId().getVideoId());
            items.add(item);
        }
        return items;
    }catch(IOException e){
        Log.d(«YC», «Could not search: «+e);
        return null;
    }
}

Создайте новый класс с именем SearchActivity.java . Этот класс имеет поля, которые представляют представления, которые мы упоминали в activity_search.xml . Он также имеет Handler для обновления в потоке пользовательского интерфейса.

В методе onCreate мы инициализируем представления и добавляем OnEditorActionListener в EditText чтобы узнать, когда пользователь завершил ввод ключевых слов.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
public class SearchActivity extends Activity {
 
    private EditText searchInput;
    private ListView videosFound;
     
    private Handler handler;
     
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);
         
        searchInput = (EditText)findViewById(R.id.search_input);
        videosFound = (ListView)findViewById(R.id.videos_found);
         
        handler = new Handler();
         
        searchInput.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if(actionId == EditorInfo.IME_ACTION_DONE){
                    searchOnYoutube(v.getText().toString());
                    return false;
                }
                return true;
            }
        });
                 
    }
}

Вы, должно быть, заметили вызов метода searchOnYoutube . Давайте определим метод сейчас. В этом методе мы создаем новый YoutubeConnector для инициализации экземпляра YoutubeConnector и запускаем его метод search . Новый поток необходим, потому что сетевые операции не могут быть выполнены в основном потоке пользовательского интерфейса. Если вы забудете это сделать, вы столкнетесь с исключением во время выполнения. Как только результаты доступны, handler используется для обновления пользовательского интерфейса.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
private List<VideoItem> searchResults;
 
private void searchOnYoutube(final String keywords){
        new Thread(){
            public void run(){
                YoutubeConnector yc = new YoutubeConnector(SearchActivity.this);
                searchResults = yc.search(keywords);
                handler.post(new Runnable(){
                    public void run(){
                        updateVideosFound();
                    }
                });
            }
        }.start();
    }

В методе updateVideosFound мы генерируем ArrayAdapter и передаем его в ListView для отображения результатов поиска. В методе getView адаптера мы раздуваем макет video_item.xml и обновляем его представления для отображения информации о результате поиска.

Метод load библиотеки Picasso используется для извлечения миниатюры видео, а метод into — для его передачи в ImageView .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
private void updateVideosFound(){
    ArrayAdapter<VideoItem> adapter = new ArrayAdapter<VideoItem>(getApplicationContext(), R.layout.video_item, searchResults){
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if(convertView == null){
                convertView = getLayoutInflater().inflate(R.layout.video_item, parent, false);
            }
            ImageView thumbnail = (ImageView)convertView.findViewById(R.id.video_thumbnail);
            TextView title = (TextView)convertView.findViewById(R.id.video_title);
            TextView description = (TextView)convertView.findViewById(R.id.video_description);
             
            VideoItem searchResult = searchResults.get(position);
             
            Picasso.with(getApplicationContext()).load(searchResult.getThumbnailURL()).into(thumbnail);
            title.setText(searchResult.getTitle());
            description.setText(searchResult.getDescription());
            return convertView;
        }
    };
     
    videosFound.setAdapter(adapter);
}

Наконец, нам нужен метод, который устанавливает OnItemClickListener ListView чтобы пользователь мог щелкнуть по результату поиска и посмотреть соответствующее видео. Давайте addClickListener этот метод addClickListener и вызовем его в конце метода onCreate .

При нажатии на элемент в списке мы создаем новое Intent для PlayerActivity и передаем идентификатор видео. После создания Intent метод startActivity используется для запуска PlayerActivity .

01
02
03
04
05
06
07
08
09
10
11
12
13
private void addClickListener(){
    videosFound.setOnItemClickListener(new AdapterView.OnItemClickListener() {
 
        @Override
        public void onItemClick(AdapterView<?> av, View v, int pos,
                long id) {
            Intent intent = new Intent(getApplicationContext(), PlayerActivity.class);
            intent.putExtra(«VIDEO_ID», searchResults.get(pos).getId());
            startActivity(intent);
        }
         
    });
}

Создайте новый класс Java с именем PlayerActivity.java, который наследуется от YouTubeBaseActivity . Это важно, потому что только подклассы YouTubeBaseActivity могут использовать YouTubePlayerView .

Этот класс имеет единственную переменную-член, которая представляет YouTubePlayerView мы упомянули в файле макета activity_player.xml . Это инициализируется в методе onCreate , вызывая метод initialize класса YouTubePlayerView , передавая ключ API разработчика.

Затем нашему классу необходимо реализовать интерфейс OnInitializedListener чтобы знать, когда инициализация завершена. Интерфейс имеет два метода, названных onInitializationFailure и onInitializationSuccess .

В случае успеха метод cueVideo используется для отображения видео YouTube. В случае сбоя отображается Toast который сообщает пользователю, что инициализация не удалась.

Вот как должен выглядеть класс PlayerActivity :

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class PlayerActivity extends YouTubeBaseActivity implements OnInitializedListener {
     
    private YouTubePlayerView playerView;
     
    @Override
    protected void onCreate(Bundle bundle) {
        super.onCreate(bundle);
         
        setContentView(R.layout.activity_player);
 
        playerView = (YouTubePlayerView)findViewById(R.id.player_view);
        playerView.initialize(YoutubeConnector.KEY, this);
    }
 
    @Override
    public void onInitializationFailure(Provider provider,
            YouTubeInitializationResult result) {
        Toast.makeText(this, getString(R.string.failed), Toast.LENGTH_LONG).show();
    }
 
    @Override
    public void onInitializationSuccess(Provider provider, YouTubePlayer player,
            boolean restored) {
        if(!restored){
            player.cueVideo(getIntent().getStringExtra(«VIDEO_ID»));
        }
    }
}

Наш клиент YouTube теперь готов к развертыванию на устройстве Android. Он установлен почти на всех популярных устройствах Android, но убедитесь, что приложение YouTube установлено на устройстве, а также обновлено, поскольку наше приложение зависит от него.

После развертывания вы сможете ввести запрос для поиска видео на YouTube, а затем нажать на результат, чтобы начать воспроизведение соответствующего видео.

Теперь вы знаете, как вставлять видео YouTube в свое приложение для Android. Вы также узнали, как использовать клиентскую библиотеку Google API и взаимодействовать с YouTube. Android Player API предоставляет множество методов для управления воспроизведением видео, и вы можете использовать их для создания очень креативных приложений. Обратитесь к полному справочному руководству, чтобы узнать больше об API.