2014-11-23 79 views
4

我想在Amazon Fire TV的WebView中播放YouTube视频。如何在Amazon Fire TV上的WebView中播放YouTube视频?

截至今日,在Fire OS上没有用于播放YouTube视频的官方API(link),所以我试图让它与Android的WebView一起工作。在Android WebView文档中写道,应用程序需要启用硬件加速,并且WebView需要具有WebChromeClient才能播放YouTube视频。

我试图让它工作,但当我开始一个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

我写了一个类来播放消防电视上YouTube视频,它也适用于Kindle Fire的为好。如你所知,Youtube没有官方的api,我们不得不求助于使用网页浏览。我在这里粘贴的课程除了网页浏览之外还有很多你可能会好奇的内容,所以我会解释一下。首先,你会发现,当你离开你的活动时,除非你让它停止,否则YouTube播放的webview将继续播放。因此,人们告诉其他人的解决方案是使用onPause和pauseTimers方法来关闭视频。但是亚马逊强加给我们的是一个令人讨厌的问题,那就是音频和视频资源没有发布到操作系统的其他部分(而不是Google Android Lolipop即Nexus Player的问题)。当资源被您的应用程序占用时,主要视频将无法播放,亚马逊不会允许您的应用程序在商店中播放。他们知道织补好,我们必须使用网页视图YouTube的,所以他们给了我们建议的这一点点:

问:我可以使用Android的WebView和视频播放 HTML标记?
答:是的,有局限性。当您的应用暂停或停止时,硬件媒体资源不是当前由系统发布的 。要 工作解决此问题,实现你的onStop()方法来明确 杀死你的应用程序的过程:

Amazon source

像AVGN会说:“他们在想什么?”

你不会相信如何强制杀死一个应用程序或活动会导致大量的问题..以及我相信你这样做,因为你得到了比我多几千点。

我能找到的唯一解决方案是在onPause方法中加载一个很短的720p高清片段(必须有音频!)。我将它与webView.onPause和.pauseTimers结合起来以确保...

如果您使用此类,请将我的blank.mp4文件复制到您自己的服务器上,因为它可能在一个月内不存在。

哦,但还有更多。所以你在你的webView中获得你的YouTube文件...一块蛋糕吧?错误,它不会播放,因为在webViews中,Html5通常不会自动播放。你不能设置网址自动播放它没有任何区别。所以我的解决方案是使用Java欺骗来强制点击。它的工作方式是webview不会立即加载,它需要花费不同的时间来完全加载。之后,视频在屏幕中央显示一个播放按钮图标。小遥控器出于某种原因不能触摸它。但是我在代码中强制在webview的中心点击一下。

哦,还有一件事,你必须处理音频焦点或亚马逊不会让你的应用程序在商店。潘多拉可以在后台玩,除非你处理。

为什么亚马逊为什么

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。 https://developers.google.com/youtube/android/player/ – 2015-07-07 01:26:42

+0

你是否在Fire TV上使用过它? – Ohiovr 2015-07-07 01:27:26

1

有趣的是,我的第一个答案并回答如何与网页视图做,但我发现别人的解决方案,它具有使用videoView很多潜在的问题。讽刺的是,我发现它从有机磷农药的一个链接:

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

不像我的解决了这个自动播放。主视频不受影响。可能还有其他一些粗糙的边缘,但这很有效。

+0

实际上这可能违反了YouTube的服务条款 – Ohiovr 2015-07-08 21:25:35

相关问题