Ryan's Log

Ionic - Youtube API Example 본문

IONIC

Ionic - Youtube API Example

Ryan c 2018. 5. 8. 10:57
728x90

[IONIC Example] 

Youtube API



IONIC에서 Youtube검색 결과를 출력하고, Native Youtube player를 이용해 영상을 플레이한다.


IONIC 설치 등은 앞 글(설치 및 새로운 앱 시작)을 참조


우선 만들어진 화면부터 보자


HOME 화면에 정해진 키워드로 검색한 결과를 나열 할 예정이며, 화면 하나면 충분하므로 template은 blank로 선택하도록 한다.


IONIC Blank 앱을 시작한다. 

> ionic start YoutubeExampleApp blank


 YoutubeExampleApp이 만들어지면 바로 시작!

> cd GoogleMapExampleApp

> ionic serve


바로 소스코드 작성 들어간다...


./src/pages/home/home.html을 열어 div를 만들고, 그 안에 Youtube 영상 정보가 반복 생성될 수 있도록 video-info라는 이름의 태그를 만들어 넣는다.

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic - Youtube Search
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <video-info *ngFor="let item of results" [result]="item">
  </video-info>
</ion-content>


./src/pages/home/home.ts를 열어 다소 복잡한 아래 소스코드로 작성한다. 

import { Component } from '@angular/core';
import { NavController, Platform } from 'ionic-angular';
import { HttpClient } from '@angular/common/http';

export const YOUTUBE_API_KEY: string = 'AIzaSyCe3Jf_4CwA5AYrufD-NH_FSB5WnG5-IM0';
export const YOUTUBE_PLAY_URL: string = 'https://www.youtube.com/watch?v=';
export const SEARCH_API_URL: string = 'https://www.googleapis.com/youtube/v3/search';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  constructor(public navCtrl: NavController,
    public platform: Platform,
    public http: HttpClient) {

      platform.ready().then(() => {
        this.doSearch('learning ionic framework');
      });

  }

  results: Object[];
  
  doSearch(keyword: string) {
    let params: string = [
      `q=${keyword}`,
      `key=${YOUTUBE_API_KEY}`,
      `part=snippet`,
      `type=video`,
      `order=date`,
      `maxResults=15`,
    ].join('&');
    let queryUrl: string = `${SEARCH_API_URL}?${params}`;

    this.http.get(queryUrl).subscribe((response:any) => {
      this.results = response.items.map(item => {
        return new Object({
          id: item.id.videoId,
          title: item.snippet.title,
          description: item.snippet.description,
          thumbnailUrl: item.snippet.thumbnails.high.url,
          channelTitle: item.snippet.channelTitle,
          publishedAt: new Date(item.snippet.publishedAt)
        });
      });
    });

  }

}


@Component({
  inputs: ['result'],
  selector: 'video-info',
  template: `
    <div class="one-of-content video">
      <div class="content-head">
        <div class="channel">{{result.channelTitle}}</div>
        <div class="caption">{{result.description}}</div>
      </div>
      <div class="thumbnail">
        <img src="{{result.thumbnailUrl}}">
      </div>
      <div class="content-body">
        <h3>{{result.title}}</h3>
      </div>
      <div class="content-foot">
        <div class="wrote">{{result.publishedAt | date:'yyyy-MM-dd HH:mm' }}</div>
      </div>
      <button ion-button full color="danger" (click)="play(result.id)">Play</button>
    </div>
 `
})
export class VideoInfoComponent {
  result: Object;
  constructor(public navCtrl: NavController){
  }

  play(videoId) {
    location.href = YOUTUBE_PLAY_URL + videoId;
  }
}

Platform이 ready된 시점에 doSearch()를 호출하며, doSearch()는 results라는 class property에 검색된 결과를 풀어 videoId,  title, description, 영상의 thumbnail 이미지 등의 URL등의 필요한 정보만을 취합하여 담는다.

이후 VideoInfoComponent Angular 컴포넌트가 results를 감시하며, 값 변경에 따라 template을 반복하여 위 videoId, title, description등을 이용해 HTML Markup을 그려낸다.


./src/pages/home/home.scss를 열어 video-info를 적절히 디자인한다.

page-home {

    video-info {
        margin: 10px 0 30px 0;
        display: block;
    }

    .channel {
        font-weight: bold;
        font-size: 1.8rem;
    }
}


./src/app/app.module.ts에 HttpClientModule과 VideoInfoComponent를 각각 import와 declaration 한다.

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import { HttpClientModule } from '@angular/common/http';

import { MyApp } from './app.component';
import { HomePage, VideoInfoComponent } from '../pages/home/home';

