2014-11-23 2 views
4

Amazon Fire TV 용 WebView에서 YouTube 비디오를 재생하고 싶습니다.Amazon Fire TV에서 WebView로 YouTube 비디오를 재생하는 방법은 무엇입니까?

오늘부터 Fire OS (link)에서 YouTube 동영상을 재생할 수있는 공식 API가 없으므로 Android의 WebView에서 작동하도록했습니다. Android WebView 문서에는 앱에 하드웨어 가속 기능이 설정되어 있어야하며 YouTube 비디오를 재생하기 위해 WebView에 WebChromeClient가 있어야한다는 문서가 작성되었습니다.

나는 그것을 얻으려고했지만 YouTube 비디오를 시작할 때 전체 화면 모드 로딩 스피너 만 보는 것보다. 내가 불 TV에 YouTube 동영상을 재생하는 클래스를 작성했습니다

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    WebView webview = new WebView(this); 
    setContentView(webview); 

    webview.getSettings().setBuiltInZoomControls(true); 
    webview.getSettings().setJavaScriptEnabled(true); 
    webview.setWebChromeClient(new WebChromeClient() { 

    @Override 
    public void onShowCustomView(View view, CustomViewCallback callback) { 
     Log.i("fire-tv", "Show custom view"); 

     super.onShowCustomView(view, callback); 
     if (view instanceof FrameLayout) { 
     FrameLayout frame = (FrameLayout) view; 
     if (frame.getFocusedChild() instanceof VideoView) { 
      VideoView video = (VideoView) frame.getFocusedChild(); 
      frame.removeView(video); 
      setContentView(video); 
      video.start(); 
     } 
     } 
    } 

    @Override 
    public void onHideCustomView() { 
     Log.i("fire-tv", "Hide custom view."); 
    } 

    }); 

    webview.setWebViewClient(new WebViewClient() { 

    @Override 
    public boolean shouldOverrideUrlLoading(WebView view, String url) { 
     return false; 
    } 

    }); 

    final String mimeType = "text/html"; 
    final String encoding = "UTF-8"; 
    String html = getHTML(); 

    Log.i("fire-tv", "Loading: " + html); 
    webview.loadDataWithBaseURL("", html, mimeType, encoding, ""); 
} 

private String getHTML() { 
    String html = "<iframe class=\"youtube-player\" style=\"border: 0; width: 100%; height: 100%; padding:0px; margin:0px\" id=\"ytplayer\" type=\"text/html\" src=\"http://www.youtube.com/embed/" 
      + "h11u3vtcpaY" 
      + "?fs=0\" frameborder=\"0\">\n" 
      + "</iframe>\n"; 

    return html; 
} 

답변

1

그리고 그것은 또한뿐만 아니라 킨들 파이어 (Kindle Fire)에서 작동 :

여기 내 코드입니다. 아시다시피 Youtube에는 공식 API가 없으므로이를 위해 webview를 사용해야합니다. 여기에 붙여 넣은 수업에는 내가 궁금해 할 웹 뷰 외에도 많은 것들이 있습니다. 그래서 설명하겠습니다. 무엇보다도 YouTube 재생중인 웹보기는 멈추라 고하지 않는 한 활동을 떠날 때 계속 재생됩니다. 따라서 사람들이 다른 사람들에게 말하는 해결책은 onPause 및 pauseTimers 메서드를 사용하여 비디오를 종료하는 것입니다. 그러나 아마존이 우리에게 강요하는 불쾌한 문제가 있습니다. 오디오 및 비디오 리소스가 나머지 운영 체제 (Google Android Lolipop 즉 Nexus Player와 관련된 문제는 아님)로 배포되지 않습니다. 리소스가 앱에 의해 보유되면 프라임 비디오는 재생되지 않으며 아마존은 앱을 스토어에서 허용하지 않습니다. 그들은 우리가 YouTube에 webviews을 사용해야 잘 꿰매 그래서 그들은 우리에게 조언이 조금 준 알고 :

Q를 : 내가 안드로이드 웹보기 및 비디오 재생을위한 HTML 태그를 사용할 수 있습니까?
A : 예, 제한 사항이 있습니다. 앱이 일시 중지되거나 중지 될 때 하드웨어 미디어 리소스가 시스템에서 현재 해제 한 이 아닙니다. 이 문제를 해결 작업에 명시 적으로 앱에 대한 프로세스를 죽일 이동 중지() 메소드를 구현 : AVGN처럼

Amazon source

은 말할 것 "무엇 그들은 생각했다을?"

당신이 앱이나 활동을 강제로 죽이는 것이 얼마나 많은 문제를 일으키는 지 믿지 못할 것입니다. 당신이 할 수 있다고 확신합니다. 당신이 나 자신보다 몇 천 포인트를 더 많이 가지고 있기 때문입니다.

유일한 해결책은 onPause 메서드에서 매우 짧은 720p HD 클립 (오디오가 있어야 함)을로드하는 것입니다. 나는 webView.onPause와 .pauseTimers를 결합하여 확실하게 ...

