我想在亚马逊Fire TV的WebView中播放YouTube视频。
到目前为止,还没有在Fire OS (link)上播放YouTube视频的官方应用程序接口,所以我尝试让它在安卓的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;
}发布于 2015-07-07 08:05:38
我写了一个在Fire TV上播放youtube视频的类,它也可以在kindle fire上运行。正如你所知道的,Youtube没有官方的api,为此我们不得不求助于webviews。我在这里粘贴的类除了webview之外还有很多东西,你可能会很好奇,所以我会解释一下。首先,你会发现当你离开你的活动时,一个播放webview的YouTube将会继续播放,除非你告诉它停止。因此,人们告诉其他人的解决方案是使用onPause和pauseTimers方法来关闭视频。但是有一个令人讨厌的问题是亚马逊强加给我们的,那就是音频和视频资源没有发布到操作系统的其余部分(这不是Google Android Lolipop Player的问题)。当资源由你的应用程序持有时,优质视频将不会播放,亚马逊将不允许你的应用程序出现在商店中。他们非常清楚我们必须在youtube上使用webviews,所以他们给了我们一些建议:
问:我可以使用安卓WebView和HTML来播放视频吗?
答:是的,有限制。当你的应用暂停或停止时,系统当前不会释放硬件媒体资源。要解决此问题,请实现onStop()方法以显式终止应用程序的进程:
就像AVGN会说“他们在想什么?”
你不会相信仅仅是强行杀死一个应用程序或活动会导致大量的问题。我相信你会的,因为你比我多得几千分。
我能找到的唯一解决方案是加载一个非常短的720p高清剪辑(必须有音频!)在onPause方法中。我将它与webView.onPause和.pauseTimers结合起来以确保...
如果您使用这个类,请将我的blank.mp4文件复制到您自己的服务器上,因为它可能在一个月后就不存在了。
哦,但还有更多。所以你在你的webView中得到了你的YouTube文件...小菜一碟对吧?错了,它不能播放,因为在webViews中,Html5通常不会自动播放。您不能将url设置为自动播放,这没有任何区别。所以我的解决方案是使用java的技巧来强制点击。它的工作方式是webview不会立即加载,它需要不同的时间才能完全加载。之后,视频会在屏幕中央显示一个播放按钮图标。因为某些原因这个小遥控器不能触摸它。但是我在代码中强制点击了网页视图的中心。
哦,还有一件事,你必须处理音频聚焦,否则亚马逊将不允许你的应用程序进入商店。除非你处理好,否则Pandora可以在后台播放。
为什么是亚马逊为什么
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
}
}发布于 2015-07-07 21:39:39
有趣的是,我的第一个答案确实回答了如何使用webview的问题,但我发现其他人的解决方案使用videoView有很大的潜力。具有讽刺意味的是,我是从其中一个操作链接中找到它的:
https://github.com/kslazarev/android-youtube-player
与我的解决方案不同,它会自动播放。Prime视频不受影响。也许还有其他一些粗糙的边缘,但这个工作得很好。
https://stackoverflow.com/questions/27095552
复制相似问题