@NgModule({
  declarations: [
    MyApp,
    HomePage,
    VideoInfoComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}


여기까지 완료 하였다면 아래처럼 브라우저에서 검색된 Youtube 영상 목록이 나열됨을 볼 수 있다.


여기까지를 빌드한다.

> ionic cordova build android


빌드 성공후 아래 위치의 파일을 폰으로 넘겨 설치하여 실행해보도록 하자.

/platforms/android/app/build/outputs/apk/debug/app-debug.apk


이파일을 있는 Android 기기에 설치한 후 실행한다. 

빨간 Play 버튼을 클릭하면 Android내에 Youtube 앱이 실행되며 재생된다. 


이제 이 Play버튼 대신 Play Native 버튼을 만들어 Native Youtube Player 플러그인을 이용하여 재생 하도록 추가 해보도록 하자.


우선 Youtube Video Player 플러그인을 설치한다.

https://ionicframework.com/docs/native/youtube-video-player/

> ionic cordova plugin add cordova-plugin-youtube-video-player

> npm install --save @ionic-native/youtube-video-player


위 ionicframework.com 사이트를 보면 Android의 5.0이상의 경우 Youtube Native Player 사용을 위해 API키를 config.xml에 추가 해야 한다고 명시되어 있다. 


./config.xml을 열어 아래를 추가한다. 

<?xml version='1.0' encoding='utf-8'?>
<widget id="io.ionic.starter" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>YoutubeExampleApp</name>
    <description>An awesome Ionic/Cordova app.</description>
    <author email="hi@ionicframework" href="http://ionicframework.com/">Ionic Framework Team</author>
    <content src="index.html" />
    <access origin="*" />
    <allow-intent href="http://*/*" />
    <allow-intent href="https://*/*" />
    <allow-intent href="tel:*" />
    <allow-intent href="sms:*" />
    <allow-intent href="mailto:*" />
    <allow-intent href="geo:*" />
    <preference name="ScrollEnabled" value="false" />
    <preference name="android-minSdkVersion" value="19" />
    <preference name="BackupWebStorage" value="none" />
    <preference name="SplashMaintainAspectRatio" value="true" />
    <preference name="FadeSplashScreenDuration" value="300" />
    <preference name="SplashShowOnlyFirstTime" value="false" />
    <preference name="SplashScreen" value="screen" />
    <preference name="SplashScreenDelay" value="3000" />
    <preference name="YouTubeDataApiKey" value="AIzaSyCe3Jf_4CwA5AYrufD-NH_FSB5WnG5-IM0" />
    <platform name="android">
        <allow-intent href="market:*" />
        <icon density="ldpi" src="resources/android/icon/drawable-ldpi-icon.png" />
...
    </platform>
    <plugin name="cordova-plugin-whitelist" spec="1.3.3" />
    <plugin name="cordova-plugin-device" spec="2.0.2" />
    <plugin name="cordova-plugin-splashscreen" spec="5.0.2" />
    <plugin name="cordova-plugin-ionic-webview" spec="1.1.19" />
    <plugin name="cordova-plugin-ionic-keyboard" spec="2.0.5" />
    <plugin name="cordova-plugin-youtube-video-player" spec="^1.0.6" />
    <engine name="android" spec="7.0.0" />
</widget>

./src/app/app.module.ts에 YoutubeVideoPlayer를 import 하고 Provide한다.

import { BrowserModule } from '@angular/platform-browser';
import { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';
import { SplashScreen } from '@ionic-native/splash-screen';
import { StatusBar } from '@ionic-native/status-bar';
import { HttpClientModule } from '@angular/common/http';
import { YoutubeVideoPlayer } from '@ionic-native/youtube-video-player';

import { MyApp } from './app.component';
import { HomePage, VideoInfoComponent } from '../pages/home/home';

@NgModule({
  declarations: [
    MyApp,
    HomePage,
    VideoInfoComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    YoutubeVideoPlayer,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

마지막으로 ./src/pages/home/home.ts를 다시 열어 video-info 탬플릿에 버튼을 추가하고. 버튼 이벤트에 player를 이용한 재생 기능을 코딩한다.

import { Component } from '@angular/core';
import { NavController, Platform } from 'ionic-angular';
import { HttpClient } from '@angular/common/http';
import { YoutubeVideoPlayer } from '@ionic-native/youtube-video-player';

export const YOUTUBE_API_KEY: string = 'AIzaSyCe3Jf_4CwA5AYrufD-NH_FSB5WnG5-IM0';
export const YOUTUBE_PLAY_URL: string = 'https://www.youtube.com/watch?v=';
export const SEARCH_API_URL: string = 'https://www.googleapis.com/youtube/v3/search';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  ...

}


@Component({
  inputs: ['result'],
  selector: 'video-info',
  template: `
    <div class="one-of-content video">
      <div class="content-head">
        <div class="channel">{{result.channelTitle}}</div>
        <div class="caption">{{result.description}}</div>
      </div>
      <div class="thumbnail">
        <img src="{{result.thumbnailUrl}}">
      </div>
      <div class="content-body">
        <h3>{{result.title}}</h3>
      </div>
      <div class="content-foot">
        <div class="wrote">{{result.publishedAt | date:'yyyy-MM-dd HH:mm' }}</div>
      </div>
      <button ion-button full color="danger" (click)="play(result.id)">Play</button>
      <button ion-button full color="primary" (click)="playNative(result.id)">Play Native</button>
    </div>
 `
})
export class VideoInfoComponent {
  result: Object;
  constructor(public navCtrl: NavController, 
    public player: YoutubeVideoPlayer){
  }

  play(videoId) {
    location.href = YOUTUBE_PLAY_URL + videoId;
  }

  playNative(videoId) {
    this.player.openVideo(videoId);
  }
}




이제 다시 빌드한다.

> ionic cordova build android


YoutubeVideoPlayer 플러그인의 문제인지 여기서 빌드중 오류가 발생한다.

경로를 자세히 보면 저 위치에 config.xml 파일은 없다. 위치를 추측 해보면 ./platforms/android/app/src/main/res/xml/config.xml으로 예상되는데...


빌드시 이 경로와 필요한 라이브러리경로 설정을 위해 다음 두 파일을 수정해야한다.


./platforms/android/cordova/Api.js를 열어 아래 표시한 다음 두 라인(if문)을 주석처리 한다. 

var self = this; this.locations = { root: self.root, www: path.join(self.root, 'assets/www'), res: path.join(self.root, 'res'), platformWww: path.join(self.root, 'platform_www'), configXml: path.join(self.root, 'res/xml/config.xml'), defaultConfigXml: path.join(self.root, 'cordova/defaults.xml'), strings: path.join(self.root, 'res/values/strings.xml'), manifest: path.join(self.root, 'AndroidManifest.xml'), build: path.join(self.root, 'build'), javaSrc: path.join(self.root, 'src'), // NOTE: Due to platformApi spec we need to return relative paths here cordovaJs: 'bin/templates/project/assets/www/cordova.js', cordovaJsSrc: 'cordova-js-src' }; // XXX Override some locations for Android Studio projects //if (AndroidStudio.isAndroidStudioProject(self.root) === true) { selfEvents.emit('log', 'Android Studio project detected'); this.builder = 'studio'; this.android_studio = true; this.locations.configXml = path.join(self.root, 'app/src/main/res/xml/config.xml'); this.locations.strings = path.join(self.root, 'app/src/main/res/values/strings.xml'); this.locations.manifest = path.join(self.root, 'app/src/main/AndroidManifest.xml'); // We could have Java Source, we could have other languages this.locations.javaSrc = path.join(self.root, 'app/src/main/java/'); this.locations.www = path.join(self.root, 'app/src/main/assets/www'); this.locations.res = path.join(self.root, 'app/src/main/res'); //}


어찌된 일인지 Youtube Player 플러그인을 설치하면 빌드 경로를 Android Studio 빌드 환경에 맞게 맞춰야 하는가보다.


이 상태에서 다시 빌드를 수행하면 YouTubeBaseActivity, YoutubeIntents등 라이브러리를 찾을 수 없다는 컴파일 오류가 발생하며 또 빌드 실패

이유는 YouTubeAndroidPlayerApi.jar, openyoutubeactivity.jar 두개의 라이브러리를 역시 경로 오류로 찾지 못함이다.


./platforms/android/app/build.gradle을 열어 위 두개 라이브러리의 dependency를 추가한다. dependencies의 위치는 약 258라인 정도에 있다.

dependencies {

implementation fileTree(dir: 'libs', include: '*.jar') implementation fileTree(dir: 'src/main/libs', include: '*.jar') // SUB-PROJECT DEPENDENCIES START implementation(project(path: ":CordovaLib")) // SUB-PROJECT DEPENDENCIES END }


이제 platforms/android/libs 하위에 있는 두 라이브러리 YouTubeAndroidPlayerApi.jar 와  openyoutubeactivity.jar 를 platforms/android/app/src/main/libs 하위에 복사하여 넣는다.


다시 빌드

> ionic cordova build android

빌드 성공했길 바라며, 폰에 배포하여 테스트 해보자





이 글의 소스코드는 아래에서

https://github.com/lugam/ionic-youtube-exam


Github에서 소스를 내려받은 경우라면 빌드 오류가 발생할 것이다. 
이 글의 빌드 오류 수정 방법을 진행해보자.


728x90

'IONIC' 카테고리의 다른 글

Ionic - QR Code Creation (ngx-qrcode) Example  (0) 2018.05.14
Ionic - QR Code Scan Example  (0) 2018.05.11
Ionic - Native Google Map Example  (0) 2018.05.04
Ionic - 설치 및 새로운앱 시작  (0) 2018.05.02