이 클래스를 사용하는 경우 한 달 안에 없을 수도 있기 때문에 내 blank.mp4 파일을 자신의 서버에 복사하십시오.

아, 더 있습니다. 그래서 당신은 귀하의 webView에서 귀하의 YouTube 파일을 얻을 ... 케이크 조각 맞지? 틀렸어, WebViews에서는 Html5가 자동으로 재생되지 않기 때문에 재생되지 않습니다. 자동 실행 URL을 설정할 수 없으므로 아무런 차이가 없습니다. 그래서 내 해결책은 자바 속임수를 사용하여 강제로 클릭하는 것이었다. 작동 방식은 webview가 즉시 로딩되지 않는다는 것입니다. 웹 뷰가 완전히로드되기까지 소요되는 시간은 다양합니다. 그 후에 비디오는 화면 가운데에 재생 버튼 아이콘을 표시합니다. 작은 리모컨은 어떤 이유로 그것을 만질 수 없습니다. 그러나 웹 뷰의 중심에 클릭을 강제로 삽입하는 코드를 작성했습니다.

아, 한 가지 더 있습니다. 오디오 포커스를 처리해야합니다. 그렇지 않으면 amazon에서 앱을 허용하지 않습니다. 판도라는 당신이 그것을 다룰 때까지 백그라운드에서 플레이 할 수 있습니다.

package com.ohiovr.modules.youtube; 


import android.app.Activity; 
import android.content.Context; 
import android.content.pm.ActivityInfo; 
import android.graphics.Point; 
import android.media.AudioManager; 
import android.os.Bundle; 
import android.os.SystemClock; 
import android.util.Log; 
import android.view.Display; 
import android.view.KeyEvent; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.WindowManager; 
import android.webkit.WebChromeClient; 
import android.webkit.WebSettings; 
import android.webkit.WebView; 
import android.webkit.WebViewClient; 

import java.util.Timer; 
import java.util.TimerTask; 



public class youtubeKindleWebView extends Activity { 


    String StringYoutubeUrl; 
    WebView webView; 

    AFChangeListener hocusFocus; 
    private String videoBlanker = "http://ohiovr.com/church_files/blank.mp4"; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_generic_web_view); 

     setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 

     webView = (WebView) findViewById(R.id.webView); 
     WebSettings webSettings = webView.getSettings(); 
     webSettings.setBuiltInZoomControls(true); 
     webSettings.setJavaScriptEnabled(true); 
     webSettings.setAppCacheEnabled(false); 
     webSettings.setLoadWithOverviewMode(true); 
     webSettings.setUseWideViewPort(true); 
     //I used this line in an old and now not used live stream implimentation. It works so I didn't remove it. But you may 
     //want to see if it is nessisary: 
     webSettings.setUserAgentString("Mozilla/5.0(iPhone;U;CPUiPhoneOS4_0likeMacOSX;en-us)AppleWebKit/532.9(KHTML,likeGecko)Version/4.0.5Mobile/8A293Safari/6531.22.7"); 


     webView.setWebViewClient(new Callback()); 
     webView.setWebChromeClient(new WebChromeClient()); 


    } 

    class AFChangeListener implements AudioManager.OnAudioFocusChangeListener { 
     @Override 
     public void onAudioFocusChange(int focusChange) { 
      if (focusChange == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT) { 
       // mp.pause(); 
      } else if (focusChange == AudioManager.AUDIOFOCUS_GAIN) { 
       // mp.start(); 
      } else if (focusChange == AudioManager.AUDIOFOCUS_LOSS) { 
       // mp.stop(); 
      } 
     } 
    } 

    @Override 
    public boolean onKeyDown(int keyCode, KeyEvent event) { 
     boolean handled = false; 

     switch (keyCode) { 
      case KeyEvent.KEYCODE_DPAD_CENTER: 
       forceAClick(); 
       break; 
      case KeyEvent.KEYCODE_BUTTON_A: 
       // ... handle selections 
       handled = true; 
       break; 
      case KeyEvent.KEYCODE_DPAD_LEFT: 
       // ... handle left action 
       handled = true; 
       break; 
      case KeyEvent.KEYCODE_DPAD_RIGHT: 
       // ... handle right action 
       handled = true; 
       break; 
     } 
     return handled || super.onKeyDown(keyCode, event); 
    } 


    public void forceAClick() { 

     Timer timer = new Timer(); 
     timer.schedule(new TimerTask() { 
      @Override 
      public void run() { 
       runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
         Display display = getWindowManager().getDefaultDisplay(); 
         Point size = new Point(); 
         display.getSize(size); 
         int width = size.x; 
         int height = size.y; 


         // Obtain MotionEvent object 
         long downTime = SystemClock.uptimeMillis(); 
         long eventTime = SystemClock.uptimeMillis() + 100; 
         float x = width/2; 
         float y = height/2; 
         // List of meta states found here: developer.android.com/reference/android/view/KeyEvent.html#getMetaState() 
         int metaState = 0; 
         MotionEvent motionEvent = MotionEvent.obtain(
           downTime, 
           eventTime, 
           MotionEvent.ACTION_DOWN, 
           x, 
           y, 
           metaState 
         ); 

         webView.setOnTouchListener(new View.OnTouchListener() { 
          @Override 
          public boolean onTouch(View v, MotionEvent event) { 
           Log.d("on touch", "touched down"); 
           return false; 
          } 
         }); 

         webView.dispatchTouchEvent(motionEvent); 
        } 
       }); 
      } 
     }, 1); 

     timer.schedule(new TimerTask() { 
      @Override 
      public void run() { 
       runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 
         Display display = getWindowManager().getDefaultDisplay(); 
         Point size = new Point(); 
         display.getSize(size); 
         int width = size.x; 
         int height = size.y; 


         // Obtain MotionEvent object 
         long downTime = SystemClock.uptimeMillis(); 
         long eventTime = SystemClock.uptimeMillis() + 100; 
         float x = width/2; 
         float y = height/2; 
         // List of meta states found here: developer.android.com/reference/android/view/KeyEvent.html#getMetaState() 
         int metaState = 0; 
         MotionEvent motionEvent = MotionEvent.obtain(
           downTime, 
           eventTime, 
           MotionEvent.ACTION_UP, 
           x, 
           y, 
           metaState 
         ); 

         webView.setOnTouchListener(new View.OnTouchListener() { 
          @Override 
          public boolean onTouch(View v, MotionEvent event) { 
           Log.d("on touch", "touched up"); 
           return false; 
          } 
         }); 

         webView.dispatchTouchEvent(motionEvent); 


        } 
       }); 
      } 
     }, 120); 


     AudioManager am = (AudioManager) this.getSystemService(Context.AUDIO_SERVICE); 
// Request audio focus for playback 
     hocusFocus = new AFChangeListener(); 
     int result = am.requestAudioFocus(hocusFocus, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); 
    } 


    @Override 
    public void onResume() { 
     super.onResume(); 
     webView.onResume(); 
     webView.resumeTimers(); 
     StringYoutubeUrl = "https://www.youtube.com/embed/" + getIntent().getStringExtra("youtubeID"); 
     webView.loadUrl(StringYoutubeUrl); 
     getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); 

    } 


    private class Callback extends WebViewClient { //this is important for some reason. don't remove! 
     @Override 
     public boolean shouldOverrideUrlLoading(WebView view, String url) { 
      return (false); 
     } 
    } 


    @Override 
    protected void onPause() { 
     super.onPause(); 

     webView.loadUrl(videoBlanker); 
     webView.pauseTimers(); 
     webView.onPause(); 
    } 



    /* 
    Q: Can I use an Android WebView and the <video> HTML tag for video playback? 
    A: 
    Yes, with limitations. Hardware media resources are not currently released by the system when your app pauses or stops. To work around this issue implement your onStop() method to explicitly kill the process for your app: 

    https://developer.amazon.com/public/solutions/devices/fire-tv/docs/amazon-fire-tv-sdk-frequently-asked-questions 
    public void onStop() { 
     super.onStop(); 
     android.os.Process.killProcess(android.os.Process.myPid()); 
    } 
    This issue may also cause instability in the user experience and navigation for your app. The VisualOn SDK is the recommended method for media playback on the device. 
    */ 

    @Override 
    protected void onStop() { 
     super.onStop(); 
     // the fascinating part of the next line is that it doesn't kill the application, only this intent 
     ///////////// android.os.Process.killProcess(android.os.Process.myPid()); 
     //no no no! Amazon's advice is bad. It causes a ton of problems. 
     //the original problem was that the webview video view frankenhybrid wouldn't release the 
     //hardware when the user left the video player. 
     //the only and correct solution is to load a very short quiet clip into the webview 
     //when the user leaves 
     //see onPause for my implementation 

    } 


} 
+1

FYI Youtube에는 API가 있습니다. Fire TV에서 https://developers.google.com/youtube/android/player/ –

+0

을 사용하셨습니까? – Ohiovr

1

재미 있은 것은 왜 아마존, 내 첫 번째 대답은 웹보기와 함께 할하지만 난 VideoView를 지켜 보면서을 사용하여 많은 잠재력을 가지고 다른 사람의 해결책을 발견하는 방법에 대한 질문에 대답 않는 이유

. 아이러니하게도 나는 작전 중 하나에서 그것을 발견 링크 : 내 솔루션과는 달리

https://github.com/kslazarev/android-youtube-player

이 자동으로 재생됩니다. 프라임 비디오는 영향을받지 않습니다. 어쩌면 몇 가지 다른 거친 모서리가있을 수 있지만 매우 잘 작동합니다.

+0

실제로 이것은 YouTube의 서비스 약관을 위반할 수 있습니다. – Ohiovr

관련 문제